/*
 Theme Name:   Astra Child
 Theme URI:    https://wpastra.com/
 Description:  Astra Child Theme
 Author:
 Author URI:
 Template:     astra
 Version:      1.0.0
 License:      GNU General Public License v2 or later
 License URI:  http://www.gnu.org/licenses/gpl-2.0.html
 Text Domain:  astra-child
*/

/* ---------------------------------------------------------------
   Spec tables (Container + Heading/Text-Editor widgets built to
   look like a table -- a label/value row per Container for most
   product pages, or a 3-column matrix for O-Ring's Material
   Selection). Elementor has no native "Table" control that
   produces this shape from the existing widget content, and no
   control for per-cell background/alternating-row shading on a
   Container-based layout, so this stays in the stylesheet per
   project convention. Class applied via Advanced > CSS Classes:
   "tcr-spec-table" on the outer wrapper container (plus
   "tcr-spec-table-cols" additionally for the O-Ring 3-column
   matrix table).
   Source: tcr-styles.css .spec-table / .spec-table-cols /
   .spec-table-wrap. Padding and border-bottom on each row were
   already correctly set via native Elementor controls (verified
   in the compiled CSS) -- only caption/header background, the
   label-column background, and alternating row shading were
   missing.
--------------------------------------------------------------- */
/* Bugfix (all spec tables, sitewide): each table's row container had
   its native flex Gap left at Elementor's default (20px column gap),
   which put a literal 20px white gap between every row -- breaking
   the label column's gray background into separate floating chips
   instead of one continuous bar flush top-to-bottom, per the
   prototype (.spec-table has zero gap; rows are separated only by
   the thin border-bottom already set natively on each row). */
