/*
 * Theme-extra.css — small additions layered on top of the ported
 * main.css / inner-pages.css / premium-enhancements.css:
 *  1) core/media-text "Reveal Split" block style alias (the alternating
 *     image/text pattern reused 3-4x on every service page).
 *  2) Front-end fallback styling for the 3 custom blocks' wrapper markup.
 *  3) Minor consistency fixes agreed during the WP port (single logo,
 *     single brand palette — the palette fix itself lives in the Customizer
 *     CSS output, see inc/customizer.php).
 */

/* ---------- core/media-text "Reveal Split" style ---------- */
.wp-block-media-text.is-style-reveal-split {
	display: grid;
	grid-template-columns: 1.1fr 0.9fr;
	gap: 80px;
	align-items: center;
}
.wp-block-media-text.is-style-reveal-split.has-media-on-the-right {
	grid-template-columns: 0.9fr 1.1fr;
}
.wp-block-media-text.is-style-reveal-split .wp-block-media-text__media {
	position: relative;
	border-radius: 12px;
	overflow: hidden;
	box-shadow: 0 20px 40px -15px rgba(17, 24, 39, 0.1);
	background-color: var(--color-surface);
}
.wp-block-media-text.is-style-reveal-split .wp-block-media-text__media img {
	width: 100%;
	height: auto;
	display: block;
	object-fit: cover;
	transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
	margin: 0;
}
.wp-block-media-text.is-style-reveal-split .wp-block-media-text__media:hover img {
	transform: scale(1.03);
}
.wp-block-media-text.is-style-reveal-split .wp-block-media-text__content {
	padding: 0 0 0 0;
}
.wp-block-media-text.is-style-reveal-split .wp-block-media-text__content p {
	font-size: 20px;
	line-height: 1.6;
	color: var(--color-text);
	font-weight: 400;
	letter-spacing: -0.01em;
}
@media (max-width: 992px) {
	.wp-block-media-text.is-style-reveal-split,
	.wp-block-media-text.is-style-reveal-split.has-media-on-the-right {
		grid-template-columns: 1fr;
		gap: 40px;
	}
	/* Core WP always pins .wp-block-media-text__media to grid-column: 2
	   when has-media-on-the-right is present, regardless of how many
	   explicit columns the container defines above. Without also
	   resetting that here, the browser creates an implicit, auto-sized
	   second column to satisfy it — starving the text column down to
	   near-zero width and forcing it to wrap one character per line. */
	.wp-block-media-text.is-style-reveal-split .wp-block-media-text__media,
	.wp-block-media-text.is-style-reveal-split .wp-block-media-text__content {
		grid-column: 1;
		grid-row: auto;
	}
}

/* ---------- Custom block front-end wrappers ---------- */
.software-split-wrapper { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: start; }
@media (max-width: 900px) { .software-split-wrapper { grid-template-columns: 1fr; } }
.sw-showcase-img { width: 100%; height: auto; display: block; transition: opacity 0.2s ease; }
.sw-fade-out { opacity: 0; }

/* ---------- Region-switch safety net ---------- */
.rc-region-hidden { display: none !important; }

/* ---------- Sector Card Grid ("Service Coverage") image accommodation ----------
   .sc-card-media is styled (in inner-pages.css) as position:absolute; inset:0
   with background-size:cover — designed for a plain div with an inline
   background-image. The block editor's native Image block gives an
   editable <figure><img/></figure> instead, which is the whole point (an
   editor can swap the image without touching code) — this just makes that
   figure/img fill the same absolutely-positioned box the same way a CSS
   background-image would. */
.sc-card-media.wp-block-image {
	position: absolute;
	inset: 0;
	z-index: -2;
	margin: 0;
}
.sc-card-media.wp-block-image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.7s var(--ease-out, ease);
}
.sc-card:hover .sc-card-media.wp-block-image img {
	transform: scale(1.08);
}
/* core/button's className always lands on the wrapping .wp-block-button
   div, never the inner <a> — .sc-card-btn's own rules (in inner-pages.css)
   assume they're directly on the clickable anchor, so re-target the real
   link element here instead of fighting core's default button styling. */
.sc-card-body .wp-block-button.sc-card-btn {
	width: 100%;
	margin-top: 0.6rem;
}
.sc-card-body .wp-block-button.sc-card-btn .wp-block-button__link {
	width: 100%;
	border: none;
	cursor: pointer;
	background: #ffffff;
	color: #0b1512;
	font-weight: 700;
	font-size: 0.9rem;
	padding: 0.85rem 1rem;
	border-radius: 100px;
	text-align: center;
	transition: transform 0.3s var(--ease-out, ease), background-color 0.3s ease, box-shadow 0.3s ease;
}
.sc-card-body .wp-block-button.sc-card-btn .wp-block-button__link:hover {
	background: var(--color-accent);
	color: #06120c;
	transform: translateY(-2px);
	box-shadow: 0 10px 24px -10px rgba(var(--color-accent-rgb), 0.6);
}

/* ---------- Homepage sector-card & home-split buttons ----------
   Same wrapper-vs-anchor problem again: core/button puts the author's
   className on the wrapping .wp-block-button div, so the theme's own
   .btn-sector-explore / .home-outline-btn rules (written for a bare <a>)
   land on the wrapper while core's default dark pill styling stays on the
   inner <a> — producing a dark pill nested inside the themed one. Reset
   the inner link and let the wrapper keep its own look. */
.wp-block-button.btn-sector-explore .wp-block-button__link,
.wp-block-button.home-outline-btn .wp-block-button__link {
	background: transparent !important;
	background-color: transparent !important;
	color: inherit !important;
	border: none;
	border-radius: inherit;
	padding: 0;
	font: inherit;
	letter-spacing: inherit;
	text-decoration: none;
}
/* The wrapper is what actually draws each button, so give it the padding
   the inner link no longer has. */
.wp-block-button.btn-sector-explore,
.wp-block-button.home-outline-btn {
	display: inline-flex;
	align-items: center;
}

/* Same wrapper-vs-anchor situation as .sc-card-btn above, for the
   Residential/Commercial cross-link callout's "explore-btn" pill button. */
.wp-block-button.explore-btn .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	background: linear-gradient(135deg, var(--color-accent) 0%, var(--color-accent-hover) 100%);
	color: #ffffff;
	padding: 16px 28px;
	border-radius: 30px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.5px;
	transition: transform 0.2s ease, opacity 0.2s ease;
}
.wp-block-button.explore-btn .wp-block-button__link:hover {
	transform: translateY(-2px);
	opacity: 0.95;
}

