/* ═══════════════════════════════════════════════════════════
   JMAC — Elementor structural compensation.

   Loaded on the front end AND in the editor, after styles.css.

   Only for rules the design writes as direct-child selectors, which Elementor
   breaks by inserting `.elementor-element > .elementor-widget-container` around
   every widget. Nothing here restyles the design — each rule restores a
   relationship the design already declared.

   Keep this file small. If a widget looks wrong, fix its markup to match the
   design HTML instead of adding an override here.
   ═══════════════════════════════════════════════════════════ */

/* styles.css declares `.ci-band > section { position: relative; z-index: 1 }`,
   lifting the four band sections above `.ci-band::before`. In Elementor the
   sections are grandchildren of the container carrying `.ci-band`, so the
   direct-child selector never matches. Same intent, one level looser. */
.ci-band section {
  position: relative;
  z-index: 1;
}

/* ───────────────────────────────────────────────────────────
   Design wrappers placed on an Elementor Container.

   Four of the design's wrappers span several widgets, so their class goes on a
   Container. But a Container is not a plain <div> — Elementor's `.e-con` gives it
   `--display: flex`, `--gap: 20px` and `--padding: 10px`, and boxed width caps it
   at 1140px. Dropped onto `.about-hero` or `.art` that shows up as extra gaps
   between blocks, a stray 10px inset, and a narrowed column.

   These rules put the container back to plain block flow, through Elementor's
   own custom properties so its rules resolve to our values.

   !important is required here, not defensive. Elementor writes each container's
   panel settings into the page stylesheet as

     .elementor-64 .elementor-element.elementor-element-07ce4b4 { --display: flex }

   which is (0,3,0) and outranks any class-based rule we can write —
   `.e-con.about-hero` is only (0,2,0). Without !important the container stays
   flex, `--overflow` stays visible, and the hero's 1000px hexagon graphic
   (about.css:42, absolutely positioned at right:-300px) escapes its box and
   paints over the sections below it.
   ─────────────────────────────────────────────────────────── */
.e-con.ci-band,
.e-con.about-hero,
.e-con.contact-hero,
.e-con.art-main {
  --display: block !important;
  --gap: 0px !important;
  --row-gap: 0px !important;
  --column-gap: 0px !important;
  --content-width: 100% !important;
  --width: 100% !important;
  --padding-top: 0px !important;
  --padding-right: 0px !important;
  --padding-bottom: 0px !important;
  --padding-left: 0px !important;
  display: block !important;
}

/* ───────────────────────────────────────────────────────────
   `.art` is a measure, not a full-width wrapper.

   article-detail.css:39 caps the article at `max-width: 1060px; margin: 0 auto`
   with `padding: 20px 64px 72px` inside it (border-box, so 1060px total).

   It used to share the block above, which forces `--width` and `--content-width`
   to 100% — right for the wrappers that really do span the page, wrong here: it
   overrode both the design's 1060px and the width typed into the panel, and
   because those are `!important` they beat Elementor's own per-element CSS too.
   Setting the container's width to 1060 by hand then appeared to do nothing.

   A boxed container also nests its children in `.e-con-inner`, which applies
   `--content-width` a second time. That inner box is flattened here so the outer
   `.art` is the only thing deciding the measure — the same single box the design
   has, whether the panel is set to boxed or full width.
   ─────────────────────────────────────────────────────────── */
.e-con.art {
  --display: block !important;
  --gap: 0px !important;
  --row-gap: 0px !important;
  --column-gap: 0px !important;
  /* `--width` feeds Elementor's `width`, so pinning it to 1060px made the
     article a fixed-width box that could not shrink — below 1060px the page
     scrolled sideways instead of reflowing. The design pairs a full-width box
     with a max-width, which is what actually caps the measure while staying
     responsive; only the cap belongs at 1060. */
  --width: 100% !important;
  --content-width: 1060px !important;
  display: block !important;
  width: 100% !important;
  max-width: 1060px !important;
  margin-left: auto !important;
  margin-right: auto !important;
}

.e-con.art > .e-con-inner {
  display: block;
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0;
}

/* The two heroes clip a large decorative graphic; Elementor's container defaults
   to `--overflow: visible`, which lets it bleed over the next section. */
.e-con.about-hero,
.e-con.contact-hero {
  --overflow: hidden !important;
  overflow: hidden !important;
  isolation: isolate;
}