.tcr-spec-table > .e-con-inner {
  gap: 0 !important;
}
.tcr-spec-table > .e-con-inner > .elementor-widget-heading:first-child {
  background: var(--steel-100, #F5F6F7);
  padding: 18px 22px;
  border-bottom: 1px solid var(--steel-200, #E5E7E9);
}
.tcr-spec-table > .e-con-inner > .elementor-widget-heading:first-child .elementor-heading-title {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink, #1F2429);
}
/* Bugfix (all 7 product pages): each row Container's own native
   padding (14px vertical, 22px horizontal) and align-items:flex-start
   were left at Elementor's defaults, stacking on top of the label
   heading's own 14px/22px padding below and keeping it from reaching
   the row's full height -- this is what read as a small floating
   gray "chip" instead of a full-height table-cell background
   flush to the table's edges, per the prototype. The native rule
   and this override tie at 3 classes each
   (.elementor-22 .elementor-element.elementor-element-{id} vs
   .tcr-spec-table > .e-con-inner > .e-con), and the native rule
   loads after this stylesheet, so !important is needed to win. */
.tcr-spec-table > .e-con-inner > .e-con {
  --padding-top: 0px !important;
  --padding-bottom: 0px !important;
  --padding-left: 0px !important;
  --padding-right: 0px !important;
  --align-items: stretch !important;
}
.tcr-spec-table > .e-con-inner > .e-con:last-child {
  border-bottom: none;
}
.tcr-spec-table > .e-con-inner > .e-con:hover {
  background: var(--paper-soft, #FAFBFB);
}
.tcr-spec-table > .e-con-inner > .e-con > .e-con-inner {
  padding: 0;
}
.tcr-spec-table:not(.tcr-spec-table-cols) > .e-con-inner > .e-con > .e-con-inner > .elementor-widget-heading:first-child {
  background: var(--steel-100, #F5F6F7);
  flex: 0 0 220px;
  padding: 14px 22px;
  font-weight: 600;
  white-space: nowrap;
}
/* Bugfix (all 7 product pages): the value cell (Text Editor widget)
   never had flex-grow set, so it only ever took its own content's
   natural width instead of stretching to fill the rest of the row --
   this left a large blank gap on the right inside the table's own
   border, varying in size per row depending on how long that row's
   text happened to be (confirmed: 634px value cell inside a 1140px
   row, a 285px unexplained gap, on the Fasteners for Plastic Screw
   Configuration table). A real HTML <td> fills its remaining column
   width automatically; this Container-based row needs it set
   explicitly since flex children default to flex-grow:0. */
.tcr-spec-table:not(.tcr-spec-table-cols) > .e-con-inner > .e-con > .e-con-inner > .elementor-widget-text-editor {
  padding: 14px 22px;
  flex-grow: 1;
  min-width: 0;
}
.tcr-spec-table-cols > .e-con-inner > .e-con:first-of-type {
  background: var(--steel-100, #F5F6F7);
}
.tcr-spec-table-cols > .e-con-inner > .e-con:first-of-type > .e-con-inner > .elementor-widget-heading {
  padding: 14px 22px;
  font-weight: 600;
  text-transform: uppercase;
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--ink, #1F2429);
}
.tcr-spec-table-cols > .e-con-inner > .e-con:not(:first-of-type) > .e-con-inner > * {
  padding: 14px 22px;
}
.tcr-spec-table-cols > .e-con-inner > .e-con:not(:first-of-type):nth-child(even) {
  background: var(--paper-soft, #FAFBFB);
}
/* Bugfix (O-Ring audit): the two ":first-of-type" rules above never
   actually match anything. :first-of-type matches by TAG NAME across
   ALL siblings, not scoped to the .e-con class -- since the "Material
   Selection" caption heading widget is also a <div> and comes first,
   it claims the real first-of-type slot, so no .e-con ever qualifies.
   Effect: the 3-column header row (Material / Temperature Range /
   Application) fell through to the alternating-row rule directly
   above instead of getting the intended steel-100 highlight, and
   rendered var(--paper-soft) instead. Fixed by targeting the .e-con
   that immediately follows the caption heading, which is the actual
   header row. Placed after the alternating rule on purpose: both
   selectors are equal specificity, and source order is the
   tie-breaker, so this one must come last to win. */
.tcr-spec-table-cols > .e-con-inner > .elementor-widget-heading:first-child + .e-con {
  background: var(--steel-100, #F5F6F7);
}
/* Improvement (O-Ring Material Selection table): each row's 3 cells
   (Material / Temperature Range / Application) had no width rule at
   all, so every cell auto-sized to its own content -- "Viton" (short)
   left its row's 2nd/3rd columns starting well left of where
   "Ethylene Propylene Rubber (EPR)" (long) pushed the same columns
   on its own row, so nothing lined up into clean vertical gridlines
   the way a real table's columns do. Giving columns 1 and 2 a fixed
   width (consistent across every row, including the header) and
   letting column 3 absorb the remainder produces actual aligned
   columns instead of per-row auto-sizing. */
.tcr-spec-table-cols > .e-con-inner > .e-con > .e-con-inner > *:nth-child(1) {
  flex: 0 0 200px !important;
}
.tcr-spec-table-cols > .e-con-inner > .e-con > .e-con-inner > *:nth-child(2) {
  flex: 0 0 180px !important;
}
.tcr-spec-table-cols > .e-con-inner > .e-con > .e-con-inner > *:nth-child(3) {
  flex: 1 1 auto !important;
  min-width: 0 !important;
}

/* ---------------------------------------------------------------
   Product detail "Overview" image (Image widget, class applied
   via Advanced > CSS Classes: "tcr-overview-img"). All 7 product
   detail pages render this widget at the uploaded image's native
   pixel size (259x259 or 800x800 -- square, object-fit:cover),
   which crops the technical line-art diagrams instead of showing
   them in full. The Image widget has no native aspect-ratio-lock
   + object-fit combo control that stays responsive across viewport
   widths, so this stays in the stylesheet per project convention.
   Source: tcr-styles.css .overview-img + .overview-img-contain
   (combined class in the prototype: aspect-ratio 4/3, contain,
   white background, 1px steel-200 border, 6px radius).

   !important on height/object-fit: Elementor's own frontend.css
   ships ".elementor img { height:auto }", same specificity (one
   class + tag) as our rule below. When a page's Image widget has
   no explicit per-widget height/object-fit override, the cascade
   tie is broken by stylesheet load order, and Elementor's sheet
   loads after this one -- so "height:auto" silently wins and the
   image renders at its native aspect ratio inside the clipped 4:3
   box instead of being contained. Confirmed on the Fasteners for
   Plastic page (post 22) 2026-07-28 after clearing that widget's
   stale per-element height:600/object-fit:cover. No native control
   raises this rule's specificity, so !important is used here only
   to win that specific tie, not as a general shortcut.
--------------------------------------------------------------- */
.tcr-overview-img {
  aspect-ratio: 4 / 3;
  background: #fff;
  border: 1px solid var(--steel-200, #E5E7E9);
  border-radius: 6px;
  overflow: hidden;
  width: 100% !important;
}
.tcr-overview-img img {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important;
}
/* ---------------------------------------------------------------
   Overview image's containing column, all 7 product pages. Each
   page's sticky column wrapping this widget carries its OWN native
   border+padding+radius (identical values to .tcr-overview-img's
   own border), which duplicates the box as a second, larger
   rectangle around the first, and the 20px padding plus
   align-items:center (not stretch) on that flex column keeps the
   image widget from ever growing to fill the column -- it shrinks
   to its content size instead, well under the design's full-column
   width. The wrapper has no shared class to hook (each page's is a
   separately-configured native Container), so this uses :has() to
   reach it structurally instead of touching 7 pages individually.
--------------------------------------------------------------- */
.e-con:has(> .tcr-overview-img) {
  border: none !important;
  padding: 0 !important;
  border-radius: 0 !important;
}

/* ---------------------------------------------------------------
   Fluid sub-hero title sizing. Elementor's responsive typography
   control only offers three fixed breakpoints, not true fluid
   clamp() scaling, so the interior sub-hero title uses this class
   instead of literal per-breakpoint font sizes.
   Source: design-system.md §2.3 (tcr-styles.css .subhero-title)

   Bug fix (widget-vs-text-node mismatch): this class is applied via
   Advanced > CSS Classes, which always lands on the WIDGET WRAPPER
   div, not the inner <h1>/.elementor-heading-title it visually
   contains. font-size inherits by default, so this rule "worked" on
   the wrapper (confirmed via computed style: 76px) while the actual
   visible heading text stayed stuck at whatever the widget's own
   Typography control resolves to (--e-global-typography-h1-font-size,
   48px) -- every page using this class was affected, since each
   product/interior page generates its own per-widget compiled rule
   (e.g. ".elementor-element-fp00004 .elementor-heading-title") at
   the same specificity, loaded after astra-child's stylesheet, so it
   won the cascade tie. Added the explicit descendant selector +
   !important to actually reach and win against that text node.
--------------------------------------------------------------- */
.tcr-subhero-title,
.tcr-subhero-title .elementor-heading-title {
  font-size: clamp(48px, 5.8vw, 76px) !important;
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: #fff;
  margin: 0;
  max-width: 20ch;
}
/* Shorter variant used on the Contact page's reduced-height sub-hero */
.tcr-subhero-title--sm,
.tcr-subhero-title--sm .elementor-heading-title {
  font-size: clamp(44px, 5.6vw, 76px) !important;
}

/* ---------------------------------------------------------------
   Home "Backed by Gexpro Services" logo carousel. The core Image
   Carousel widget only offers a binary Image Stretch toggle
   (width:100%, no height/object-fit pairing) -- there is no native
   control to cap every slide image to one consistent contained
   height regardless of each logo's native aspect ratio, which is
   what caused the partner logos to render at inconsistent sizes.
   Source: user-reported defect, home-companies-strip carousel.
--------------------------------------------------------------- */
.elementor-element-hm00022 .swiper-slide-image {
  width: auto;
  height: 56px;
  max-width: 100%;
  object-fit: contain;
  margin: 0 auto;
}

/* ---------------------------------------------------------------
   Full-bleed content wrapper. Astra's theme-level `.ast-container`
   wraps every Elementor-templated page's content area at
   max-width:1240px plus 20px side padding (1200px usable),
   regardless of each Container widget's own Content Width setting.
   Elementor's "Full Width" containers (`.e-con-full`) render at
   width:100% of *this* wrapper, so every hero/subhero background
   across the site was invisibly capped to 1200px instead of
   genuinely reaching the viewport edge. Even "Boxed" containers
   (`.e-con-boxed`) were affected: they correctly declare
   --content-width:1240px per the design system (verified in the
   compiled per-page CSS), but were being pre-clipped to 1200px by
   this same wrapper before that max-width ever had a chance to
   apply. Verified via computed styles/parent-chain inspection on
   the Fasteners for Plastic subhero: #fp-subhero rendered at
   exactly 1200px wide with 0 margin, nested inside .ast-container
   (max-width:1240px, 20px+20px padding).
   Source: hero/subhero full-bleed defect, sitewide (all 13 pages
   share the same elementor_header_footer template).
--------------------------------------------------------------- */
.page-template-elementor_header_footer .ast-container {
  max-width: none;
  padding-left: 0;
  padding-right: 0;
}

/* ---------------------------------------------------------------
   Home hero max-height cap. The Container widget's native Min
   Height control (--min-height:92vh) has no matching Max Height
   control -- the prototype's hero uses min-height:640px combined
   with max-height:920px so it stops growing on tall viewports; the
   WordPress build had min-height:92vh with no ceiling, so on a tall
   monitor the hero grows well past the prototype's capped size and
   pushes the whole page down. Verified via computed styles on the
   prototype (.hero.hero-single: min-height:640px, max-height:920px).

   Follow-up bug fix: the first pass only added a min-height cap,
   which is still just a floor -- it stops the hero from shrinking
   below 920px but has no ceiling, so if the heading/content ever
   needed more vertical room than 920px (different viewport width,
   font rendering, etc.) the box would grow past it with nothing to
   stop it, unlike the prototype which sets max-height:920px AND
   overflow:hidden so it physically cannot exceed 920px -- any
   overflow gets cropped instead of growing the box. Adding both
   properties here to match exactly.

   Second follow-up bug fix: the prototype's <header> is
   position:fixed (102.8px tall) and overlaps the top of its hero,
   so the prototype's 640px/920px are the FULL page-top-to-hero-
   bottom span already. Our header is position:static (128.8px
   tall, confirmed via computed styles) and pushes the hero down
   instead of overlapping it, so matching 640/920 outright stacks
   the header ON TOP of that, making the combined hero taller than
   the prototype by a full header's height. Subtracting our header's
   128.8px from both bounds keeps the SAME total page-top-to-hero-
   bottom span as the prototype without touching header positioning
   sitewide (a much larger, riskier change).

   Third follow-up bug fix: the previous pass subtracted 128.8px from
   the prototype's two flat numbers (640/920) and hardcoded the
   results (511px/791px), which loses the fluidity those two numbers
   were capping in the first place -- the prototype's *actual*
   min-height is 92vh (confirmed via computed styles: renders at
   828px on a 900px-tall viewport, 920px on a 1000px-tall viewport,
   i.e. genuinely scales with viewport height up to the 920px
   ceiling), not a flat 640px. A flat 511px floor stops scaling
   with viewport height entirely, so on any viewport taller than
   ~700px the hero renders shorter than the prototype's, not just a
   little off by a fixed amount. calc() keeps the same 92vh growth
   and 920px ceiling, both minus the header's 128.8px, so the hero
   scales exactly like the prototype's at every viewport height
   instead of matching only the one height this was tested at.
--------------------------------------------------------------- */
.elementor-12 .elementor-element-hr0a1b2 {
  min-height: calc(92vh - 128.8px);
  max-height: calc(920px - 128.8px);
  overflow: hidden;
}

/* ---------------------------------------------------------------
   Interior-page sub-hero container height, ALL 11 non-home pages
   (About, Quality, Services, Contact, and all 7 product pages).
   Same root cause as the Home hero above, just never applied here:
   the Container widget's native Min Height control gives only a
   floor (min-height, no ceiling), while the prototype's .subhero
   uses a fixed height:420px with overflow:hidden -- a hard cap that
   crops any overflow instead of letting the box grow. Every one of
   these containers already carries a unique per-page id ending in
   "-subhero" (ab-subhero, ql-subhero, ct-subhero, sv-subhero,
   fp-subhero, etc. -- confirmed on 5 of the 11 pages, and the
   naming is generated by the same template pattern for the rest),
   so a single attribute selector covers all of them without
   depending on per-page element IDs. Deliberately does NOT match
   "-subhero-inner" or "-subhero-title" (those don't end in
   "-subhero"), and does not match the Home hero (id="home-hero").
   !important needed: each page's own compiled per-widget rule sets
   --min-height at the same specificity tier and loads after this
   stylesheet.

   Bugfix: same header-overlap issue as the Home hero above -- the
   prototype's 420px is the full page-top-to-subhero-bottom span
   (its position:fixed, 102.8px header overlaps the top of it), but
   our position:static, 128.8px header pushes the subhero down
   instead, so matching 420px outright stacks a full header's height
   on top of the prototype's already-complete span. Subtracting our
   header's 128.8px (420 - 128.8 = 291.2, rounded to 291px) keeps the
   same total span without changing header positioning sitewide.

   Third follow-up bug fix: `height` alone isn't enough here --
   each page's own compiled per-widget CSS also sets a native
   `min-height` (via `--min-height`, from the Container's Min
   Height control, originally 420px/360px to match the prototype's
   *un-subtracted* number). Per the CSS box model, min-height wins
   outright whenever it's larger than height, so leaving it in place
   silently re-inflated the box back to the old too-tall value even
   after height/max-height were corrected here. Overriding min-height
   to the same subtracted value closes that gap.
--------------------------------------------------------------- */
[id$="-subhero"] {
  height: 291px !important;
  min-height: 291px !important;
  max-height: 291px !important;
  overflow: hidden !important;
}
/* Bugfix: Contact's subhero is a shorter 360px variant in the
   prototype (every other interior page uses the standard 420px),
   but the blanket rule above applies to every "-subhero" id with no
   exception, so Contact was silently stretched to the standard
   height. #ct-subhero's ID specificity wins over the attribute
   selector above. Same header-overlap subtraction as above:
   360 - 128.8 = 231.2, rounded to 231px. */
#ct-subhero {
  height: 231px !important;
  min-height: 231px !important;
  max-height: 231px !important;
}

/* ---------------------------------------------------------------
   Product card (Home "Our Products" slider, Products Landing grid)
   photo/body divider. tcr-styles.css .prod-card-photo has its own
   border-bottom separating the image area from the icon/heading/
   description below -- but these cards were built as 4 flat
   sibling widgets (Image, icon+heading row, description, Read More
   link) with no dedicated "photo box" wrapper to put a native
   border on, so the divider was left off entirely. Targeting the
   first child (the Image widget) positionally since that's every
   card's actual photo area regardless of instance.
--------------------------------------------------------------- */
.tcr-prod-card > .e-con-inner > *:first-child {
  border-bottom: 1px solid var(--steel-200, #E5E7E9);
}

/* ---------------------------------------------------------------
   Product card (Home "Our Products" slider, Products Landing grid)
   horizontal padding. The card's own native Padding control applies
   one flat 10px left/right inset to all 4 sibling widgets uniformly
   (Image, icon+heading row, description, Read More link) -- but the
   prototype's image sits flush with the card edges (.prod-card-photo
   has no side inset) while its text content (icon+heading row,
   description, link) is inset 26px (.prod-card-body padding), a
   deliberately UNEVEN padding no single "Padding" value on the
   shared card container can produce. Zeroing the card's own padding
   restores the flush image, then re-adding 26px to every child
   except the first (the Image widget) matches the text inset
   without touching the image.
--------------------------------------------------------------- */
.tcr-prod-card {
  padding-left: 0 !important;
  padding-right: 0 !important;
}
.tcr-prod-card > .e-con-inner > *:not(:first-child) {
  padding-left: 26px;
  padding-right: 26px;
}

/* ---------------------------------------------------------------
   Bugfix: Home "Our Products" carousel card border vanishing on
   whichever slide the swiper happens to position at a fractional
   pixel offset. The card's 1px border is correct and identical on
   every card (native Elementor control, confirmed in loop-478.css)
   -- but Chrome anti-aliases a 1px line into near-invisibility when
   a `transform: translate3d(...)` lands it on a non-integer pixel,
   which the swiper does for every slide position except by chance.
   An inset box-shadow of the same width/color renders on top of the
   (still-present) border and Chrome rasterizes box-shadow more
   consistently under transforms, so the edge no longer disappears.
   !important needed: Elementor's own frontend.min.css sets
   `.elementor a { box-shadow: none; }` -- that 1-class+1-type
   selector beats this single-class selector on specificity alone,
   regardless of load order, silently discarding the box-shadow. */
a.tcr-prod-card {
  box-shadow: inset 0 0 0 1px var(--steel-200, #E5E7E9) !important;
}

/* ---------------------------------------------------------------
   Product card (Home "Our Products" slider, Products Landing grid)
   description + "Read More" link. Two bugs matching tcr-styles.css
   .prod-card-desc / .prod-card-link:
   1) The description (3rd child: image, icon+heading, description,
      link) had no flex-grow, so "Read More" sat directly under
      whatever text happened to be in that card -- different across
      cards with different description lengths, instead of lining
      up at a consistent bottom edge. Growing the description to
      fill remaining space pushes the link to the same spot on every
      card regardless of text length.
   2) "Read More" rendered at the browser's default paragraph weight
      (400) instead of the prototype's 600 (semibold).
--------------------------------------------------------------- */
.tcr-prod-card > .e-con-inner > *:nth-child(3) {
  flex-grow: 1;
}
.tcr-prod-card > .e-con-inner > *:nth-child(4),
.tcr-prod-card > .e-con-inner > *:nth-child(4) p {
  font-weight: 600;
}

/* ---------------------------------------------------------------
   Card hover-lift (product cards, More Products cards, gallery
   cards, service/quality icon cards). The Container widget has
   native Hover tabs for border-color and box-shadow, but no native
   control for a transform on hover -- that part only is custom CSS.
   Source: tcr-styles.css .prod-card:hover / .svc-icon-card:hover.
--------------------------------------------------------------- */
/* Bugfix (multiple product pages: "Product Series" grids, "More
   Products" cards): these cards are flex children with the native
   flex-grow left at 0, so each card only ever sized to its own
   content (varying per card depending on image dimensions/text
   length) instead of evenly filling the row -- confirmed on
   Fasteners for Sheet Metal, where the row fell ~78px short of the
   1240px container on the Product Series grid and the More Products
   row didn't fill its 1140px row either. flex-grow:1 makes every
   card in a row claim an equal share of the remaining width, same
   as a real CSS grid column would.
   !important needed: Elementor's own Container CSS sets flex-grow
   via a `flex` SHORTHAND on `.e-con.e-flex` (2-class selector,
   `flex: var(--flex-grow) var(--flex-shrink) var(--flex-basis)`,
   defaulting --flex-grow to 0 on every `.e-con`) -- that beats this
   rule's single-class selector on specificity alone, regardless of
   load order, so a plain flex-grow declaration here was silently
   losing outright, not just on a tie. */
.tcr-hover-lift,
.tcr-more-product-card {
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
  flex-grow: 1 !important;
  min-width: 0 !important;
}
.tcr-hover-lift:hover,
.tcr-more-product-card:hover {
  transform: translateY(-4px);
}

/* ---------------------------------------------------------------
   Contact form field focus ring. The Elementor Pro Form widget has
   no native :focus-state control for its input fields (only a
   Normal-state border color) -- source: tcr-styles.css
   .form-field input:focus. Selector matches the specificity of
   Elementor's own generated normal-state field rule
   (.elementor-32 .elementor-element.elementor-element-ct00008
   .elementor-field-group .elementor-field:not(.elementor-select-wrapper))
   so the focus state actually wins the cascade instead of being
   silently outranked by it.
--------------------------------------------------------------- */
.elementor-32 .elementor-element.elementor-element-ct00008 .elementor-field-group .elementor-field:not(.elementor-select-wrapper):focus {
  outline: none;
  border-color: #1690C4;
  box-shadow: 0 0 0 3px rgba(22, 144, 196, 0.12);
}

/* ---------------------------------------------------------------
   Contact form Message textarea. The Elementor Pro Form widget's
   textarea field type has no native min-height or resize-direction
   control -- only a "Rows" number, which sets the HTML rows
   attribute rather than an explicit min-height floor. Source:
   tcr-styles.css .form-field textarea (min-height:130px,
   resize:vertical). Without this, the field's floor was 40px and
   it allowed horizontal resize (resize:both), letting a user drag
   it narrower than its column and break the form-grid layout.
--------------------------------------------------------------- */
.elementor-32 .elementor-element.elementor-element-ct00008 .elementor-field-group textarea.elementor-field {
  min-height: 130px;
  resize: vertical;
}

/* ---------------------------------------------------------------
   Home "Our Products" Loop Carousel arrows. Elementor's Loop
   Carousel only offers an Arrows Position of "Inside" or "Outside"
   -- both keep the prev/next buttons absolutely positioned beside
   the slides, vertically centered. The prototype's slider instead
   renders plain, non-absolute prev/next buttons as the next
   elements after the card grid (.cards-controls, margin-top:36px),
   so they sit in a row below it. There is no native control for
   "below" placement, so this switches the arrows from absolute to
   static positioning -- since they already sit in the DOM
   immediately after the swiper track, removing the absolute
   positioning drops them into normal flow right below it, matching
   the prototype's layout without needing new markup.
   Source: tcr-styles.css .cards-controls / .round-arrow.

   !important: Elementor Pro's own widget-loop-carousel.min.css sets
   position/top/left/transform via a same-specificity two-class
   selector (.elementor-widget-loop-carousel .elementor-swiper-
   button-prev/next), and that stylesheet is enqueued after
   astra-child's, so on an exact specificity tie its later load
   order would otherwise win. !important is used here only to break
   that specific tie, not as a general shortcut.
--------------------------------------------------------------- */
.elementor-element-977ca84 .elementor-swiper-button {
  position: static !important;
  top: auto !important;
  left: auto !important;
  right: auto !important;
  transform: none !important;
  display: inline-flex !important;
  margin-top: 36px;
}
.elementor-element-977ca84 .elementor-swiper-button-next {
  margin-left: 10px;
}

/* ---------------------------------------------------------------
   Home "Our Products" carousel per-product icon (.tcr-card-icon,
   Loop Item template "Product Card Loop Item"). Elementor's Icon
   widget control has no Dynamic Tag support (confirmed: no
   "dynamic" key on the icons control type), so a single Loop Item
   template can't natively show a different icon per looped post --
   it always renders the one icon chosen in the template. Every
   product-slide DOM node already carries a "post-{ID}" class
   (WordPress's own post_class()), so this swaps the icon per
   product via CSS mask-image instead: the template's Icon widget
   keeps one base icon for markup/sizing, its SVG is hidden, and a
   masked, ft-blue-colored pseudo-element takes over.

   Bug fix: this originally used guessed Font Awesome solid-glyph
   icons (fa-plug, fa-globe, fa-plus, etc.) as a stand-in, which are
   a completely different icon family/shape from the prototype's
   thin-stroke line icons -- still visibly "the wrong icon" even
   though each was at least mapped to a plausible-sounding product.
   Replaced with the exact same SVG path data used for the product
   pages' "More Products" cards (.tcr-more-product-card, same
   post-ID-to-icon mapping, scraped directly from the prototype's
   Products landing/all-products grid), so the icon set is now
   identical and pixel-accurate everywhere it appears on the site.
   Post ID -> product, confirmed via this carousel's own post-{ID}
   classes: 22 Fasteners for Plastic, 23 Fasteners for Sheet Metal,
   24 Battery Contacts & Holder, 25 General Fasteners, 26 Blind
   Rivet, 27 Pogo Pin, 28 O-Ring.
--------------------------------------------------------------- */
.tcr-card-icon .elementor-icon svg {
  display: none;
}
.tcr-card-icon .elementor-icon {
  position: relative;
  width: 28px;
  height: 28px;
}
.tcr-card-icon .elementor-icon::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--ft-blue, #1690C4);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}
.post-22 .tcr-card-icon .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='13' y='6' width='14' height='28' rx='1'/%3E%3Cpath d='M13 11h14M13 16h14M13 21h14M13 26h14M13 31h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='13' y='6' width='14' height='28' rx='1'/%3E%3Cpath d='M13 11h14M13 16h14M13 21h14M13 26h14M13 31h14'/%3E%3C/svg%3E");
}
.post-23 .tcr-card-icon .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 33 12.5v15L20 35 7 27.5v-15L20 5Z'/%3E%3Ccircle cx='20' cy='20' r='6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 33 12.5v15L20 35 7 27.5v-15L20 5Z'/%3E%3Ccircle cx='20' cy='20' r='6'/%3E%3C/svg%3E");
}
.post-24 .tcr-card-icon .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='12' width='27' height='16' rx='2'/%3E%3Cpath d='M32 18h3v4h-3M11 16v8M11 20h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='12' width='27' height='16' rx='2'/%3E%3Cpath d='M32 18h3v4h-3M11 16v8M11 20h6'/%3E%3C/svg%3E");
}
.post-25 .tcr-card-icon .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M14 6h12l-2 5h-8l-2-5ZM16 11h8v3l-8 20-0-20'/%3E%3Cpath d='M16 15h8M16 19h8M17 23h6M18 27h4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M14 6h12l-2 5h-8l-2-5ZM16 11h8v3l-8 20-0-20'/%3E%3Cpath d='M16 15h8M16 19h8M17 23h6M18 27h4'/%3E%3C/svg%3E");
}
.post-26 .tcr-card-icon .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M13 8h14l-3 6h-8l-3-6ZM16 14h8v6l-1 15h-6l-1-15v-6Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M13 8h14l-3 6h-8l-3-6ZM16 14h8v6l-1 15h-6l-1-15v-6Z'/%3E%3C/svg%3E");
}
.post-27 .tcr-card-icon .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 4v7'/%3E%3Crect x='15' y='11' width='10' height='9' rx='1'/%3E%3Cpath d='M17 20l3 3 3-3M17 24l3 3 3-3M17 28l3 3 3-3'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 4v7'/%3E%3Crect x='15' y='11' width='10' height='9' rx='1'/%3E%3Cpath d='M17 20l3 3 3-3M17 24l3 3 3-3M17 28l3 3 3-3'/%3E%3C/svg%3E");
}
.post-28 .tcr-card-icon .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.6'%3E%3Ccircle cx='20' cy='20' r='14'/%3E%3Ccircle cx='20' cy='20' r='7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.6'%3E%3Ccircle cx='20' cy='20' r='14'/%3E%3Ccircle cx='20' cy='20' r='7'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------
   Product pages "Explore the rest of our range" / More Products
   cards (.tcr-more-product-card), all 7 product page templates.

   1) Image: each card's Image widget had a hardcoded custom Height
      of 176px (native per-widget style setting, compiled to
      ".elementor-{X} .elementor-element.elementor-element-{id} img
      {width:100%;height:176px;object-fit:contain}" -- same value
      copy-pasted onto every card on every page). The prototype's
      photo instead fills the full card width as a 1:1 square
      (tcr-styles.css .prod-card-photo: aspect-ratio 1/1, padding
      26px), so the fixed 176px floor left it far smaller than the
      card. Overriding to a responsive square. !important needed:
      the native rule's 3-class selector ties or beats this one's
      specificity, and loads after astra-child's stylesheet.

   2) Icon: each card's Icon widget uses a real Font Awesome glyph
      (fa-ring / fa-car-battery / fa-screwdriver, etc.) as a stand-in
      -- visually a different icon family/shape than the prototype's
      thin-stroke line icons (tcr-styles.css .prod-card-icon svg).
      Same mask-image swap technique as the Home carousel's
      .tcr-card-icon fix, but scoped by the card link's href (each
      card is an <a href="/products/{slug}/">) instead of a post-ID
      class, since these are static per-page cards, not a post loop.
      Path data scraped directly from the live prototype's own
      Products landing/all-products grid for exact fidelity.