/* ==========================================================================
   CARD ICON BLOCK — media-library icons at the template's fixed size

   The realcognita/card-icon block lets an editor replace a card's built-in
   inline SVG with an SVG or PNG from the media library. inner-pages.css
   sizes only the `svg` child of each icon wrapper, so a chosen <img> would
   otherwise render at whatever pixel dimensions it was uploaded at and blow
   the card layout apart. These mirror each wrapper's own svg size, so the
   icon is always the template size regardless of the source file.

   object-fit: contain keeps a non-square PNG in proportion inside the box.
   ========================================================================== */
.rcn-card-icon-img {
	display: block !important;
	object-fit: contain !important;
	max-width: none !important;
}

.support-card-icon .rcn-card-icon-img { width: 22px !important; height: 22px !important; }
.impact-card-icon  .rcn-card-icon-img { width: 24px !important; height: 24px !important; }
.engagement-icon   .rcn-card-icon-img { width: 22px !important; height: 22px !important; }
.role-card-icon    .rcn-card-icon-img { width: 20px !important; height: 20px !important; }
.growth-card-icon  .rcn-card-icon-img { width: 24px !important; height: 24px !important; }

/* The default inline SVG is wrapped in a span in the editor preview; make
   that span transparent to layout so the svg still centres in its box. */
.rcn-card-icon-default {
	display: contents;
}

/* ==========================================================================
   SERVICE COVERAGE CARD BUTTON — strip the outer pill

   The anchor is already restyled above (see .sc-card-body .wp-block-button
   .sc-card-btn .wp-block-button__link). What was still missing: the WRAPPER
   also paints itself, because .sc-card-btn in inner-pages.css was written
   for the dev site where that class sits on the anchor itself, so it styles
   whatever carries it. On WordPress the class lands on the wrapping
   .wp-block-button div, so both were painted — measured as a 202x74 white
   pill containing a 170x47 white pill, 25px taller than the dev reference's
   single 202x49 anchor.

   Only the wrapper's paint is removed here; its width and top margin stay.
   ========================================================================== */
.sc-card .sc-card-btn,
.sc-card-body .wp-block-button.sc-card-btn {
	background: none !important;
	background-color: transparent !important;
	padding: 0 !important;
	border: none !important;
	border-radius: 0 !important;
	box-shadow: none !important;
	transform: none !important;
}

/* The dev anchor is display:block; core's is inline-block, which adds the
   inline baseline gap and rendered 2px shorter (47px against the
   reference's 49px). */
.sc-card .sc-card-btn .wp-block-button__link {
	display: block !important;
}

/* ==========================================================================
   REGION-HIDDEN DRAWER LINKS
   main.css sets `nav#mobileDrawer .drawer-link { display: block !important }`.
   That selector carries an ID, so its specificity (1,1,1) beats the region
   system's `.rc-region-hidden { display: none !important }` (0,1,0) — both are
   !important, so specificity decides and the drawer link always won. The
   effect: an AU-only service (HVAC Drafting & Detailing) could not be hidden
   in the mobile drawer and showed up in US mode pointing at an /au/ URL.

   Matching the ID selector and adding the state class puts this at (1,2,1),
   which wins. Kept here rather than editing main.css because that file is
   shared with the static dev site.
   ========================================================================== */
.mobile-drawer .drawer-link.rc-region-hidden,
nav#mobileDrawer .drawer-link.rc-region-hidden {
  display: none !important;
}

/* ==========================================================================
   "SOFTWARE WE WORK IN" — DARK MODE IMAGE PLATES

   The showcase images use `mix-blend-mode: multiply !important`
   (inner-pages.css). Multiply against a white plate shows an image normally;
   against a near-black plate it renders everything black, so in dark mode the
   brand logo and the sample render both disappeared.

   premium-enhancements.css already tries to fix this at line ~893
   (`[data-theme="dark"] .sw-frame--logo { background-color: #fff }`) but
   1,200 lines further down the same file sets
   `.sw-frame--logo { background-color: var(--color-bg) !important }`.
   An !important declaration beats an un-flagged one whatever the specificity,
   so the intended fix never applied — and `.sw-frame--sample` never had a
   dark-mode rule at all.

   Restoring the light plate is the minimal fix: `multiply` then behaves
   exactly as it does in light mode, so both images render identically in both
   themes without touching the blend mode or the assets.
   ========================================================================== */
[data-theme="dark"] .sw-frame--logo,
[data-theme="dark"] .sw-frame--sample {
  background-color: #ffffff !important;
  border-color: rgba(0, 0, 0, 0.10) !important;
}

/* ==========================================================================
   HOMEPAGE SECTOR CARDS — OPTIONAL BACKGROUND IMAGE

   Set from the Sector Card block's "Background image" control. The block
   passes only the image, its position and the overlay strength, as custom
   properties; the overlay itself is composed here because it has to differ
   between light and dark mode and an inline style cannot respond to the theme.

   Composed as two background LAYERS on the card, not as a pseudo-element or
   an extra wrapper div. `.sector-card` already sets `position: relative` and
   a solid `background`, and its children are plain heading/paragraph/list
   blocks with no stacking context of their own — so a `z-index: -1`
   pseudo-element would sit behind the card's own background-color and never
   be visible. Layer order, top to bottom, is: overlay, image, then the card's
   background-color underneath.

   The `!important` flags are needed, not decorative, and this was measured
   rather than assumed: inner-pages.css line ~744 carries a much older
   `.sector-card { background: transparent !important; box-shadow: none
   !important; }` from a different, 2-column sector-card component. An
   `!important` shorthand beats an un-flagged declaration at ANY specificity,
   and the `background` shorthand resets every background sub-property — so
   without these flags the image, size, position and repeat were all silently
   discarded and the cards rendered with `background-image: none`.

   That old rule is NOT edited here because it is still live on the Our
   Experience page (the only other content using `.sector-card`), where the
   transparent background is what that layout expects. Scoping these rules to
   `.sectors-overview-section` keeps the fight contained to the homepage.
   ========================================================================== */
/* The photograph is NOT composed here. It is painted by the masked ::before in
   css/pages/home.css, which is what home.css's own `background-image: none
   !important` on the card assumes. This stylesheet used to paint it a second
   time as card background layers under a flat scrim; both selectors are three
   classes and both flagged, so source order alone decided it, and the two
   copies — the ::before is scaled 1.02 — sat out of register and ghosted
   against each other. One copy only, and it is the masked one, because the
   mask is what keeps the picture off the copy. */