/* ───────────────────────────────────────────────────────────
   Let the crumb bar anchor to the hero, not to its own widget.

   `.hero-crumb-bar` is `position: absolute; top: 0; left: 0; right: 0`
   (styles.css:9737) and in the design it is a direct child of the hero section,
   so it pins to the very top edge — above the hero's 88px of padding.

   Elementor gives EVERY widget `position: relative` (frontend.css:445), which
   makes the widget's own box the containing block. The bar then measures `top: 0`
   from inside the container's padding, and lands ~104px too low — under the
   eyebrow instead of above the title.

   Making the immediate children static hands the containing block back to the
   container, which `.e-con` already positions for us.
   ─────────────────────────────────────────────────────────── */
.e-con.about-hero > .elementor-element,
.e-con.contact-hero > .elementor-element,
.e-con.about-hero > .elementor-element > .elementor-widget-container,
.e-con.contact-hero > .elementor-element > .elementor-widget-container {
  position: static;
}

/* Elementor's zeroed padding above wins over the design's own rule on load
   order, so restate it here at (0,2,0) — including the design's breakpoints. */
.e-con.about-hero   { padding: 88px 64px 72px; }   /* about.css:36 */
.e-con.contact-hero { padding: 96px 64px 88px; }   /* contact.css:16 */
.e-con.art          { padding: 20px 64px 72px; }   /* article-detail.css:42 */

@media (max-width: 1100px) {
  .e-con.about-hero   { padding: 72px 32px 56px; }  /* about.css:758 */
  .e-con.contact-hero { padding: 72px 32px; }       /* contact.css:371 */
}
@media (max-width: 1000px) {
  .e-con.art          { padding: 16px 32px 56px; }  /* article-detail.css:306 */
}
@media (max-width: 700px) {
  .e-con.about-hero   { padding: 56px 20px 44px; }  /* about.css:779 */
  .e-con.contact-hero { padding: 56px 20px 48px; }  /* contact.css:378 */
}
@media (max-width: 640px) {
  .e-con.art          { padding: 12px 20px 44px; }  /* article-detail.css:311 */
}

/* ───────────────────────────────────────────────────────────
   Hello Elementor's <button> reset bleeding into the design.

   hello-elementor 3.4.4 ships assets/css/reset.css (minified), containing:

     [type=button],[type=submit],button {
       background-color: transparent; border: 1px solid #c36;
       border-radius: 3px; color: #c36; padding: .5rem 1rem;
       font-size: 1rem; font-weight: 400; text-align: center;
       transition: all .3s; white-space: nowrap; }
     [type=button]:hover,[type=submit]:hover,button:hover,
     …:focus { background-color: #c36; color: #fff; }

   (3.4.3 had the same rules inline in style.css.)

   The design was authored without Hello in the page, so every property it left
   alone now takes Hello's value — pink hovers and a 3px radius on buttons whose
   corner is cut with clip-path.

   These use !important deliberately. The plain-specificity version of this file
   was losing: reset.css is a separate stylesheet whose load order relative to
   ours is not guaranteed, and `button:hover` (0,1,1) outranks a bare
   `.svc-nav:hover` (0,1,0) for any property the design's own hover rule does
   not declare. Forcing them is the only order-independent fix.

   Each rule re-states ONLY what the audit showed leaking, using the design's
   own value — nothing here invents styling.
   ─────────────────────────────────────────────────────────── */

/* The brand buttons cut their corner with clip-path and never declare a radius,
   so Hello's 3px rounds the cut. */
.btn-primary,
.btn-download,
.btn-contact,
.btn-call,
.btn-submit,
.view-all,
.wp-btn,
.sol-card-btn,
.svc-nav,
.lang-btn,
.htl-nav,
.art-chip,
.svc-toggle,
.custom-select-trigger,
.fpi-slider-btn {
  border-radius: 0 !important;
}

/* Icon-only buttons: the design relies on its own `* { padding: 0 }` reset,
   which Hello's element selector outranks. */
.svc-nav,
.nav-burger,
.htl-nav,
.svc-toggle,
.fpi-slider-btn {
  padding: 0 !important;
}

/* ── Hover / focus: undo Hello's pink, restore the design's own values ── */

/* The primary CTA. styles.css:1136 inverts it on hover — white fill, cyan text
   and border. `.btn-primary` is a <button> in the hero, so Hello's
   `button:hover { background-color:#c36; color:#fff }` competes with it, and
   `:focus` was never answered by the design at all. */