--------------------------------------------------------------- */
.tcr-more-product-card .elementor-widget-image {
  width: 100% !important;
}
.tcr-more-product-card .elementor-widget-image img {
  width: 100% !important;
  height: auto !important;
  aspect-ratio: 1 / 1 !important;
  object-fit: contain !important;
}

/* ---------------------------------------------------------------
   Products Landing page (7 cards, pl10003/pl20003/.../pl70003):
   same fixed-176px-style bug as the More Products cards above --
   each Image widget was left at a small fixed size (200x200)
   instead of filling the card width as a responsive square, which
   read as the photo being "zoomed out" with excess white space
   around it (confirmed same source file/object-fit/object-position
   as the prototype -- only the box size differed: prototype's photo
   box is ~374px within a ~376px card, this was 200px within a
   ~397px card).
--------------------------------------------------------------- */
.elementor-element-pl10003,
.elementor-element-pl20003,
.elementor-element-pl30003,
.elementor-element-pl40003,
.elementor-element-pl50003,
.elementor-element-pl60003,
.elementor-element-pl70003 {
  width: 100% !important;
}
.elementor-element-pl10003 img,
.elementor-element-pl20003 img,
.elementor-element-pl30003 img,
.elementor-element-pl40003 img,
.elementor-element-pl50003 img,
.elementor-element-pl60003 img,
.elementor-element-pl70003 img {
  width: 100% !important;
  height: auto !important;
  aspect-ratio: 1 / 1 !important;
  object-fit: contain !important;
}