/* ==========================================================================
   HOVER — reveal more of the photo, without losing the text

   The scrim thins on hover so the image comes forward. The block computes the
   hover value from the editor's own overlay setting (overlay x 0.7), so a
   card set to a heavy 82% resting scrim eases to ~57% and one already set
   light still moves by a visible amount.

   Thinning the scrim alone would trade legibility for atmosphere, so the text
   is pushed the other way at the same time: body copy goes to the full
   heading colour and the "Capabilities include:" label darkens from the dim
   grey it uses at rest. Contrast against the busier backdrop therefore goes
   UP as the photo comes forward, rather than down.

   The transition is declared on the resting rule, not the hover rule, so it
   applies to the pointer leaving as well as arriving.
   ========================================================================== */
.sectors-overview-section .sector-card.has-sector-bg {
  transition:
    transform 0.45s var(--ease-out, ease),
    border-color 0.45s ease;
}

/* The hover reveal lives with the picture, on the ::before in home.css
   (opacity 0.34 -> 0.46, scale 1.02 -> 1.09). */

/* ==========================================================================
   "CAPABILITIES INCLUDE:" LABEL — LIGHT MODE CONTRAST

   inner-pages.css ~6317 pins this label to the accent green with
   !important. On a dark backdrop that is fine, but in light mode it fails
   badly, and measurement is what settled it — sampled against the real
   photos, the green label scored:

       resting  1.34:1      hover  1.00:1      (WCAG AA needs 4.5:1)

   1.00 means the label and its backdrop were the same luminance: invisible.
   It also fails on the plain white card, at 2.13:1. I previously left this
   alone on the reasoning that a brand accent "stays legible over the thinned
   scrim" — the numbers and the screenshots both say otherwise.

   Fixed to the heading colour in light mode, for ALL cards in this section
   rather than only image-backed ones, because the US view shows a plain card
   and an image card side by side — giving them different label colours would
   read as a mistake.

   A darker green was tried first and rejected on measurement: to clear 4.5:1
   on white the green has to drop to about L=0.18, and at that luminance it
   still only reaches ~2.6:1 over a scrimmed photo. No single green satisfies
   both backdrops, so the label follows the text colour and the accent is
   carried by the dot bullets instead.

   Dark mode keeps the green: it measures fine there, and it is the state
   already signed off.
   ========================================================================== */