.btn-primary:hover,
.btn-primary:focus,
.btn-download:hover,
.btn-download:focus,
.wp-btn:hover,
.wp-btn:focus {
  background: #fff !important;
  color: #2295C4 !important;
  border-color: #2295C4 !important;
}

/* .view-all is NOT the same: styles.css:1305 overrides the rule above (same
   specificity, later in the file) so the button itself goes transparent with
   white text and the cyan fill is drawn by ::before at :1313. Forcing the
   white-fill values here would invert it. */
.view-all:hover,
.view-all:focus,
.jmac01-imported .know .section-header .view-all:hover,
.jmac01-imported .know .section-header .view-all:focus {
  background-color: transparent !important;
  background-image: none !important;
  color: #fff !important;
  border-color: transparent !important;
}

.view-all:hover::before,
.view-all:focus::before,
.jmac01-imported .know .section-header .view-all:hover::before,
.jmac01-imported .know .section-header .view-all:focus::before {
  background: var(--cyan) !important;
}

/* Fill comes from ::before; the button itself stays transparent. */
.svc-nav:hover,
.svc-nav:focus {
  background-color: transparent !important;
}

/* Design's hover sets colour only, leaving the background to the normal rule. */
.lang-btn:hover,
.lang-btn:focus {
  background-color: transparent !important;
}

/* The switcher is an <a> once Polylang drives it, and styles.css:651 only ever
   answered a <button> — so the link arrived underlined and in the theme's link
   colour. These hand back what the button already had. */
a.lang-btn {
  text-decoration: none;
}

a.lang-btn:hover,
a.lang-btn:focus {
  text-decoration: none;
}

/* Design's hover sets background + border-color, but not colour. */
.nav-burger:hover,
.nav-burger:focus {
  color: var(--navy) !important;
}

/* Design styles only ::before on hover. */
.htl-nav:hover,
.htl-nav:focus {
  background-color: transparent !important;
  color: #fff !important;
}

/* Design's hover recolours the text and flips ::before; the base fill stays. */
.btn-call:hover,
.btn-call:focus {
  background-color: var(--btn-call-bg) !important;
}

/* No hover rule in the design at all — hold the normal state. */
.svc-toggle:hover,
.svc-toggle:focus {
  background: none !important;
  color: var(--cyan) !important;
}

.custom-select-trigger:hover,
.custom-select-trigger:focus {
  background: var(--navy-soft) !important;
  color: var(--ink) !important;
}

/* ───────────────────────────────────────────────────────────
   Insights cards: photo and title are links.

   The design's `.know-item` is a plain <article> with no anchor anywhere, so
   nothing in styles.css styles a link inside it. Once the cards are driven by
   real posts they have to be clickable, so `.tag-photo` is emitted as an <a>
   and the heading text is wrapped in one.

   `.tag-photo` needs nothing but its own class (it is already display:block at
   styles.css:6293) — but both anchors would otherwise pick up Hello
   Elementor's link colour and underline, which the design never accounts for.
   These rules only hand back the values the surrounding text already has.
   ─────────────────────────────────────────────────────────── */
.jmac01-imported .know-item a.tag-photo {
  text-decoration: none;
}

.jmac01-imported .know-item h2 .know-title-link,
.jmac01-imported .know-item h3 .know-title-link,
.jmac01-imported .know-item h4 .know-title-link,
.jmac01-imported .know-item h5 .know-title-link,
.jmac01-imported .know-item h6 .know-title-link {
  color: inherit;
  text-decoration: none;
  background: none;
}

.jmac01-imported .know-item .know-title-link:hover,
.jmac01-imported .know-item .know-title-link:focus {
  color: var(--cyan);
  text-decoration: none;
}

/* ───────────────────────────────────────────────────────────
   Decorative graphics now come from the Media Library.

   The design's stylesheets load these from inside the plugin — e.g.
   service.css:101 gives `.burst-banner::before` a background-image of
   `../images/element.png`. Those files are no longer shipped, so each widget
   exposes a Media control and writes the chosen URL inline.

   `.burst-banner::before` is the one that cannot be reached that way: a
   pseudo-element takes no inline style. The widget therefore sets
   `--jmac-burst-graphic` on `.burst-banner` itself, and this rule hands it
   down. With no image chosen the property is unset and `none` applies, which
   is the same thing the missing file produced — just without the 404.
   ─────────────────────────────────────────────────────────── */
.burst-banner::before {
  background-image: var(--jmac-burst-graphic, none);
}