/* ---------------------------------------------------------------
   Products Landing page (7 cards): same "Read More" alignment +
   weight bugs as the Home slider cards -- description had no
   flex-grow (so Read More sat directly under whatever text length
   each card happened to have, not lined up across cards), and Read
   More rendered at the browser default weight (400) instead of the
   prototype's 600.
--------------------------------------------------------------- */
.elementor-element-pl10008, .elementor-element-pl20008, .elementor-element-pl30008,
.elementor-element-pl40008, .elementor-element-pl50008, .elementor-element-pl60008,
.elementor-element-pl70008 {
  flex-grow: 1;
}
.elementor-element-pl10009, .elementor-element-pl20009, .elementor-element-pl30009,
.elementor-element-pl40009, .elementor-element-pl50009, .elementor-element-pl60009,
.elementor-element-pl70009,
.elementor-element-pl10009 p, .elementor-element-pl20009 p, .elementor-element-pl30009 p,
.elementor-element-pl40009 p, .elementor-element-pl50009 p, .elementor-element-pl60009 p,
.elementor-element-pl70009 p {
  font-weight: 600;
}

.tcr-more-product-card .elementor-icon svg {
  display: none;
}
/* Bugfix: sized to 40x40 to match the icon SVGs' own viewBox
   ("0 0 40 40"), but viewBox is just the SVG's internal coordinate
   system, not its rendered size -- the prototype's own More Products
   icon (.prod-card-icon svg, same viewBox) renders at 28x28, giving
   every card's icon a visibly larger, heavier look than the
   prototype across all 7 product pages. */