.sectors-overview-section .capabilities-heading {
  color: var(--color-heading, #0d0d0d) !important;
}

[data-theme="dark"] .sectors-overview-section .capabilities-heading {
  color: var(--color-accent, #26d07c) !important;
}

/* Dark mode keeps the green at rest (6.32:1, fine) but must drop it on hover.
   Thinning the scrim to 57% takes the green label down to 2.80:1 against the
   photo — a failure introduced by the hover reveal itself, caught only by
   re-measuring the hover state rather than the resting one. White on hover
   matches what the description and list items already do here. */
[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:hover .capabilities-heading,
[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:focus-within .capabilities-heading {
  color: #ffffff !important;
}

/* ==========================================================================
   CARD TITLE ACCENT ("Residential <span class="accent">Services</span>")

   The brand accent green measures 2.13:1 on white and 1.01:1 over a scrimmed
   photo — at 1.01 the word is the same luminance as its backdrop, i.e.
   invisible. Large text still needs 3.0:1.

   A deeper green is used rather than dropping to the heading colour, because
   measurement showed a green CAN satisfy both backdrops here even though none
   could for the smaller eyebrow label: the title is 25px/700, so it only
   needs 3.0:1 instead of 4.5:1, and that is reachable while still reading as
   green. Applied to every card in this section, not just image-backed ones,
   so the two cards sitting side by side in the US view match.

   NOTE: the same `.accent` green is used in the section heading above these
   cards and throughout the site, where it measures the same 2.13:1. That is a
   site-wide brand-contrast question, deliberately NOT changed here.
   ========================================================================== */
.sectors-overview-section .sector-card .sector-card-title .accent {
  color: #0b6b3c;
}

[data-theme="dark"] .sectors-overview-section .sector-card .sector-card-title .accent {
  color: var(--color-accent, #26d07c);
}

[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:hover .sector-card-title .accent,
[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:focus-within .sector-card-title .accent {
  color: #6ef0b0;
}

/* Text contrast compensation. Scoped to image-backed cards only — the plain
   white card has no backdrop change to compensate for, so shifting its text
   on hover would just read as a stray flicker.
 *
 * Only the description and the list items are touched, and the two themes
 * gain different amounts, which is a consequence of where each colour already
 * sits rather than an oversight:
 *
 *  - .sector-card-desc is --color-text-muted (#4a4a4a) at rest, so it has
 *    real headroom and darkens to the heading colour in light mode.
 *  - .capabilities-list li is already #0d0d0d in light mode — effectively
 *    maximum contrast — so the light-mode rule is a deliberate no-op there
 *    and the gain comes in dark mode, where it lifts #e2e8f0 to pure white.
 *
 * ".capabilities-heading" is NOT included. inner-pages.css ~6317 sets it to
 * the accent green with !important, so any rule here loses; and it should
 * lose — the green eyebrow is a deliberate brand accent, it stays legible
 * over the thinned scrim, and repainting a short uppercase label grey on
 * hover would be a regression, not a fix. Measured before removing: it
 * stayed rgb(38, 208, 124) through the whole transition. */
/* The description is --color-text-muted (#4a4a4a) by default, which is a fine
   choice on a plain white card and a poor one over a photograph: measured
   against the real images it sat at 6.00:1 at REST, clearing AA but with
   little headroom and on top of high-frequency building detail. On an
   image-backed card it takes the heading colour from the outset, so the
   resting state is comfortable rather than merely compliant. Light mode only
   — dark mode's #cbd5e1 measured 8.16:1 at rest and is already signed off. */
.sectors-overview-section .sector-card.has-sector-bg .sector-card-desc {
  color: var(--color-heading, #0d0d0d);
}

[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg .sector-card-desc {
  color: #cbd5e1;
}

.sectors-overview-section .sector-card.has-sector-bg:hover .sector-card-desc,
.sectors-overview-section .sector-card.has-sector-bg:focus-within .sector-card-desc,
.sectors-overview-section .sector-card.has-sector-bg:hover .capabilities-list li,
.sectors-overview-section .sector-card.has-sector-bg:focus-within .capabilities-list li {
  color: var(--color-heading, #0d0d0d);
}

[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:hover .sector-card-desc,
[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:focus-within .sector-card-desc,
[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:hover .capabilities-list li,
[data-theme="dark"] .sectors-overview-section .sector-card.has-sector-bg:focus-within .capabilities-list li {
  color: #ffffff;
}

.sectors-overview-section .sector-card.has-sector-bg .sector-card-desc,
.sectors-overview-section .sector-card.has-sector-bg .capabilities-list li {
  transition: color 0.45s ease;
}

/* Someone who has asked for less motion still gets the reveal — it carries
   the information — just without the animated ramp. */
@media (prefers-reduced-motion: reduce) {
  .sectors-overview-section .sector-card.has-sector-bg,
  .sectors-overview-section .sector-card.has-sector-bg .sector-card-desc,
  .sectors-overview-section .sector-card.has-sector-bg .capabilities-list li {
    transition: none;
  }
}

/* The number of visible cards in this grid changes with the region: two in
   US, one in AU (the Commercial card is US-only). `.sectors-grid` is
   `repeat(auto-fit, minmax(340px, 1fr))`, so with a single visible card that
   one card stretches across the whole row — 1344px of card holding one
   centred list, under a left-aligned heading.

   Capping the card rather than the grid keeps the US pair untouched: at two
   cards each track is already ~656px, well under this cap, so nothing
   changes there. A stretched grid item with a max-width aligns to the start
   of its track, which also puts the lone AU card under the left-aligned
   section heading instead of adrift in the middle. */
.sectors-overview-section .sector-card {
  max-width: 660px;
}


/* ==========================================================================
   HOMEPAGE "LATEST NEWS & ARTICLES" SECTION

   A core Query Loop, so publishing a post is all an admin has to do — the
   three most recent appear here automatically and the section needs no
   further editing. Deliberately NOT set to inherit its query: the two
   stock patterns that were here before both had `inherit: true`, which on a
   static front page inherits the PAGE query and rendered the homepage itself
   as the article ("Home", dated 08.7 2026).

   These styles mirror .article-card in css/pages/blog.css — same radius,
   border, hover lift, tag pill and accent read-more — but under their own
   `home-news-*` names rather than reusing that file. blog.css is 24KB and is
   only enqueued on the blog page, so loading it site-wide for one component
   would be a poor trade; and the blog page is being built out separately, so
   separate names keep the two from colliding mid-flight. Worth consolidating
   into one shared card component once the blog page settles.

   Markup note: core/post-template emits <ul class="wp-block-post-template">
   with an <li class="wp-block-post"> per post, so the CARD is the <li> — the
   class cannot be put on it from the editor, hence the child selectors.
   ========================================================================== */
.home-news-section {
  padding: 60px 0 80px;
}

.home-news-section .home-news-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 26px;
  list-style: none;
  margin: 0 0 40px;
  padding: 0;
}

.home-news-section .home-news-grid > li {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--color-surface, #ffffff);
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.08));
  border-radius: 18px;
  transition: transform 0.45s var(--ease-out, ease), box-shadow 0.45s var(--ease-out, ease),
    border-color 0.45s var(--ease-out, ease);
}

[data-theme="dark"] .home-news-section .home-news-grid > li {
  background: rgba(255, 255, 255, 0.03);
  border-color: rgba(255, 255, 255, 0.08);
}

.home-news-section .home-news-grid > li:hover {
  transform: translateY(-8px);
  box-shadow: 0 34px 60px -30px rgba(var(--ink-rgb, 0, 0, 0), 0.32);
  border-color: rgba(var(--color-accent-rgb, 38, 208, 124), 0.35);
}

/* Thumbnail ------------------------------------------------------------- */
.home-news-section .home-news-thumb {
  margin: 0;
  overflow: hidden;
  background: var(--color-surface2, rgba(0, 0, 0, 0.04));
}

.home-news-section .home-news-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease-out, ease);
}

.home-news-section .home-news-grid > li:hover .home-news-thumb img {
  transform: scale(1.06);
}

/* No featured image set: core/post-featured-image renders NOTHING at all
   rather than a placeholder, which left those cards looking clipped. When the
   figure is absent the body becomes the first child — so this selector is a
   pure-CSS test for "this post has no image", and turns the gap into a
   deliberate accent rule instead of an accident. Every currently published
   post is in this state. */
.home-news-section .home-news-grid > li > .home-news-body:first-child {
  border-top: 3px solid var(--color-accent, #26d07c);
  padding-top: 25px;
}

/* Body ------------------------------------------------------------------ */
.home-news-section .home-news-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 12px;
  padding: 24px 24px 26px;
}

.home-news-section .home-news-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0;
}

.home-news-section .home-news-tag,
.home-news-section .home-news-tag a {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--color-accent, #26d07c);
}

.home-news-section .home-news-date {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--color-text-dim, #808080);
  margin: 0;
}

/* The date sits after the category, separated by a dot rather than more
   whitespace — the meta row is short and reads as one line. */
.home-news-section .home-news-date::before {
  content: "•";
  margin-right: 10px;
  opacity: 0.5;
}

.home-news-section .home-news-title {
  margin: 0;
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.35;
}

.home-news-section .home-news-title a {
  color: var(--color-heading, #0d0d0d);
  text-decoration: none;
  transition: color 0.3s ease;
}

[data-theme="dark"] .home-news-section .home-news-title a {
  color: #ffffff;
}

.home-news-section .home-news-grid > li:hover .home-news-title a {
  color: var(--color-accent, #26d07c);
}

.home-news-section .home-news-excerpt {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--color-text-muted, #4a4a4a);
}

[data-theme="dark"] .home-news-section .home-news-excerpt {
  color: #cbd5e1;
}

/* Push the read-more to the bottom so it lines up across cards of unequal
   text length, instead of floating directly under each excerpt. */
.home-news-section .home-news-excerpt {
  flex: 1 1 auto;
}

.home-news-section .home-news-more {
  position: relative;
  align-self: flex-start;
  width: max-content;
  margin: 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--color-accent, #26d07c);
  text-decoration: none;
}

.home-news-section .home-news-more::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -5px;
  width: 100%;
  height: 1px;
  background: var(--color-accent, #26d07c);
  transform: scaleX(0.3);
  transform-origin: left;
  opacity: 0.4;
  transition: transform 0.35s var(--ease-out, ease), opacity 0.35s var(--ease-out, ease);
}

.home-news-section .home-news-grid > li:hover .home-news-more::after {
  transform: scaleX(1);
  opacity: 1;
}

/* Empty state ----------------------------------------------------------- */
.home-news-section .home-news-empty {
  padding: 44px 28px;
  border: 1px dashed var(--color-border, rgba(0, 0, 0, 0.18));
  border-radius: 18px;
  text-align: center;
  color: var(--color-text-dim, #808080);
  font-size: 0.95rem;
}

/* Responsive ------------------------------------------------------------ */
@media (max-width: 992px) {
  .home-news-section .home-news-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .home-news-section .home-news-grid {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .home-news-section .home-news-grid > li,
  .home-news-section .home-news-thumb img,
  .home-news-section .home-news-more::after {
    transition: none;
  }
  .home-news-section .home-news-grid > li:hover {
    transform: none;
  }
  .home-news-section .home-news-grid > li:hover .home-news-thumb img {
    transform: none;
  }
}

/* ==========================================================================
   HOMEPAGE NEWS — READ-IN-PLACE ARTICLE DIALOG

   Mirrors the .exp-modal-* dialog on the dev-site blog page, under its own
   names for the same reason as the cards above: blog.css is only enqueued on
   the blog page, and that page is being rebuilt separately.

   The dialog element is created by js/home-news-modal.js, not by page
   content, so an editor cannot half-delete it from the block editor.
   ========================================================================== */
.rcn-news-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s var(--ease-out, ease), visibility 0.35s var(--ease-out, ease);
}

.rcn-news-modal.is-open {
  opacity: 1;
  visibility: visible;
}

/* Locks the page behind the dialog. A class rather than an inline style so
   it cannot fight the preloader or region-switch, which also touch overflow. */
body.rcn-news-modal-open {
  overflow: hidden;
}

.rcn-news-modal-window {
  position: relative;
  width: 100%;
  max-width: 760px;
  max-height: 85vh;
  overflow-y: auto;
  background: var(--card-bg, #ffffff);
  border-radius: 22px;
  box-shadow: 0 60px 120px -40px rgba(0, 0, 0, 0.5);
  transform: translateY(24px) scale(0.97);
  opacity: 0;
  transition: transform 0.4s var(--ease-out, ease), opacity 0.4s var(--ease-out, ease);
}

.rcn-news-modal.is-open .rcn-news-modal-window {
  transform: translateY(0) scale(1);
  opacity: 1;
}

/* sticky + float keeps the button pinned top-right while the article scrolls
   underneath it, without taking a row of its own in the flow. */
.rcn-news-modal-close {
  position: sticky;
  top: 16px;
  float: right;
  z-index: 5;
  width: 38px;
  height: 38px;
  margin: 16px 16px 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.1));
  border-radius: 50%;
  background: var(--card-bg, #ffffff);
  color: var(--color-text, #0d0d0d);
  cursor: pointer;
  transition: background-color 0.25s ease, color 0.25s ease, transform 0.25s ease;
}

.rcn-news-modal-close:hover,
.rcn-news-modal-close:focus-visible {
  background: var(--color-accent, #26d07c);
  color: #ffffff;
  transform: rotate(90deg);
}

.rcn-news-modal-close svg {
  width: 18px;
  height: 18px;
}

.rcn-news-modal-inner {
  clear: both;
  padding: 8px 44px 44px;
}

.rcn-news-modal-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--color-accent, #26d07c);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.rcn-news-modal-title {
  margin: 12px 0 10px;
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  font-weight: 700;
  line-height: 1.25;
  color: var(--color-heading, #0d0d0d);
}

.rcn-news-modal-meta {
  margin: 0 0 18px;
  font-size: 0.85rem;
  color: var(--color-text-dim, #808080);
}

.rcn-news-modal-img {
  display: block;
  width: 100%;
  max-height: 320px;
  object-fit: cover;
  border-radius: 14px;
  margin: 16px 0 24px;
}

/* Article body — the post's own rendered HTML, so this has to style whatever
   blocks an author used rather than a known structure. */
.rcn-news-modal-body {
  color: var(--color-text-muted, #4a4a4a);
  font-size: 0.98rem;
  line-height: 1.75;
}

.rcn-news-modal-body > * + * {
  margin-top: 16px;
}

.rcn-news-modal-body h1,
.rcn-news-modal-body h2,
.rcn-news-modal-body h3,
.rcn-news-modal-body h4 {
  margin: 28px 0 10px;
  color: var(--color-heading, #0d0d0d);
  font-weight: 700;
  line-height: 1.3;
}

.rcn-news-modal-body h2 { font-size: 1.25rem; }
.rcn-news-modal-body h3 { font-size: 1.1rem; }
.rcn-news-modal-body h4 { font-size: 1.02rem; }

.rcn-news-modal-body ul,
.rcn-news-modal-body ol {
  padding-left: 20px;
}

.rcn-news-modal-body li + li {
  margin-top: 8px;
}

.rcn-news-modal-body a {
  color: var(--color-accent, #26d07c);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.rcn-news-modal-body img,
.rcn-news-modal-body iframe,
.rcn-news-modal-body video {
  max-width: 100%;
  height: auto;
  border-radius: 12px;
}

.rcn-news-modal-body blockquote {
  margin: 22px 0;
  padding: 4px 0 4px 18px;
  border-left: 3px solid var(--color-accent, #26d07c);
  font-style: italic;
}

/* Long code or wide tables scroll inside themselves rather than making the
   dialog scroll sideways. */
.rcn-news-modal-body pre,
.rcn-news-modal-body table {
  display: block;
  max-width: 100%;
  overflow-x: auto;
}

.rcn-news-modal-foot {
  margin: 30px 0 0;
  padding-top: 20px;
  border-top: 1px solid var(--color-border, rgba(0, 0, 0, 0.1));
}

.rcn-news-modal-permalink {
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--color-accent, #26d07c);
  text-decoration: none;
}

.rcn-news-modal-permalink:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Loading state ---------------------------------------------------------- */
.rcn-news-modal-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 70px 0 60px;
  color: var(--color-text-dim, #808080);
  font-size: 0.92rem;
}

.rcn-news-modal-spinner {
  width: 30px;
  height: 30px;
  border: 2px solid rgba(var(--color-accent-rgb, 38, 208, 124), 0.25);
  border-top-color: var(--color-accent, #26d07c);
  border-radius: 50%;
  animation: rcn-news-spin 0.8s linear infinite;
}

@keyframes rcn-news-spin {
  to { transform: rotate(360deg); }
}

/* Signals that the whole card is clickable, since it now opens a dialog
   rather than only the two links doing something. */
.home-news-section .home-news-grid > li {
  cursor: pointer;
}

@media (max-width: 640px) {
  .rcn-news-modal {
    padding: 12px;
  }
  .rcn-news-modal-window {
    max-height: 92vh;
    border-radius: 16px;
  }
  .rcn-news-modal-inner {
    padding: 4px 22px 32px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rcn-news-modal,
  .rcn-news-modal-window,
  .rcn-news-modal-close {
    transition: none;
  }
  .rcn-news-modal.is-open .rcn-news-modal-window {
    transform: none;
  }
  .rcn-news-modal-spinner {
    animation-duration: 2s;
  }
}

/* ==========================================================================
   SOFTWARE LOGO MARQUEE ("Digital Stack")

   Replaces the 13-row accordion, which stood ~1350px tall on the homepage.
   This holds any number of tools in one row.

   Built as its own component rather than reusing `.ct-logo-strip` because
   that one applies `filter: invert(1)` to its images in light mode — the
   client logos are white artwork made for dark surfaces. Software brand
   logos are full-colour, and inverting them produces a photographic
   negative. No filter is applied here; logos are shown as supplied.

   The track holds two identical sets and animates by -50%, so the second
   set is exactly where the first began when the loop restarts — that is
   what makes it seamless, and why the width must come from the content
   (`width: max-content`) rather than a percentage.
   ========================================================================== */
.sw-logo-strip {
  position: relative;
  margin: 2.5rem 0 0;
  border-top: 1px solid var(--color-border, rgba(0, 0, 0, 0.08));
  border-bottom: 1px solid var(--color-border, rgba(0, 0, 0, 0.08));
  overflow: hidden;
  /* Fades both ends so items enter and leave rather than being cut off
     mid-glyph at the section edge. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

/* ==========================================================================
   MARQUEE MOTION — shared by the software strip and the Our Clients strip

   Runs LEFT TO RIGHT. The keyframes start at the shift and end at zero, so
   the content always has copies waiting off-screen to the left to move in;
   doing it with `animation-direction: reverse` on a 0 -> -shift keyframe
   would work too, but this way the direction is readable at the declaration
   rather than inferred from a modifier three rules away.

   The distance is `--marquee-shift`, emitted per strip by PHP as exactly one
   copy's worth (100 / number of copies). Shift and copy count MUST agree or
   the loop visibly jumps, which is why neither is hardcoded here — see
   rcn_marquee_copies() in inc/blocks.php.
   ========================================================================== */
@keyframes rcn-marquee-ltr {
  from { transform: translateX(var(--marquee-shift, -50%)); }
  to   { transform: translateX(0); }
}

/* Right-to-left: start flush and travel one copy leftwards. The mirror of
   the above, kept as its own keyframe rather than `animation-direction:
   reverse` so each strip's rule states its direction outright. */
@keyframes rcn-marquee-rtl {
  from { transform: translateX(0); }
  to   { transform: translateX(var(--marquee-shift, -50%)); }
}

.sw-logo-track {
  display: flex;
  width: max-content;
  animation: rcn-marquee-ltr 42s linear infinite;
}

/* Our Clients travels the OTHER way, right-to-left, so the two strips on the
   page counter-rotate rather than sliding in parallel.
   Specificity (0,2,0) is deliberate: it has to outrank `.ct-logo-track {
   animation: ct-logo-scroll ... }` in premium-enhancements.css, whose
   hardcoded 50% shift no longer matches the copy count. */
.ct-logo-strip .ct-logo-track {
  width: max-content;
  /* Requested to read as fast as Digital Stack (.sw-logo-track, above: 42s).
     Duration alone is the wrong knob -- the two strips hold different
     numbers of logos, so the same duration gives them different speeds.
     Matched on measured velocity instead: Digital Stack covers one set of
     2756px in 42s = 65.6px/s, and one set of Our Clients is ~1220px (six logos
     at ~203px each), so 1220 / 65.6 = ~18.5s puts the two at the same px/s. Re-measure both if
     a logo is ever added or removed from either strip. */
  animation: rcn-marquee-rtl 18.5s linear infinite;
}

/* Pausing on hover applies to both, for the same reason: it lets someone
   read an item they just spotted. */
.ct-logo-strip:hover .ct-logo-track,
.ct-logo-strip:focus-within .ct-logo-track {
  animation-play-state: paused;
}

/* Each copy of the client list is its own set, so the repeats can be told
   apart from the originals (see rcn_render_client_logo_strip_block).
   `flex: 0 0 auto` is load-bearing here exactly as it is on `.sw-logo-set`:
   as flex items the sets inherit flex-shrink: 1 and would be squeezed to the
   strip's width while their own tiles, which cannot shrink, overflow --
   leaving the sets overlapping and the -50% translate no longer equal to one
   set's width. */
.ct-logo-set {
  display: flex;
  flex: 0 0 auto;
}

/* THE MARQUEE DOES NOT LOOP WITHOUT THIS.
 *
 * premium-enhancements.css carries a global `*, ::before, ::after {
 * max-width: 100vw }` — a blanket guard against horizontal overflow. It also
 * applies to the track, so `width: max-content` was being clamped to the
 * viewport: measured 1440px against 2756px of actual content (13 tiles x
 * 212px).
 *
 * That silently breaks the animation, because `translateX(-50%)` resolves
 * against the element's OWN width. At 1440px the track shifted 720px per
 * cycle instead of one full set of 2756px, so the strip jumped backwards
 * mid-loop and the last tiles collided with the first — which is exactly the
 * glitch reported at the reset point.
 *
 * Safe to lift here: both live inside `.sw-logo-strip`, which is
 * `overflow: hidden`, so nothing can escape and cause the page-level
 * horizontal scrolling that the global rule exists to prevent.
 *
 * The Our Clients strip is fixed alongside it: `.ct-logo-track` is built the
 * same way and was clamped identically — measured 1440px of box against
 * 1684px of content, so that marquee was jumping too. Pre-existing, not
 * caused by this work, but it is the same one-line cause and the two strips
 * sit on the same page.
 *
 * The client SETS need it too. They were added so the reduced-motion
 * fallback could hide the duplicate copies, and each one was promptly
 * clamped to 1440px against 3600px of real content -- so the two sets
 * measured 2880px between them, the -50% shift shrank to 1440px, and the
 * strip overlapped itself at the seam. Same cause, same fix. */
.sw-logo-strip .sw-logo-track,
.sw-logo-strip .sw-logo-set,
.ct-logo-strip .ct-logo-track,
.ct-logo-strip .ct-logo-set {
  max-width: none;
}

/* `flex: 0 0 auto` is load-bearing, not tidiness.
   As flex items the two sets inherit flex-shrink: 1, so each was squeezed to
   the strip's width (1440px) while its tiles — which are themselves
   `flex: 0 0 auto` and cannot shrink — overflowed it. Set 2 therefore began
   at x=1440 while set 1's content actually ran to 2769px, so the two sets
   OVERLAPPED and the -50% translate (2104px) no longer equalled one set's
   width (2769px): the loop jumped and the last items collided with the first.
   Measured: 13 tiles x 213px = 2769 content vs a 1440 measured box. */
.sw-logo-set {
  display: flex;
  flex: 0 0 auto;
}

/* Pausing on hover lets someone actually read an item they spotted, which
   a continuously moving strip otherwise makes a game of chance. */
.sw-logo-strip:hover .sw-logo-track,
.sw-logo-strip:focus-within .sw-logo-track {
  animation-play-state: paused;
}

/* Fixed basis rather than min-width, so every tile is the same width no
   matter how wide its logo renders — otherwise the pitch of the strip
   changes item to item and the scroll reads as uneven. */
.sw-logo {
  flex: 0 0 212px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 88px;
  padding: 0 2rem;
  border-right: 1px solid var(--color-border, rgba(0, 0, 0, 0.08));
  opacity: 0.8;
  transition: opacity 0.3s var(--ease-out, ease);
}

.sw-logo:hover {
  opacity: 1;
}

/* Scale to the tile WIDTH, then cap the height.
 *
 * These 13 files fall into two shapes, and one box cannot serve both:
 *   - wide wordmarks, ratio 3–9 (Autodesk 100x11, SketchUp 300x61)
 *   - tall lockups, ratio 1–1.8 (Adobe 240x234 is the Creative Cloud icon
 *     with no wordmark at all; Bluebeam 576x324 stacks icon over wordmark)
 *
 * Letterboxing everything into a fixed 140x40 sized them by their WIDEST
 * dimension, so the tall ones shrank to fit: Adobe rendered 40x40 and
 * Bluebeam 71x40, visibly smaller than the horizontal logos beside them.
 * Sizing by width and capping height instead lets the tall pair render ~52px
 * tall while the wide ones still fill the 148px of available width.
 *
 * `max-height` on a replaced element with `height: auto` re-derives the width
 * from the aspect ratio (CSS 2.1 10.4), so this clamps proportionally and
 * never distorts. object-fit is kept as a belt-and-braces guard for any
 * future file whose intrinsic ratio is missing. */
.sw-logo img {
  width: 100%;
  height: auto;
  max-height: 52px;
  object-fit: contain;

  /* The supplied artwork is WHITE on transparency, drawn for dark surfaces,
     so it has to be inverted to read on the light theme — the same treatment
     the Our Clients strip uses for its white logos. Inverting is safe here
     precisely because these files are single-colour: there is no brand hue to
     destroy, which is why the earlier full-colour set needed a plate instead. */
  filter: invert(1) opacity(0.85);
  transition: filter 0.3s var(--ease-out, ease);
}

.sw-logo:hover img {
  filter: invert(1) opacity(1);
}

/* Wordmark fallback, used until a real logo image is set. Weighted and
   letter-spaced so a row of names still reads as a brand strip rather than
   as body copy. */
.sw-logo-name {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  color: var(--color-heading, #0d0d0d);
}

[data-theme="dark"] .sw-logo-name {
  color: #ffffff;
}

/* Icon-only artwork paired with its name (see the render callback). The image
   drops to icon size so the two read as one lockup rather than a logo with a
   caption, and the name steps down a little to fit the tile alongside it. */
.sw-logo--with-name {
  gap: 9px;
}

.sw-logo--with-name img {
  width: 30px;
  height: 30px;
  max-height: 30px;
  flex: 0 0 auto;
}

.sw-logo--with-name .sw-logo-name {
  font-size: 0.95rem;
}

/* DARK MODE: use the artwork as supplied, no plate.
 *
 * The white-plate treatment that used to live here has been removed along
 * with the full-colour logo set it existed for. The replacement files are
 * single-colour WHITE artwork on transparency, so a white plate behind them
 * would render them invisible — the exact inverse of the problem the plate
 * was solving.
 *
 * White-on-transparent is the same shape as the Our Clients logos, so it
 * takes the same treatment: inverted to black for the light theme (see the
 * rule above) and passed through untouched here. Nothing is being
 * misrepresented, because these files carry no brand colour to lose. */
[data-theme="dark"] .sw-logo img {
  filter: opacity(0.9);
}

[data-theme="dark"] .sw-logo:hover img {
  filter: opacity(1);
}

@media (max-width: 640px) {
  .sw-logo {
    min-width: 150px;
    height: 74px;
    padding: 0 1.5rem;
  }
  .sw-logo-name {
    font-size: 0.95rem;
  }
}

/* A continuously scrolling strip is exactly the kind of motion this setting
   exists to stop. Freezing the track alone would leave most items outside
   the viewport, so it also wraps onto multiple rows and drops the mask,
   turning the marquee into a static grid that shows everything at once. */
@media (prefers-reduced-motion: reduce) {
  .sw-logo-track {
    animation: none;
    width: 100%;
    flex-wrap: wrap;
  }
  .sw-logo-set {
    flex-wrap: wrap;
  }
  .sw-logo-set[aria-hidden="true"] {
    display: none;
  }
  .sw-logo-strip {
    -webkit-mask-image: none;
    mask-image: none;
  }

  /* premium-enhancements.css already stops `.ct-logo-track` here, but at
     (0,1,0) — and the rule above that gives it the shared RTL animation is
     (0,2,0), so it would have won and kept the client strip moving for
     someone who asked for reduced motion. Restated at matching specificity.

     Only the first copy is shown. That was the stated intent before, but
     nothing implemented it: the client logos had no per-copy wrapper, so the
     frozen, wrapped track laid out the whole list two to four times over as
     a tall grid of duplicates -- which is what this looked like when the
     strip was reported as broken. The sets exist now, and the repeats are
     hidden, matching what the software strip already did. */
  .ct-logo-strip .ct-logo-track {
    animation: none;
    width: 100%;
    flex-wrap: wrap;
    justify-content: center;
  }
  .ct-logo-set {
    flex-wrap: wrap;
    justify-content: center;
  }
  .ct-logo-set--repeat {
    display: none;
  }
  .ct-logo-strip {
    -webkit-mask-image: none;
    mask-image: none;
  }
}


/* ==========================================================================
   The block below was added directly on the server by another developer and
   was not in version control. It arrived as part of a deploy that also
   reverted this file to an earlier snapshot, wiping the marquee, news-card,
   news-dialog, sector-card background and light-mode contrast rules. Merged
   back in here so the same deploy cannot drop it again.
   ========================================================================== */
/* ============================================================================
   EDITOR CONTENT — restore list markers
   main.css ~244 sets `ul { list-style: none }` as a site-wide reset, which is
   right for navs, card badge rows and footer link columns but also strips the
   bullets from every core/list block an editor writes. On a post body that
   reads as a run-on block of lines with no indent (measured: listStyleType
   none, padding-left 0).

   Markers are restored only inside authored content, so the reset still
   applies everywhere else.
   ============================================================================ */
.page-content-wrap ul,
.entry-content ul,
ul.wp-block-list {
	list-style: disc outside;
	padding-left: 1.5rem;
	margin: 0 0 1.25rem;
}

.page-content-wrap ol,
.entry-content ol,
ol.wp-block-list {
	list-style: decimal outside;
	padding-left: 1.5rem;
	margin: 0 0 1.25rem;
}

.page-content-wrap ul ul,
.entry-content ul ul,
ul.wp-block-list ul {
	list-style: circle outside;
	margin: 0.4rem 0 0.4rem;
}

.page-content-wrap li,
.entry-content li,
.wp-block-list li {
	margin-bottom: 0.5rem;
	line-height: 1.7;
	color: var(--color-text-muted);
}

.page-content-wrap li::marker,
.entry-content li::marker,
.wp-block-list li::marker {
	color: var(--color-accent);
}

/* Components that legitimately want no markers keep the reset. */
.page-content-wrap .detail-checklist,
.page-content-wrap .vision-checklist,
.page-content-wrap .model-points,
.page-content-wrap .integration-list,
.entry-content .detail-checklist,
.entry-content .vision-checklist,
.entry-content .model-points,
.entry-content .integration-list {
	list-style: none;
	padding-left: 0;
}

/* ---------------------------------------------------------------------------
   Post body rhythm
   --------------------------------------------------------------------------- */
.page-content-wrap > .container > p,
.page-content-wrap > .container > .wp-block-paragraph {
	max-width: 72ch;
	line-height: 1.8;
	margin: 0 0 1.25rem;
	color: var(--color-text-muted);
}

.page-content-wrap > .container > h2,
.page-content-wrap > .container > h3 {
	margin: 2.25rem 0 0.9rem;
	letter-spacing: -0.02em;
	color: var(--color-text);
}

.page-content-wrap > .container > .wp-block-quote {
	margin: 1.75rem 0;
	padding: 1rem 0 1rem 1.5rem;
	border-left: 3px solid var(--color-accent);
	font-style: italic;
	color: var(--color-text);
}

/* ==========================================================================
   HOMEPAGE LOGO STRIPS — TIGHTER VERTICAL RHYTHM

   Both strips were carrying far more air than their content needs: measured,
   the Our Clients section was 506px tall to present a 94px strip (104px
   padding top and bottom, plus 52/60px of margin on the strip itself), and
   Digital Stack 449px for a 90px strip.

   Brought in line with the two sections above them, which use 60px top —
   so the page reads with one rhythm instead of the strips sitting in
   noticeably bigger blocks than everything else.

   SCOPED TO body.home deliberately. `#software` is also the anchor on 13
   service pages and `.inner-section` is used by 29 published posts, so
   changing either unscoped would reflow most of the site. body.home is
   present only on the static front page (service pages carry
   `single-service_page` instead), which makes it the narrowest safe hook.
   ========================================================================== */
body.home .home-testimonial,
body.home #software {
  padding: 60px 0 72px;
}

/* The strips' own margins were the other half of the problem — the section
   padding and these stacked. */
body.home .ct-logo-strip {
  margin: 36px 0 24px;
}

body.home .sw-logo-strip {
  margin: 32px 0 0;
}

/* ==========================================================================
   SOFTWARE WE WORK IN — hidden on service pages

   Hidden rather than deleted, so the content stays in the editor and can be
   brought back by removing this one rule.

   Scoped to single-service_page deliberately. The anchor "software" is not
   unique to these pages: the homepage uses the same id for its "Digital
   Stack" logo marquee, which must stay visible. Body class rather than a
   page list so a service page added later is covered too.

   Applies to all 13 US and AU service pages that carry the section.
   ========================================================================== */
body.single-service_page #software {
	display: none !important;
}

/* ==========================================================================
   THE REGION SWITCHER

   The toggle names the region in full -- "United States" rather than "US" --
   which is a good deal more text in a header that is already tight at laptop
   widths.

   THIS MUST BE SITEWIDE. It lived in css/pages/home.css at first, which is
   enqueued on the front page only -- so the homepage behaved and every other
   page kept the full label at every width. At 1280px on a service page that
   pushed the Contact Us button past the viewport and gave the whole document
   a horizontal scrollbar. The header is sitewide chrome; its rules have to
   live in a sitewide sheet.
   ========================================================================== */

.market-switch-label {
	white-space: nowrap;
}

@media (max-width: 1439px) {
	/*
	 * Below this the full name competes with the navigation for room. The flag
	 * and the chevron carry the control on their own, and the open menu still
	 * names both regions in full -- so nothing is lost, it is just not spelled
	 * out twice.
	 *
	 * 1439 rather than 1320, which was measured rather than guessed: with the
	 * label showing, the header ran to 1420px on a service page, so anything
	 * from 1321 to 1420 got a horizontal scrollbar. At 1440 the header fits
	 * with the label, on every page checked.
	 */
	.market-switch-toggle .market-switch-label {
		display: none;
	}
	.market-switch-toggle {
		padding: 8px 10px;
	}

	/*
	 * The actions row is a few pixels too wide in this band even with the
	 * label hidden: measured 311px against the room available at 1320, which
	 * gave the document a 6px horizontal scrollbar. Pre-existing rather than
	 * introduced here, but this is the rule that already narrows the header at
	 * this width, so it is the right place to finish the job.
	 *
	 * Taken off the gap and the Contact button's side padding, not its font
	 * size -- the button should still read as the primary action.
	 */
	.header-actions {
		gap: 10px;
	}
	.header-actions .btn-contact {
		padding-inline: 20px;
	}
}

/* ==========================================================================
   FAQ QUESTION WEIGHT

   The questions were set at 600, which reads as the same weight as the body
   copy beside them at a glance -- so an FAQ list looked like a wall of
   paragraphs rather than a set of headings you can scan. 700 separates them.

   Sitewide rather than on the three pages it was reported on: the same
   component draws every FAQ list, and having two weights across the site is
   the actual defect.
   ========================================================================== */
/* !important because inner-pages.css and main.css both set this at the same
   specificity, and which of the three loads last is not something this rule
   should depend on. */
.faq-question,
.faq-question span,
.faq-item .faq-question {
	font-weight: 700 !important;
}