/* ───────────────────────────────────────────────────────────
   Category icons as uploaded SVGs.

   `.know-avatar` is a 42px gradient tile that centres a Tabler `<i>` in white
   (styles.css:8080). An uploaded icon goes in the same tile, so it needs a size
   of its own — an <img> has no font-size to inherit — and the same white.

   `brightness(0) invert(1)` flattens any artwork to white, which is what the
   design's glyph is. It costs nothing when the SVG is already white, and saves
   having to re-export a file that isn't.
   ─────────────────────────────────────────────────────────── */
.jmac01-imported .know-avatar img {
  width: 22px;
  height: 22px;
  object-fit: contain;
  filter: brightness(0) invert(1);
}

/* ───────────────────────────────────────────────────────────
   Two services on one case card.

   `.prod-case-tag` is `align-self: flex-start` inside `.prod-case-body`, a flex
   column (case-study-production.css:206) — the design only ever shows one, so a
   second chip would drop onto its own line. A case study can deliver more than
   one service, so the chips get a wrapper that lays them out the way `.cs-tags`
   (case-study-factory.css:96) already does. The chip itself is untouched.
   ─────────────────────────────────────────────────────────── */
.prod-case-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-self: flex-start;
  margin: 0 0 14px;
}

.prod-case-tags .prod-case-tag {
  margin: 0;
}

/* ───────────────────────────────────────────────────────────
   Elementor's Post Content widget inside `.art`.

   Services and case studies are laid out per post in Elementor, so they use
   Elementor's own Post Content widget rather than the Article Body widget. But
   article-detail.css styles the article by CLASS — `.art-lead:152`,
   `.art-h2:158`, `.art-quote:170`, `.art-list:182` — and the only element-based
   rule is `.art-main > p:145`, which needs `<p>` to be a direct child of
   `.art-main`.

   Post Content emits bare `<p>`, `<h2>`, `<blockquote>`, `<ul>` wrapped in
   Elementor's own container, so none of those rules match and the text renders
   unstyled. These rules re-state the design's own values against the bare
   elements, scoped to `.art` so nothing leaks into the rest of the site.

   No rule here invents a value; each one is copied from the class it mirrors.
   The design defines no h3–h6, so those are deliberately left alone — use H2,
   or add the class by hand in the editor.
   ─────────────────────────────────────────────────────────── */
.art .elementor-widget-theme-post-content .elementor-widget-container > p {
  font-size: 18px;                    /* article-detail.css:145 */
  line-height: 1.95;
  color: var(--ink-2);
  margin: 0 0 22px;
}

.art .elementor-widget-theme-post-content .elementor-widget-container > p:last-child {
  margin-bottom: 0;                   /* article-detail.css:151 */
}

.art .elementor-widget-theme-post-content .elementor-widget-container > h2 {
  font-family: var(--displayfont);    /* article-detail.css:158 */
  font-size: clamp(22px, 2.4vw, 28px);
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.3;
  color: var(--cyan-deep);
  margin: 12px 0 18px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--navy-soft);
}

.art .elementor-widget-theme-post-content .elementor-widget-container > blockquote {
  margin: 30px 0;                     /* article-detail.css:170 */
  padding: 22px 28px;
  border-left: 4px solid var(--cyan);
  background: var(--navy-soft);
  font-family: var(--displayfont);
  font-size: 22px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--navy);
}

.art .elementor-widget-theme-post-content .elementor-widget-container > ul {
  margin: 0 0 22px;                   /* article-detail.css:182 */
  padding: 0;
  list-style: none;
  display: grid;
  gap: 12px;
}

.art .elementor-widget-theme-post-content .elementor-widget-container > ul > li {
  position: relative;                 /* article-detail.css:189 */
  padding-left: 24px;
  font-size: 18px;
  line-height: 1.8;
  color: var(--ink-2);
}

.art .elementor-widget-theme-post-content .elementor-widget-container > ul > li::before {
  content: '';                        /* article-detail.css:196 */
  position: absolute;
  left: 0;
  top: 12px;
  width: 8px;
  height: 8px;
  background: var(--cyan);
  transform: rotate(45deg);
}

/* An <ol> has no counterpart in the design at all. Numbering is left to the
   browser; only the text metrics are matched so it sits with the paragraphs. */
.art .elementor-widget-theme-post-content .elementor-widget-container > ol {
  margin: 0 0 22px;
  padding-left: 24px;
}