.tcr-more-product-card .elementor-icon {
  position: relative;
  width: 28px;
  height: 28px;
}
/* Bugfix: the title Heading widget shrink-wraps to its own text
   content instead of filling the available column width (measured:
   only given 220.9px of a 270.4px available column on "Battery
   Contacts & Holder", the longest of the 7 product titles) --
   because it narrows as it wraps, this created a feedback loop
   where the box got narrower AND wrapped, instead of just using the
   full column width like the prototype does (confirmed: prototype's
   equivalent title box is 235.7px, comfortably fitting one line).
   Forcing full width here guarantees enough room for every title. */
.tcr-more-product-card .elementor-widget-heading {
  width: 100% !important;
}
/* Bugfix: even at full available width, the two longest product
   titles -- "Battery Contacts & Holder" and "Fasteners for Sheet
   Metal" (both ~26 characters, notably longer than the other 5
   product names) -- were still a few px short of fitting one line.
   Scoped to just these two products' cards (matching the same
   href-attribute technique used for the icon swaps above) rather
   than applied to every More Products card -- an earlier version of
   this rule targeted all cards uniformly, which fixed the wrap but
   also crowded every OTHER (already-short-enough) card's icon
   against its title unnecessarily. Root cause found instead of
   patching the symptom: the icon+title row sits inside TWO nested
   ".e-con-boxed" wrappers (same redundant-double-wrapper pattern as
   the gallery card bug fixed earlier), the inner one adding an extra
   10px of left/right padding on top of the outer's own 26px --
   removing the inner (redundant) layer's side padding frees 20px of
   width for every More Products card, which is enough for even the
   two longest titles to fit at the same icon size and gap as every
   other card, matching "Fasteners for Plastic" exactly instead of
   needing a per-card size/spacing compromise. */
.tcr-more-product-card > .e-con-boxed .e-con-boxed {
  padding-left: 0 !important;
  padding-right: 0 !important;
}
.tcr-more-product-card .elementor-icon::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--ft-blue, #1690C4);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}
.tcr-more-product-card[href*="fasteners-for-plastic"] .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='13' y='6' width='14' height='28' rx='1'/%3E%3Cpath d='M13 11h14M13 16h14M13 21h14M13 26h14M13 31h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='13' y='6' width='14' height='28' rx='1'/%3E%3Cpath d='M13 11h14M13 16h14M13 21h14M13 26h14M13 31h14'/%3E%3C/svg%3E");
}
.tcr-more-product-card[href*="fasteners-for-sheet-metal"] .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 33 12.5v15L20 35 7 27.5v-15L20 5Z'/%3E%3Ccircle cx='20' cy='20' r='6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 33 12.5v15L20 35 7 27.5v-15L20 5Z'/%3E%3Ccircle cx='20' cy='20' r='6'/%3E%3C/svg%3E");
}
.tcr-more-product-card[href*="battery-contacts-holder"] .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='12' width='27' height='16' rx='2'/%3E%3Cpath d='M32 18h3v4h-3M11 16v8M11 20h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='12' width='27' height='16' rx='2'/%3E%3Cpath d='M32 18h3v4h-3M11 16v8M11 20h6'/%3E%3C/svg%3E");
}
.tcr-more-product-card[href*="general-fasteners"] .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M14 6h12l-2 5h-8l-2-5ZM16 11h8v3l-8 20-0-20'/%3E%3Cpath d='M16 15h8M16 19h8M17 23h6M18 27h4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M14 6h12l-2 5h-8l-2-5ZM16 11h8v3l-8 20-0-20'/%3E%3Cpath d='M16 15h8M16 19h8M17 23h6M18 27h4'/%3E%3C/svg%3E");
}
.tcr-more-product-card[href*="blind-rivet"] .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M13 8h14l-3 6h-8l-3-6ZM16 14h8v6l-1 15h-6l-1-15v-6Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M13 8h14l-3 6h-8l-3-6ZM16 14h8v6l-1 15h-6l-1-15v-6Z'/%3E%3C/svg%3E");
}
.tcr-more-product-card[href*="pogo-pin"] .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 4v7'/%3E%3Crect x='15' y='11' width='10' height='9' rx='1'/%3E%3Cpath d='M17 20l3 3 3-3M17 24l3 3 3-3M17 28l3 3 3-3'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 4v7'/%3E%3Crect x='15' y='11' width='10' height='9' rx='1'/%3E%3Cpath d='M17 20l3 3 3-3M17 24l3 3 3-3M17 28l3 3 3-3'/%3E%3C/svg%3E");
}
.tcr-more-product-card[href*="o-ring"] .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.6'%3E%3Ccircle cx='20' cy='20' r='14'/%3E%3Ccircle cx='20' cy='20' r='7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.6'%3E%3Ccircle cx='20' cy='20' r='14'/%3E%3Ccircle cx='20' cy='20' r='7'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------
   Home Services accordion (hm00014) active-item title size bump.
   The prototype's hover-list grows the active item's name to 32px/
   500 weight, full white, while inactive items stay 20px/400 at 70%
   opacity (tcr-styles.css .market-row.active .market-name).
   Elementor's Accordion widget only exposes ONE shared Title
   Typography control plus a separate Normal/Active COLOR pair --
   there's no per-state font-size or font-weight control, so the
   base 20px/400 is set natively and this covers the active-state
   size/weight/color increase that has no native equivalent.

   Bug fix: this rule was never actually taking effect. Its selector
   (.elementor-element-hm00014 .elementor-tab-title.elementor-active
   .elementor-accordion-title) ties in specificity (4 classes) with
   Elementor's own compiled rule for this exact element
   (.elementor-12 .elementor-element.elementor-element-hm00014
   .elementor-accordion-title, also 4 classes), and that compiled
   CSS loads after astra-child's stylesheet -- so on the tie, it was
   silently winning and this rule did nothing. Verified by checking
   which rules actually matched the live active-title element.
--------------------------------------------------------------- */
.elementor-element-hm00014 .elementor-tab-title.elementor-active .elementor-accordion-title {
  font-size: 32px !important;
  font-weight: 500 !important;
  color: #fff !important;
}

/* ---------------------------------------------------------------
   Home "Backed by Gexpro Services" logo carousel (hm00022).
   1) Each slide needs a light steel-100 backing box behind the
      partner logo (tcr-styles.css .company-card: background
      var(--steel-100)) so white-background logo files don't
      disappear into the page background -- the Image Carousel
      widget has no native per-slide background control.
   2) Same arrows-below-row treatment as the Home products carousel
      (.elementor-element-977ca84 rule above) and for the same
      reason: no native "below" arrow position exists, only Inside/
      Outside (both keep arrows absolutely overlaid). Native Arrow
      Color was set to --ink via the widget's own Style tab; this
      only handles repositioning.
--------------------------------------------------------------- */
.elementor-element-hm00022 .swiper-slide {
  background: var(--steel-100, #F5F6F7);
  height: 188px !important;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  box-sizing: border-box;
}
.elementor-element-hm00022 .swiper-slide img {
  max-height: 100%;
  max-width: 100%;
  width: auto;
  object-fit: contain;
}
.elementor-element-hm00022 .swiper-wrapper,
.elementor-element-hm00022 .swiper {
  height: 188px !important;
}
.elementor-element-hm00022 .elementor-swiper-button {
  position: static !important;
  top: auto !important;
  left: auto !important;
  right: auto !important;
  transform: none !important;
  display: inline-flex !important;
  margin-top: 24px;
}
.elementor-element-hm00022 .elementor-swiper-button-next {
  margin-left: 10px;
}

/* ---------------------------------------------------------------
   Bug fix: a prior fix for the footer's TCR logo (dark charcoal
   background, logo needs to read solid white) targeted element ID
   "ft00004" for the brightness(0) invert(1) treatment. That ID
   actually belongs to a DIFFERENT widget on the same footer
   template -- the "A Gexpro Services Company" partner-logo image,
   which sits on a light/white band and is meant to show its own
   full natural color (confirmed via prototype: filter:none). The
   real TCR logo widget is ft00008, and it already renders correctly
   without any filter (its source file is already a white/transparent
   PNG), so the override was never needed there either -- removing
   entirely rather than retargeting.
--------------------------------------------------------------- */

/* ---------------------------------------------------------------
   Button widget arrow icon badge (all "Contact Us" / "View All
   Products" / "Request a Quote" style pill buttons, sitewide).
   Elementor's Button widget has an Icon control but no "frame/
   background behind the icon" control, so the prototype's circular
   tinted badge behind the arrow (tcr-styles.css .btn-pill .arrow:
   18x18px circle, background rgba(255,255,255,.22), centered) has
   no native equivalent. Scoped to .elementor-widget-button so it
   never touches the Elementor Form widget's own Submit button
   (different widget type/markup entirely, and the prototype's own
   .form-submit button intentionally has no badge either).
--------------------------------------------------------------- */
.elementor-widget-button .elementor-button-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.22);
}
.elementor-widget-button .elementor-button-icon svg {
  width: 10px;
  height: 10px;
}

/* ---------------------------------------------------------------
   Bugfix, sitewide: every button's text sits visibly high inside
   its pill (client-reported: "Contact Us" and similar). Root cause
   is in Elementor's own core CSS, not this build --
   .elementor-button-content-wrapper is display:flex but never sets
   align-items, so it defaults to stretch: the icon and text spans
   both stretch to fill the wrapper's full height, and since the
   text's own line-height (14px) is shorter than that stretched box
   (18px, set by the taller icon), the text renders in the top 14px
   of its box with the leftover 4px left empty below it -- text
   looks top-heavy even though the wrapper itself is correctly
   centered in the button. align-items:center lets each span size to
   its own content instead of stretching, so the text centers
   properly. Unscoped (not just .elementor-widget-button) since this
   is a genuine correctness fix, not a design choice -- it should
   apply to every button sharing this wrapper, including the
   Elementor Form widget's Submit button.
--------------------------------------------------------------- */
.elementor-button-content-wrapper {
  align-items: center;
}

/* ---------------------------------------------------------------
   Footer Newsletter form (ft00019): Subscribe button should sit
   embedded inside the same rounded pill as the email input
   (tcr-styles.css .newsletter-form: one flex pill container with
   both the input and button as direct children, border/background
   on the pill itself). Elementor's Form widget always renders the
   submit button as its own separate field-group -- there's a
   Button Alignment control (Left/Center/Right/Stretch) but no
   option to keep it inline with the last field, and no per-widget
   "wrap fields + button in one bordered pill" control either.
   Changing button_align away from the default "stretch" doesn't
   help on its own: the two fields plus the button's default
   padding/font-size add up to more than this column's ~298px
   width, so flex-wrap still drops the button to its own line
   regardless of alignment. Rebuilding the pill via CSS: the fields
   wrapper becomes the single bordered/backed pill (nowrap), the
   input loses its own border/background (transparent, sits inside
   the shared pill instead), and the button shrinks to a compact
   pill matching the prototype's tighter padding/font-size so both
   fit on one line at this column width.
--------------------------------------------------------------- */
.elementor-element-ft00019 .elementor-form-fields-wrapper {
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: center;
  justify-content: center;
  gap: 0;
  width: 100%;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  padding: 4px;
}
/* Bugfix: the email field previously used flex:1 1 auto, growing to
   fill 100% of the pill's remaining width regardless of how short
   the placeholder text is, which pinned the button flush to the
   right edge instead of centered. Sizing the field to its actual
   content, plus justify-content:center on the wrapper and a wider
   fixed pill width, centers the input+button as one group within a
   wide bubble instead of stretching the input to fill it. */
.elementor-element-ft00019 .elementor-field-type-email {
  flex: 0 1 auto;
  min-width: 0;
}
.elementor-element-ft00019 .elementor-field-type-email input {
  border: none !important;
  background: transparent !important;
  padding: 8px 4px !important;
  height: auto !important;
  width: 11ch;
  padding-left: 12px !important;
  text-align: center;
}
.elementor-element-ft00019 .elementor-field-group {
  margin: 0 !important;
}
.elementor-element-ft00019 .elementor-field-type-submit {
  flex: 0 0 auto;
}
.elementor-element-ft00019 .elementor-field-type-submit button {
  padding: 8px 16px !important;
  font-size: 13px !important;
  height: auto !important;
  white-space: nowrap;
}