.art .elementor-widget-theme-post-content .elementor-widget-container > ol > li {
  font-size: 18px;
  line-height: 1.8;
  color: var(--ink-2);
  margin-bottom: 12px;
}

/* ───────────────────────────────────────────────────────────
   Case-study body text when `cs-block` is on a Container.

   case-study-factory.css:88 styles article text as `.cs-block > p`. With the
   class on an Elementor Container, a paragraph from a Text Editor or Post
   Content widget is a great-grandchild — the direct-child selector never fires
   and the body renders at the browser default.

   Same intent, deep enough to reach through Elementor's two wrappers. The
   `.cs-` exclusions keep the blocks that style their own paragraphs — the quote,
   the stat description, the vision line — off this rule.
   ─────────────────────────────────────────────────────────── */
.e-con.cs-block p:not([class*="cs-"]) {
  font-size: 20px;                     /* case-study-factory.css:88 */
  line-height: 1.95;
  color: var(--ink-2);
  margin: 0 0 20px;
}

@media (max-width: 640px) {
  .e-con.cs-block p:not([class*="cs-"]) { font-size: 18px; }  /* :463 */
}

/* The design's own vertical rhythm between blocks (:86). Elementor's container
   gap would otherwise decide it. */
.e-con.cs-block {
  --display: block !important;
  --gap: 0px !important;
  --row-gap: 0px !important;
  display: block !important;
  margin-top: 40px;
}

.e-con.cs-block:first-of-type {
  margin-top: 0;
}

/* ───────────────────────────────────────────────────────────
   Contact Form 7's markup wearing the design's clothes.

   The design writes each option as `<label class="cf-radio">` around the input
   (contact.html:340). CF7 generates its own nesting instead —

     span.wpcf7-radio > span.wpcf7-list-item > label > input + span.wpcf7-list-item-label

   — so `.cf-radio` matches nothing and the options render as a default inline
   run. These map CF7's classes onto the design's rules rather than restyling
   anything: every value is copied from contact.css:412-424.

   The custom dropdown in the design is a button-plus-listbox that only its own
   JS can build. CF7 emits a real `<select>`, which is better for accessibility
   anyway, so it is styled to match the trigger instead of being replaced.
   ─────────────────────────────────────────────────────────── */
/* ── The two sub-dropdowns sit between the radios ──
   The design puts a dropdown directly under the first option and another under
   the second (contact.html:339-384). CF7 renders all seven options from a single
   [radio] tag as one block, so anything written after it lands after all seven.

   The options cannot be split across several [radio] tags either: CF7 rejects two
   fields with the same name, and the group has to stay one field to submit one
   answer.

   An earlier attempt dissolved CF7's wrappers with `display: contents` and
   re-sequenced everything with `order`. It depended on CF7's exact nesting and on
   the option count never changing, and it broke. main.js moves the two divs into
   place instead — one DOM operation, no assumptions about markup depth. All that
   is left here is the column layout they land in. */
.cf-subject .cf-subject-options,
.cf-subject .wpcf7-radio {
  display: flex;
  flex-direction: column;              /* contact.css:412 */
  gap: 12px;
}

.cf-subject .wpcf7-list-item {
  margin: 0;
}

/* contact.css:424 — the dropdown is indented under the option above it. */
.cf-subject .cf-subselect {
  max-width: 420px;
  padding-left: 26px;
}

@media (max-width: 600px) {
  .cf-subject .cf-subselect {
    max-width: none;
    padding-left: 0;
  }
}

.cf-subject .wpcf7-list-item label {
  display: inline-flex;                /* contact.css:413 */
  align-items: baseline;
  gap: 10px;
  font-size: 17px;
  color: var(--ink-2);
  cursor: pointer;
  width: fit-content;
}

.cf-subject .wpcf7-list-item input[type="radio"] {
  accent-color: var(--cyan);           /* contact.css:422 */
  transform: translateY(2px);
  cursor: pointer;
}

/* Revealed by the subject handler in main.js; hidden until then. */
.cf-subselect[hidden] {
  display: none !important;
}

/* CF7's own validation chrome. The design has no equivalent — it never had
   server-side validation — so these only make the messages legible in place
   rather than inventing a look for them. */
.contact-form-col .wpcf7-not-valid-tip {
  display: block;
  margin-top: 6px;
  font-size: 14px;
  color: #c0392b;
}

.contact-form-col .wpcf7-not-valid {
  border-color: #c0392b !important;
}