/* ---------------------------------------------------------------
   Pogo Pin page "Types" row (pg10003): each type name (Single Pogo
   Pin, Double Head Pin, Screw Pin, Ultra Small Pins, Magnetic
   Connectors) is already its own separate Text Editor widget, but
   rendered with no box styling at all -- just plain text running
   together with default widget spacing, no visual separation.
   Prototype styles each as its own tag/chip (tcr-styles.css
   .tag-item: steel-100 background, steel-200 border, 4px radius,
   9px/16px padding) inside a wrapping flex row (.tag-row: wrap,
   10px gap). Elementor's Text Editor widget has no "pill/tag"
   style preset, so this is custom CSS per project convention.
--------------------------------------------------------------- */
.elementor-element-pg10003 {
  flex-wrap: wrap !important;
  gap: 10px !important;
}
.elementor-element-pg10003 > .e-con-inner > .elementor-widget-text-editor {
  background: var(--steel-100, #F5F6F7);
  border: 1px solid var(--steel-200, #E5E7E9);
  border-radius: 4px;
  padding: 9px 16px;
  font-size: 13px;
  font-weight: 500;
  color: var(--steel-700, #454A53);
  flex: 0 0 auto;
}

/* ---------------------------------------------------------------
   Fasteners for Sheet Metal "Product Series" gallery (4 cards,
   fm10004/fm10011/fm10021/fm10031): each card's Container widget
   was set to a flat Width: 23%, which doesn't account for the row's
   24px gaps the way a true 4-column CSS grid would -- confirmed via
   matching-viewport DevTools comparison against the prototype: its
   .gallery-card is 276px (border-box) in a 1176px-wide row with
   three 24px gaps (4x276 + 3x24 = 1176, exact fit), while WP's flat
   23% only produced 262px, leaving each card too narrow and forcing
   more text-wrap (which is why "Self-Clinching Nut" -- the longest
   description -- was dragging every card in the row taller too).
   calc() reproduces the exact grid math regardless of row width.
--------------------------------------------------------------- */
.elementor-element-fm10004,
.elementor-element-fm10011,
.elementor-element-fm10021,
.elementor-element-fm10031 {
  width: calc((100% - 72px) / 4) !important;
}

/* ---------------------------------------------------------------
   Same double-wrapper/width bug as the Sheet Metal fix above,
   confirmed identical on the other two gallery pages: Fasteners for
   Plastic (8 cards, fp10001/fp10003 wrapper chain) and Blind Rivet
   (4 cards, br10001/br10003 wrapper chain). This calc() rule fixes
   the card width itself once the redundant wrapper's extra padding/
   max-width is corrected in Elementor (see fp10001/fp10003 and
   br10001/br10003 -- same two settings changes as fm10001/fm10003).
--------------------------------------------------------------- */
.elementor-element-fp10004,
.elementor-element-fp10011,
.elementor-element-fp10021,
.elementor-element-fp10031,
.elementor-element-fp10041,
.elementor-element-fp10051,
.elementor-element-fp10061,
.elementor-element-fp10071 {
  width: calc((100% - 72px) / 4) !important;
}
.elementor-element-br10004,
.elementor-element-br10011,
.elementor-element-br10021,
.elementor-element-br10031 {
  width: calc((100% - 72px) / 4) !important;
}

/* ---------------------------------------------------------------
   Bugfix: the calc() width above is a flat desktop value with no
   responsive override, so all 3 galleries stayed at 4-per-row
   regardless of viewport width -- the prototype drops to 2 cards
   per row at tablet widths. Confirmed via matching-width comparison
   (~940px, both sides of a split screen): prototype showed 2 cards,
   WP still showed 4. Elementor's own default breakpoint for
   Tablet is max-width:1024px, matched here.
--------------------------------------------------------------- */
@media (max-width: 1024px) {
  .elementor-element-fm10004,
  .elementor-element-fm10011,
  .elementor-element-fm10021,
  .elementor-element-fm10031,
  .elementor-element-fp10004,
  .elementor-element-fp10011,
  .elementor-element-fp10021,
  .elementor-element-fp10031,
  .elementor-element-fp10041,
  .elementor-element-fp10051,
  .elementor-element-fp10061,
  .elementor-element-fp10071,
  .elementor-element-br10004,
  .elementor-element-br10011,
  .elementor-element-br10021,
  .elementor-element-br10031 {
    width: calc((100% - 24px) / 2) !important;
  }
}

/* ---------------------------------------------------------------
   Services page icon cards (sv10002 Inventory, sv20002 Procurement,
   sv30002 Prototyping, sv40002 Kitting/Labeling): each used a solid
   Font Awesome glyph (fa-boxes-stacked / fa-cart-shopping / fa-cube /
   fa-tag) as a stand-in -- same color (#1690C4) as the prototype but
   a visually different icon family/shape than its thin-stroke line
   icons (viewBox 0 0 40 40, stroke-width 1.4). Same mask-image swap
   technique used elsewhere on the site (Blind Rivet, Home carousel),
   with path data pulled directly from the live prototype for exact
   fidelity. Icon color still comes from the widget's own primary_color
   setting (already #1690C4) via currentColor -- only the shape changes.
--------------------------------------------------------------- */
.elementor-element-sv10002 .elementor-icon svg,
.elementor-element-sv20002 .elementor-icon svg,
.elementor-element-sv30002 .elementor-icon svg,
.elementor-element-sv40002 .elementor-icon svg {
  display: none;
}
.elementor-element-sv10002 .elementor-icon,
.elementor-element-sv20002 .elementor-icon,
.elementor-element-sv30002 .elementor-icon,
.elementor-element-sv40002 .elementor-icon {
  position: relative;
  width: 44px;
  height: 44px;
}
.elementor-element-sv10002 .elementor-icon::before,
.elementor-element-sv20002 .elementor-icon::before,
.elementor-element-sv30002 .elementor-icon::before,
.elementor-element-sv40002 .elementor-icon::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: currentColor;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}
.elementor-element-sv10002 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='20' width='13' height='14'/%3E%3Crect x='22' y='20' width='13' height='14'/%3E%3Crect x='13.5' y='6' width='13' height='14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='20' width='13' height='14'/%3E%3Crect x='22' y='20' width='13' height='14'/%3E%3Crect x='13.5' y='6' width='13' height='14'/%3E%3C/svg%3E");
}
.elementor-element-sv20002 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M4 6h4l3 18h18l3-12H10'/%3E%3Ccircle cx='14' cy='31' r='2.2'/%3E%3Ccircle cx='28' cy='31' r='2.2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M4 6h4l3 18h18l3-12H10'/%3E%3Ccircle cx='14' cy='31' r='2.2'/%3E%3Ccircle cx='28' cy='31' r='2.2'/%3E%3C/svg%3E");
}
.elementor-element-sv30002 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 6 12v16l14 7 14-7V12L20 5Z'/%3E%3Cpath d='M6 12l14 7 14-7M20 19v16'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 6 12v16l14 7 14-7V12L20 5Z'/%3E%3Cpath d='M6 12l14 7 14-7M20 19v16'/%3E%3C/svg%3E");
}
.elementor-element-sv40002 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M6 6h13l15 15-13 13L6 19V6Z'/%3E%3Ccircle cx='13' cy='13' r='2.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M6 6h13l15 15-13 13L6 19V6Z'/%3E%3Ccircle cx='13' cy='13' r='2.5'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------
   Bugfix, sitewide: every custom-sized icon (.tcr-card-icon,
   .tcr-more-product-card, Services/Quality page icons, Products
   Landing page icons, etc.) shrinks `.elementor-icon` down to a
   specific px size (28px, to match the prototype), but Elementor's
   own `.elementor-icon-wrapper` around it keeps its default,
   TALLER size (34.4px, from the widget's font-size-driven line-
   height) and top-anchors the now-smaller icon inside it instead of
   re-centering. Invisible wherever the icon sits in a flex row next
   to other content of about the same height (the row's own
   align-items:center centers the *wrapper*, close enough to look
   right) -- but on the Products Landing page, where the icon and
   heading are separate sibling widgets centered against each other
   directly, the 6.4px gap between wrapper and icon shows up as the
   icon visibly sitting ~3px above the title's true center.
   display:flex here re-centers the icon inside its own wrapper
   regardless of any size mismatch, so this holds even if a future
   icon's custom size changes again.
--------------------------------------------------------------- */
.elementor-icon-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---------------------------------------------------------------
   Products Landing page (7 cards, pl10006...pl70006): each icon
   used a real Font Awesome glyph (fa-plug/fa-ring/fa-car-battery/
   fa-screwdriver/fa-thumbtack/fa-microchip/fa-circle) instead of
   the prototype's thin-stroke line icons -- same mask-image swap
   technique as the Services page and product detail pages, path
   data pulled directly from the live prototype.
--------------------------------------------------------------- */
.elementor-element-pl10006 .elementor-icon svg,
.elementor-element-pl20006 .elementor-icon svg,
.elementor-element-pl30006 .elementor-icon svg,
.elementor-element-pl40006 .elementor-icon svg,
.elementor-element-pl50006 .elementor-icon svg,
.elementor-element-pl60006 .elementor-icon svg,
.elementor-element-pl70006 .elementor-icon svg {
  display: none;
}
.elementor-element-pl10006 .elementor-icon,
.elementor-element-pl20006 .elementor-icon,
.elementor-element-pl30006 .elementor-icon,
.elementor-element-pl40006 .elementor-icon,
.elementor-element-pl50006 .elementor-icon,
.elementor-element-pl60006 .elementor-icon,
.elementor-element-pl70006 .elementor-icon {
  position: relative;
  width: 28px;
  height: 28px;
}
.elementor-element-pl10006 .elementor-icon::before,
.elementor-element-pl20006 .elementor-icon::before,
.elementor-element-pl30006 .elementor-icon::before,
.elementor-element-pl40006 .elementor-icon::before,
.elementor-element-pl50006 .elementor-icon::before,
.elementor-element-pl60006 .elementor-icon::before,
.elementor-element-pl70006 .elementor-icon::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: currentColor;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
}
.elementor-element-pl10006 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='13' y='6' width='14' height='28' rx='1'/%3E%3Cpath d='M13 11h14M13 16h14M13 21h14M13 26h14M13 31h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='13' y='6' width='14' height='28' rx='1'/%3E%3Cpath d='M13 11h14M13 16h14M13 21h14M13 26h14M13 31h14'/%3E%3C/svg%3E");
}
.elementor-element-pl20006 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 33 12.5v15L20 35 7 27.5v-15L20 5Z'/%3E%3Ccircle cx='20' cy='20' r='6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 5 33 12.5v15L20 35 7 27.5v-15L20 5Z'/%3E%3Ccircle cx='20' cy='20' r='6'/%3E%3C/svg%3E");
}
.elementor-element-pl30006 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='12' width='27' height='16' rx='2'/%3E%3Cpath d='M32 18h3v4h-3M11 16v8M11 20h6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Crect x='5' y='12' width='27' height='16' rx='2'/%3E%3Cpath d='M32 18h3v4h-3M11 16v8M11 20h6'/%3E%3C/svg%3E");
}
.elementor-element-pl40006 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M14 6h12l-2 5h-8l-2-5ZM16 11h8v3l-8 20-0-20'/%3E%3Cpath d='M16 15h8M16 19h8M17 23h6M18 27h4'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M14 6h12l-2 5h-8l-2-5ZM16 11h8v3l-8 20-0-20'/%3E%3Cpath d='M16 15h8M16 19h8M17 23h6M18 27h4'/%3E%3C/svg%3E");
}
.elementor-element-pl50006 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M13 8h14l-3 6h-8l-3-6ZM16 14h8v6l-1 15h-6l-1-15v-6Z'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M13 8h14l-3 6h-8l-3-6ZM16 14h8v6l-1 15h-6l-1-15v-6Z'/%3E%3C/svg%3E");
}
.elementor-element-pl60006 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 4v7'/%3E%3Crect x='15' y='11' width='10' height='9' rx='1'/%3E%3Cpath d='M17 20l3 3 3-3M17 24l3 3 3-3M17 28l3 3 3-3'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.4'%3E%3Cpath d='M20 4v7'/%3E%3Crect x='15' y='11' width='10' height='9' rx='1'/%3E%3Cpath d='M17 20l3 3 3-3M17 24l3 3 3-3M17 28l3 3 3-3'/%3E%3C/svg%3E");
}
.elementor-element-pl70006 .elementor-icon::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.6'%3E%3Ccircle cx='20' cy='20' r='14'/%3E%3Ccircle cx='20' cy='20' r='7'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none' stroke='black' stroke-width='1.6'%3E%3Ccircle cx='20' cy='20' r='14'/%3E%3Ccircle cx='20' cy='20' r='7'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------
   Products Landing 7-card grid (3+3+1 layout): cards 1-6 each have
   an explicit Width matching a true 3-column grid
   (calc((100% - 48px) / 3), confirmed 397.33px each in a 1240px
   row with 24px gaps), but the 7th card (O-Ring, pl70001) was left
   on Elementor's default Content-Width:Full behavior, so sitting
   alone in the final row it stretched to fill the entire 1240px row
   width -- including its photo, which rendered at a dramatic,
   broken-looking full-page size instead of matching its siblings.
   The prototype keeps the last card the same size as the other 6
   (confirmed 376px, not stretched), so matching that here instead
   of the default full-width behavior. Setting width alone wasn't
   enough: this card also has flex-grow:1, and since it's alone in
   its row, that grow value absorbs 100% of the row's leftover space
   regardless of width -- the other 6 don't show this because 3
   equal flex-grow:1 siblings already filling their shared row leaves
   nothing left to grow into. Capping flex-grow to 0 stops it from
   expanding past the explicit width. */
.elementor-element-pl70001 {
  width: calc((100% - 48px) / 3) !important;
  flex-grow: 0 !important;
}

/* ---------------------------------------------------------------
   Products Landing grid: "Read More" links weren't aligned across
   a row (up to ~22px apart) since each card's description had no
   flex-grow, the same root cause already fixed for the Home slider
   cards (.tcr-prod-card) -- these Products Landing cards use their
   own per-instance pl##### widgets instead of that shared class, so
   the fix needs its own selector scoped to #pl-grid-inner. Card
   structure: [image, body], body > [icon+heading row, description,
   Read More link] -- description is nth-child(2) of body, link is
   nth-child(3). The 7 cards aren't structurally identical though:
   some (e.g. Fasteners for Plastic) wrap [image, body] in their own
   extra .e-con-inner layer, others (e.g. Fasteners for Sheet Metal)
   have [image, body] as direct children with no such wrapper --
   covering both variants since a single fixed-depth selector only
   matched some of the 7 cards. */
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > .e-con-inner > *:nth-child(2),
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > *:nth-child(2) {
  flex-grow: 1;
}
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > .e-con-inner > *:nth-child(2) > .e-con-inner > *:nth-child(2),
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > *:nth-child(2) > .e-con-inner > *:nth-child(2) {
  flex-grow: 1;
}
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > .e-con-inner > *:nth-child(2) > .e-con-inner > *:nth-child(3),
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > .e-con-inner > *:nth-child(2) > .e-con-inner > *:nth-child(3) p,
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > *:nth-child(2) > .e-con-inner > *:nth-child(3),
#pl-grid-inner > .e-con-inner > [class*="e-con-full"] > *:nth-child(2) > .e-con-inner > *:nth-child(3) p {
  font-weight: 600;
}