.contact-form-col .wpcf7-response-output {
  margin: 20px 0 0;
  padding: 12px 16px;
  border-width: 1px;
  border-style: solid;
  font-size: 15px;
}

/* CF7 wraps every control in a span that defaults to inline, which collapses
   the field to its content width instead of filling the column. */
.contact-form-col .wpcf7-form-control-wrap {
  display: block;
  width: 100%;
}

.cf-subselect select,
.contact-form-col select {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border-2);
  border-radius: 0;
  background: #fff;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}

/* ───────────────────────────────────────────────────────────
   The copy-link control is a <button>, not an <a>.

   Copying is a clipboard action, so it cannot be a link — but it sits in a row
   of two anchors and has to look identical.

   article-detail.css:231-258 styles the share row entirely through `.art-share a`
   — the 40px box, the border, and crucially `.art-share a .art-ico`, which is the
   only rule giving the icon a size. A <button> matched none of them, so the box
   vanished and the SVG fell back to its intrinsic size. Restated here against the
   button, using the design's own values, so the three controls stay identical.
   ─────────────────────────────────────────────────────────── */
.art-share button.art-share-copy {
  width: 40px;
  height: 40px;
  display: inline-grid;
  place-items: center;
  overflow: hidden;
  background: none !important;
  border: 1px solid var(--border-2) !important;
  border-radius: 0 !important;
  padding: 0 !important;
  color: var(--navy) !important;
  font-size: 22px;
  cursor: pointer;
  transition: background .2s, color .2s, border-color .2s;
}

.art-share button.art-share-copy:hover,
.art-share button.art-share-copy:focus {
  background: var(--navy) !important;
  color: #fff !important;
  border-color: var(--navy) !important;
}

.art-share button.art-share-copy .art-ico {
  width: auto;
  height: 20px;                        /* article-detail.css:252 */
  max-width: 24px;
  display: block;
  margin: 0 auto;
  object-fit: contain;
  transition: filter .2s;
}

.art-share-copied {
  margin-left: 8px;
  font-size: 14px;
  color: var(--cyan-deep);
  white-space: nowrap;
}

/* ───────────────────────────────────────────────────────────
   Rich text in a service card description.

   factory-productivity-improvement.css:223 sets `margin: 0` on
   `.svcsol-card-desc` because the design writes it as a single `<p>`. It is a
   `<div>` now so the editor's own paragraphs can live inside it — and those
   arrive with the browser's default 1em margins, which pushes the first line
   down and the last line past the card's padding.

   The spacing is restated on the children instead, so a one-paragraph
   description sits exactly where it did and a longer one still reads as
   paragraphs. Everything else about the block is untouched.
   ─────────────────────────────────────────────────────────── */
.svcsol-card-desc > p {
  margin: 0 0 14px;
}

.svcsol-card-desc > p:last-child,
.svcsol-card-desc > ul:last-child,
.svcsol-card-desc > ol:last-child {
  margin-bottom: 0;
}

.svcsol-card-desc > ul,
.svcsol-card-desc > ol {
  margin: 0 0 14px;
  padding-left: 22px;
}

.svcsol-card-desc > ul > li,
.svcsol-card-desc > ol > li {
  margin-bottom: 6px;
}

/* ───────────────────────────────────────────────────────────
   The load-more button really hides when there is nothing more.

   `hidden` is honoured by a UA rule of the form `[hidden] { display: none }`,
   which any author `display` declaration outranks — and article.css:273 gives
   `.article-more` `display: flex`. So the attribute was set correctly and had
   no effect: three posts, nine per page, and the button still showed.

   contact.css:260 already answers this the same way for its own panels.
   ─────────────────────────────────────────────────────────── */
.article-more[hidden] {
  display: none !important;
}

/* ───────────────────────────────────────────────────────────
   Insight gallery panels are clickable.

   insight.css:89 gives `.gallery-panel` `cursor: pointer`, so the whole tile is
   meant to be a link — but the design never put an anchor on it, only on the
   button, so clicking the image did nothing. The panel's `<img>` is sized
   `width:100%; height:100%` against the panel itself (insight.css:95), so
   wrapping it in an anchor would collapse it. This covers the tile instead.

   It sits before `.gallery-panel-text` in the markup, and both are positioned,
   so the text and its button paint on top and keep their own click targets.
   ─────────────────────────────────────────────────────────── */
.gallery-panel-cover {
  position: absolute;
  inset: 0;
  display: block;
  text-decoration: none;
}

/* ───────────────────────────────────────────────────────────
   Per-category icon on an article card.

   `.article-avatar` is a 38px gradient tile centring a Tabler glyph at 18px
   (article.css:247). An uploaded SVG has no font-size to inherit, so it needs a
   size of its own, and `brightness(0) invert(1)` flattens it to the white the
   glyph already was. Same treatment as `.know-avatar img` above.
   ─────────────────────────────────────────────────────────── */
.article-avatar img {
  width: 20px;
  height: 20px;
  object-fit: contain;
  filter: brightness(0) invert(1);
}

/* ───────────────────────────────────────────────────────────
   The same icon on the article page's own avatar.

   `.art-avatar` is the odd one out: `background: var(--cyan-soft)` with
   `color: var(--cyan-deep)` (article-detail.css:85) — a LIGHT tile, where the
   two card avatars are dark gradients. The white icon that reads on those
   disappears here, and `brightness(0) invert(1)` would only make it whiter.

   Masking sidesteps the file's own colour entirely: only its alpha channel is
   used, and the paint comes from `currentColor`, which the tile already sets.
   One upload then works on both light and dark tiles. Monochrome artwork only —
   a multi-colour logo would flatten to a silhouette.
   ─────────────────────────────────────────────────────────── */
.art-avatar-icon {
  display: block;
  width: 24px;
  height: 24px;
  background-color: currentColor;
  -webkit-mask: var(--jmac-icon) center / contain no-repeat;
  mask: var(--jmac-icon) center / contain no-repeat;
}

/* ───────────────────────────────────────────────────────────
   TH Sarabun New inside the article and service body.

   article-detail.css:20-27 switches the font by rebinding custom properties on
   `.art` and setting `font-family: var(--sans-th)` — with no !important, because
   the design was authored without a site-wide font rule in the page.

   The site now carries one:

     body, h1…h6, p, span:not(.fa):not(.ab-icon), button, label, a p, strong,
     input, div, .elementor-image-box-title { font-family:'Noto Sans Thai' !important }

   An !important declaration beats a normal one outright, so every element
   inside `.art` reverts to Noto Sans Thai and the article loses its typeface.

   Specificity is what settles two !important rules, so these have to outrank
   the ones above — `span:not(.fa):not(.ab-icon)` is (0,2,1), so the `body`
   prefix here takes the span rule to (0,2,2) and wins deterministically,
   whatever order the stylesheets load in.

   `.service-content` is the class put on the Elementor container that holds a
   service body, and `.jmac-sarabun` is the general-purpose version: put it on
   any Elementor container and everything inside switches typeface. Both need
   the same treatment for the same reason.

   `.cs` and `.cs-block` are the case-study equivalent. case-study-factory.css:483
   binds the typeface on `:root`, which works when that stylesheet is the only one
   on the page but loses outright to a site-wide !important font rule — so the
   case study rendered in the wrong face with nothing obviously wrong to look at.
   Scoped here the same way, so it needs no class of its own.
   ─────────────────────────────────────────────────────────── */
body .cs,
body .e-con.cs-block,
body .art,
body .art h1, body .art h2, body .art h3,
body .cs h1, body .cs h2, body .cs h3,
body .art h4, body .art h5, body .art h6,
body .cs h4, body .cs h5, body .cs h6,
body .art p, body .art div, body .art li,
body .cs p, body .cs div, body .cs li,
body .art strong, body .art b, body .art em,
body .cs strong, body .cs b, body .cs em,
body .art blockquote, body .art cite, body .art a,
body .cs blockquote, body .cs cite, body .cs a,
body .art td, body .art th, body .art figcaption,
body .cs td, body .cs th, body .cs figcaption,
body .art span:not(.ti):not([class*=" ti-"]):not([class^="ti-"]),
body .cs span:not(.ti):not([class*=" ti-"]):not([class^="ti-"]),
body .service-content,
body .jmac-sarabun,
body .service-content h1, body .service-content h2, body .service-content h3,
body .jmac-sarabun h1, body .jmac-sarabun h2, body .jmac-sarabun h3,
body .service-content h4, body .service-content h5, body .service-content h6,
body .jmac-sarabun h4, body .jmac-sarabun h5, body .jmac-sarabun h6,
body .service-content p, body .service-content div, body .service-content li,
body .jmac-sarabun p, body .jmac-sarabun div, body .jmac-sarabun li,
body .service-content strong, body .service-content b, body .service-content em,
body .jmac-sarabun strong, body .jmac-sarabun b, body .jmac-sarabun em,
body .service-content blockquote, body .service-content cite, body .service-content a,
body .jmac-sarabun blockquote, body .jmac-sarabun cite, body .jmac-sarabun a,
body .service-content td, body .service-content th, body .service-content figcaption,
body .jmac-sarabun td, body .jmac-sarabun th, body .jmac-sarabun figcaption,
body .service-content span:not(.ti):not([class*=" ti-"]):not([class^="ti-"]),
body .jmac-sarabun span:not(.ti):not([class*=" ti-"]):not([class^="ti-"]) {
  font-family: 'TH Sarabun New', 'Noto Sans Thai', system-ui, sans-serif !important;
}

/* Form and disclosure elements. The site-wide rule names `button, label, input`
   explicitly, and the FAQ accordion's question is a `<summary>` — none of which
   the element list above covers, so those stayed on the other typeface while the
   text around them changed. `.faq-list` was the visible symptom. */
body .art summary, body .art button, body .art label,
body .cs summary, body .cs button, body .cs label,
body .art input, body .art textarea, body .art select,
body .cs input, body .cs textarea, body .cs select,
body .art dt, body .art dd, body .art small, body .art time, body .art figure,
body .cs dt, body .cs dd, body .cs small, body .cs time, body .cs figure,
body .service-content summary, body .service-content button, body .service-content label,
body .service-content input, body .service-content textarea, body .service-content select,
body .service-content dt, body .service-content dd, body .service-content small,
body .service-content time, body .service-content figure,
body .jmac-sarabun summary, body .jmac-sarabun button, body .jmac-sarabun label,
body .jmac-sarabun input, body .jmac-sarabun textarea, body .jmac-sarabun select,
body .jmac-sarabun dt, body .jmac-sarabun dd, body .jmac-sarabun small,
body .jmac-sarabun time, body .jmac-sarabun figure {
  font-family: 'TH Sarabun New', 'Noto Sans Thai', system-ui, sans-serif !important;
}

/* ───────────────────────────────────────────────────────────
   The case-study widgets carry the typeface themselves.

   `.cs` and `.cs-block` above only help once someone puts those classes on a
   Container, and a case study assembled from individual widgets has neither —
   so `.cs-tags` and everything else rendered outside a wrapper stayed on the
   other face with nothing to hint why.

   Elementor stamps `elementor-widget-<name>` on every widget, so the case-study
   widgets can be addressed directly. They only ever appear on a case study, so
   this needs no page-level class and cannot leak anywhere else.

   `.burst-banner` is deliberately NOT here: it is shared with the service pages,
   where the design keeps Noto Sans Thai. Put `jmac-sarabun` on the container
   holding it when a case study uses one.
   ─────────────────────────────────────────────────────────── */
body [class*="elementor-widget-jmac_cs_"],
body [class*="elementor-widget-jmac_cs_"] *:not(.ti):not([class*=" ti-"]):not([class^="ti-"]),
body .elementor-widget-jmac_case_study_tags,
body .elementor-widget-jmac_case_study_tags *:not(.ti):not([class*=" ti-"]):not([class^="ti-"]),
body .elementor-widget-jmac_case_study_article,
body .elementor-widget-jmac_case_study_article *:not(.ti):not([class*=" ti-"]):not([class^="ti-"]) {
  font-family: 'TH Sarabun New', 'Noto Sans Thai', system-ui, sans-serif !important;
}

/* The Tabler glyphs are an icon font — forcing a text face on them prints
   tofu instead of the icon, so they are excluded above and restated here. */
body [class*="elementor-widget-jmac_cs_"] .ti,
body [class*="elementor-widget-jmac_cs_"] i[class*="ti-"],
body .elementor-widget-jmac_case_study_tags .ti,
body .elementor-widget-jmac_case_study_article .ti,
body .elementor-widget-jmac_case_study_article i[class*="ti-"],
body .art .ti,
body .cs .ti,
body .art i[class*="ti-"],
body .cs i[class*="ti-"],
body .service-content .ti,
body .jmac-sarabun .ti,
body .service-content i[class*="ti-"],
body .jmac-sarabun i[class*="ti-"] {
  font-family: 'tabler-icons' !important;
}

/* Elementor style controls are emitted with !important too (see
   trait-controls.php), and their selectors carry the widget wrapper — so a
   control the editor actually sets still beats everything above. */
