/*
  WordPress-specific additions.

  inrico.css is a straight copy of the prototype's src/b_style.css and must stay
  that way — re-copied on every change, never edited. This file holds the small
  number of rules WordPress needs that the prototype never did: a skip link, a
  logo fallback, editor content, the mobile nav toggle, and filter links.

  Everything here uses the same tokens as the main stylesheet, so both themes
  stay correct. Nothing here restyles an existing component.
*/

/* ---------------------------------------------------- accessibility */

/* Skip link — visually hidden until focused. */
.skip {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 200;
	padding: 12px 18px;
	border-radius: var(--r-s);
	background: var(--panel-solid);
	color: var(--fg);
	border: 1px solid var(--line-2);
}
.skip:focus {
	left: 16px;
	top: 16px;
}

/* --------------------------------------------------------- branding */

/*
  The logo lockup. Two files ship — dark navy wordmark for light grounds, white
  wordmark for dark — and CSS picks one, because the active theme is only known
  in the browser. See inrico_logo() in inc/render.php.

  The show/hide follows the same three-state pattern as .lg-d/.lg-l in
  inrico.css (bare :root is DARK, light is the override), so the logo and the
  theme-toggle glyph can never disagree about which theme is showing.
*/
.logo {
	display: inline-flex;
	align-items: center;
}

.logo img {
	width: auto;
	display: block;
}

/*
  Both need the extra class in the selector: inrico.css carries
  `.brand img{height:38px}`, which out-specifies a bare `.logo img` and would
  silently resize the nav mark back to 38px on the next re-copy.
*/
.brand .logo img { height: 42px; }
.fbrand .logo img { height: 52px; }

/*
  The nav is position:fixed with 14px of vertical padding, and several templates
  clear it with a hardcoded top padding (page.php uses 126px, .posthero 150px).
  A taller mark makes the bar taller, so the padding comes down to keep the
  fixed nav roughly the height it was and those clearances still correct.
*/
.nav:has(.brand .logo) { padding-top: 8px; padding-bottom: 8px; }

@media (max-width: 620px) {
	.brand .logo img { height: 34px; }
	.fbrand .logo img { height: 44px; }
}

/*
  Every one of these has to be `.logo img.<class>`, NOT a bare `.logo-l`.
  `.logo img` above is (0,1,1) and a lone `.logo-l` is (0,1,0), so the broad
  rule wins the cascade and BOTH logos paint side by side — which is exactly
  the specificity trap in HANDOFF §7, and it looks like a markup bug rather
  than a CSS one.
*/
.logo img.logo-l { display: none; }

:root[data-theme="light"] .logo img.logo-d { display: none; }
:root[data-theme="light"] .logo img.logo-l { display: block; }

@media (prefers-color-scheme: light) {
	:root:not([data-theme="dark"]) .logo img.logo-d { display: none; }
	:root:not([data-theme="dark"]) .logo img.logo-l { display: block; }
}

/*
  Footer lockup — the first column of .fgrid, which is the 1.5fr track.
*/
.fbrandcol {
	display: flex;
	flex-direction: column;
	gap: 16px;
	align-items: flex-start;
}

.fbrand {
	display: inline-block;
}

.fblurb {
	margin: 0;
	max-width: 34ch;
	font-size: .86rem;
	line-height: 1.6;
	color: var(--fg-2);
}

.fbrand:focus-visible {
	outline: 2px solid var(--gold);
	outline-offset: 4px;
	border-radius: 4px;
}

/*
  Text fallback, kept for the case where the logo files are missing. Sized to
  the nav, not to a heading, so it does not inherit display type sizing.
*/
.brandmark {
	font-family: "Sora", system-ui, sans-serif;
	font-weight: 700;
	font-size: 1.16rem;
	letter-spacing: -.01em;
	color: var(--fg);
}

/* ---------------------------------------------------------- filters */

/*
  The prototype filters client-side with <button>. Here they are real links so
  each filtered view has its own URL, so the button rule is extended to anchors.
  Kept as a separate selector rather than editing the original rule, so re-copying
  inrico.css never clobbers it.
*/
.filters a {
	padding: 9px 16px;
	border-radius: 999px;
	border: 1px solid var(--line-2);
	background: transparent;
	color: var(--fg-2);
	cursor: pointer;
	text-decoration: none;
	transition: background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.filters a:hover {
	color: var(--fg);
	background: var(--tint);
}
.filters a.sel {
	background: var(--blue);
	border-color: var(--blue);
	color: #fff;
}

/* ------------------------------------------------------- mobile nav */

.navtoggle {
	display: none;
	flex-direction: column;
	gap: 4px;
	padding: 10px;
	margin-left: auto;
	background: transparent;
	border: 1px solid var(--line-2);
	border-radius: var(--r-s);
	cursor: pointer;
}
.navtoggle span {
	display: block;
	width: 18px;
	height: 2px;
	border-radius: 2px;
	background: var(--fg-2);
}

@media (max-width: 900px) {
	.navtoggle { display: flex; }
}

/* ------------------------------------------------- editor content */

/*
  Anything the editor adds to the static front page renders inside .prose. Scoped
  tightly so it cannot leak into component markup — see HANDOFF §7 trap 1, where a
  broad descendant selector out-specifying a component class cost four separate
  debugging sessions.
*/
.prose > h2,
.prose > h3 { margin: 1.4em 0 .5em; }
.prose > p  { margin: 0 0 1em; color: var(--fg-2); }
.prose > ul,
.prose > ol { margin: 0 0 1em 1.2em; color: var(--fg-2); }
.prose > img { max-width: 100%; height: auto; border-radius: var(--r-s); }
.prose > a  { color: var(--blue); }

/*
  Gutenberg wraps every core/image in a <figure>, so `.prose > img` never
  matches an image added through the editor — only a bare <img> pasted into
  HTML. Both are styled, or article images render unrounded and flush against
  the paragraph above while inline ones look correct.
*/
.prose > figure {
	margin: 1.8em 0;
}
.prose > figure img {
	max-width: 100%;
	height: auto;
	display: block;
	border-radius: var(--r-s);
}
.prose > figure figcaption {
	margin-top: 10px;
	font-size: .82rem;
	color: var(--fg-2);
}

/* --------------------------------------------------- WordPress core */

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}

.custom-logo {
	max-height: 46px;
	width: auto;
	display: block;
}

/* ------------------------------------------------------- quote form */

/*
  Submission feedback. The prototype had none — its form opened a mailto: link,
  so there was never a server response to report.
*/
.qmsg {
	padding: 16px 20px;
	border-radius: var(--r-s);
	border: 1px solid var(--line-2);
	background: var(--tint);
	color: var(--fg-2);
	margin-bottom: 26px;
}
.qmsg strong { color: var(--fg); }
.qmsg.ok  { border-color: var(--stock); }
.qmsg.bad { border-color: var(--gold); }

/* The form's own submit is a <button>; .btn assumes an <a> in places. */
button.btn {
	font-family: "Sora", system-ui, sans-serif;
}

/* ------------------------------------------------ coming-soon products
   A WordPress-side concept: driven by the _inrico_soon post meta, which the
   prototype has no equivalent of. It lives here rather than in inrico.css so
   that re-copying src/b_style.css never clobbers it (HANDOFF §11).

   Deliberately quieter than .best (gold) and .new (blue). Those are selling
   badges; this is a status, and dressing a product you cannot buy in the same
   colour as a best seller reads as a promotion and frustrates the visitor. */
.tag.soon{
  background:var(--tint-2);
  color:var(--fg-2);
  border:1px solid var(--line-2);
  /* .tag has no border, so trim the padding to keep this pill the same height
     as .best and .new when they sit side by side in the same grid. */
  padding:4px 10px;
}

/* The price slot still has to hold its line so cards stay aligned in the grid,
   but it must not look like a number. */
.price.soon{
  color:var(--fg-2);
  font-family:"Sora",sans-serif;
  font-weight:600;
  letter-spacing:.01em;
}

/* ---------------------------------------- manufacturer feature panels
   Full-bleed. These images are composed edge to edge and carry their own
   captions, so constraining them to the text column wastes them. No max-width
   on the figure; the image itself is capped so it never upscales past its
   natural size on a very wide monitor. */
.featstrip{
  display:block;
  /* The manufacturer's site is light-themed, so ~64% of these panels have white
     grounds. Dropped straight onto the dark page they strobe dark-white-dark,
     once per panel. Painting the whole strip white turns seven interruptions
     into ONE deliberate transition, and the handful of dark panels read as
     cards on it rather than as another flash. There is no CSS that can relight
     the inside of a photograph, so the choice is to own the light band or to
     contain the images — this owns it. */
  background:#fff;
  padding:clamp(28px, 5vw, 72px) 0;
}
/* Soften the joins so the strip reads as one surface, not nine stacked images. */
.featstrip .feat + .feat{ margin-top:clamp(20px, 3vw, 48px) }
.featstrip .feat{
  margin:0;
  display:block;
}
.featstrip .feat img{
  display:block;
  width:100%;
  max-width:2560px;
  margin:0 auto;
  height:auto;
}

/* ---------------------------------------- video dialog
   <dialog> gives us the focus trap, Escape-to-close and inert background for
   free. ::backdrop only applies when opened with showModal(). */
.vidbox{
  border:0; padding:0; background:transparent;
  width:min(1100px, 92vw);
  max-width:100%;
  color:var(--fg);
}
.vidbox::backdrop{
  background:rgba(0,0,0,.82);
  backdrop-filter:blur(3px);
}
.vidbox .vidframe{
  position:relative;
  aspect-ratio:16 / 9;
  background:#000;
  border-radius:var(--r, 14px);
  overflow:hidden;
  box-shadow:var(--shadow, 0 24px 60px rgba(0,0,0,.5));
}
.vidbox .vidframe iframe{
  position:absolute; inset:0;
  width:100%; height:100%;
  border:0;
}
.vidclose{
  position:absolute; top:-44px; right:0;
  width:36px; height:36px;
  display:grid; place-items:center;
  font-size:1.6rem; line-height:1;
  /* A hairline circle on a near-black backdrop is almost invisible. Give it a
     real surface so it reads as a control at a glance. */
  background:rgba(255,255,255,.14); color:#fff;
  border:1px solid rgba(255,255,255,.5);
  border-radius:999px; cursor:pointer;
  transition:background .15s ease, transform .15s ease;
}
.vidclose:hover{ background:rgba(255,255,255,.3); transform:scale(1.06) }
.vidclose:focus-visible{ outline:2px solid var(--blue); outline-offset:2px }

/* The button carries an icon, so it needs to lay its children out. */
.btn.play{
  display:inline-flex; align-items:center; gap:8px;
  cursor:pointer;
}

@media (max-width: 640px){
  .vidclose{ top:-40px }
}

/* ---------------------------------------------- product page CTA row
   inrico.css styles `.hero .cta` only, so on a product page .cta inherits
   nothing: the buttons were inline elements separated by whatever whitespace
   the template happened to emit. That is the uneven spacing between Add to
   quote / Watch the video / Brochure / ICASA certificate. */
.pgrid .cta,
.phero .cta{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:10px;
  margin:22px 0 4px;
}
.pgrid .cta .btn,
.phero .cta .btn{ margin:0 }

/* The price row sat tight against the buttons. Give it room to breathe. */
.pprice{ margin-bottom:6px }

/* ---------------------------------------------- overlay feature panels
   A port of the manufacturer's #pro_intro blocks: a full-bleed image with the
   copy laid OVER it, not beside it. Alignment and ink colour come from the
   source markup because they are compositional — the copy sits in whichever
   half of the photograph is empty, and it is black where that half is light.
   Get either wrong and the words land on the subject. */
.featstrip .feat{ position:relative }

.feat-t{
  position:absolute;
  top:50%;
  transform:translateY(-50%);
  width:min(38ch, 40%);
  z-index:2;
}
.feat-t.is-left{  left:clamp(20px, 6vw, 110px) }
.feat-t.is-right{ right:clamp(20px, 6vw, 110px) }

.feat-t h3{
  font-family:"Sora",sans-serif;
  font-size:clamp(1.15rem, 2.1vw, 2rem);
  line-height:1.18;
  font-weight:600;
  margin:0 0 .5em;
  letter-spacing:-.01em;
}
.feat-t p{
  font-size:clamp(.82rem, 1.05vw, 1rem);
  line-height:1.6;
  margin:0;
  opacity:.92;
}
.feat-t.ink-dark{  color:#10131a }
.feat-t.ink-light{ color:#fff; text-shadow:0 1px 24px rgba(0,0,0,.45) }

/* Below the panel's natural breakpoint the photograph no longer has an empty
   half to write into, so stop overlaying and stack instead — otherwise the
   copy sits on the subject's face at 380px wide. */
@media (max-width: 860px){
  .feat-t{
    position:static;
    transform:none;
    width:auto;
    padding:18px clamp(16px, 5vw, 28px) 4px;
  }
  .feat-t.is-left, .feat-t.is-right{ left:auto; right:auto }
  .feat-t.ink-light{ color:var(--ink, #10131a); text-shadow:none }
  .featstrip .feat + .feat{ margin-top:8px }
}

/* ---------------------------------------------- highlight cards
   Replaces the two-column "At a glance" text list. Icons are the
   manufacturer's own, imported to the media library. */
.hcards{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(210px, 1fr));
  gap:14px;
  margin:26px 0 6px;
}
.hcard{
  border:1px solid var(--line);
  border-radius:var(--r-s);
  background:var(--tint-2);
  padding:15px 16px 14px;
}
/* The icon is a mask, so it takes the brand colour in both themes rather than
   arriving as dark line art that vanishes on the dark card. */
.hcard .hicon{
  display:block;
  width:34px; height:34px;
  margin-bottom:12px;
  background:var(--blue);
  -webkit-mask:var(--ic) center / contain no-repeat;
          mask:var(--ic) center / contain no-repeat;
}
/* If a browser cannot mask, show the image instead of an empty blue square. */
@supports not ((-webkit-mask: url()) or (mask: url())){
  .hcard .hicon{
    background:transparent;
    background-image:var(--ic);
    background-size:contain;
    background-position:center;
    background-repeat:no-repeat;
  }
}
/* Icon and title on one row. Four of these sit above the fold; stacking the
   icon over the title cost roughly a screen of height before the specs. */
.hcard-h{
  display:flex;
  align-items:center;
  gap:10px;
  margin-bottom:8px;
}
.hcard-h .hicon{ margin-bottom:0; flex:0 0 auto; width:20px; height:20px }
.hcard b{
  font-family:"Sora",sans-serif;
  font-size:.95rem;
  font-weight:600;
  line-height:1.25;
  color:var(--fg);
}
.hcard-b{
  display:block;
  font-size:.85rem;
  line-height:1.5;
  color:var(--fg-2);
}

/* ---------------------------------------------- At a glance fallback list
   Was rendering into .exlist, which belongs to the scroll-scrubbed exploded
   view: that rule dims every item to 34% opacity and only lifts it on .on,
   which is added by explode.js as you scroll. On a product page nothing ever
   adds .on, so the entire list sat at a third opacity and read as broken. */
.glist{
  list-style:none; margin:14px 0 4px; padding:0;
  border-left:1px solid var(--line);
  display:grid; gap:2px;
}
.glist li{
  padding:7px 0 7px 16px;
  margin-left:-1px;
  border-left:2px solid transparent;
}
.glist li::marker{ content:none }
.glist li:hover{ border-left-color:var(--blue) }
.glist span{
  display:block;
  font-size:.9rem; line-height:1.5;
  color:var(--fg-2);
}

/* ---------------------------------------------- "Where it's used"
   Sits under the product shot. The left column of .pgrid runs about a third
   shorter than the details column, so this fills a real gap rather than being
   padding for its own sake. */
.usedin{
  margin-top:18px;
  border:1px solid var(--line);
  border-radius:var(--r-s);
  background:var(--tint-2);
  padding:18px 20px 20px;
}
.usedin h4{
  margin:0 0 10px;
  font-family:"Sora",sans-serif;
  font-size:.72rem;
  font-weight:700;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--fg-3);
}
.usedin p{
  margin:0 0 14px;
  font-size:.92rem;
  line-height:1.55;
  color:var(--fg-2);
}
.usedin .scen{
  list-style:none;
  margin:0; padding:0;
  display:flex; flex-wrap:wrap; gap:7px;
}
.usedin .scen li{
  font-family:"JetBrains Mono",monospace;
  font-size:.68rem;
  letter-spacing:.04em;
  padding:5px 10px;
  border-radius:999px;
  border:1px solid var(--line-2);
  color:var(--fg-2);
  background:var(--tint);
}

/* ---------------------------------------------- product gallery thumbnails
   Four angles of one object, so this is a picker, not a slideshow — no arrows,
   no auto-advance, nothing to wait for. */
[data-gallery] img{
  transition:opacity .12s linear;
}
.pthumbs{
  display:flex;
  flex-wrap:wrap;
  gap:10px;
  margin-top:12px;
}
.pthumb{
  width:66px; height:66px;
  padding:5px;
  flex:0 0 auto;
  border:1px solid var(--line);
  border-radius:var(--r-s);
  background:var(--tint-2);
  cursor:pointer;
  display:grid; place-items:center;
  transition:border-color .18s var(--ease), background .18s var(--ease);
}
.pthumb img{
  width:100%; height:100%;
  object-fit:contain;
  display:block;
}
.pthumb:hover{ border-color:var(--line-2); background:var(--tint) }
.pthumb.is-on{
  border-color:var(--blue);
  background:var(--tint);
}
.pthumb:focus-visible{
  outline:2px solid var(--blue);
  outline-offset:2px;
}
@media (max-width:520px){
  .pthumb{ width:56px; height:56px }
}

/* A handful of gallery shots are annotated diagrams — black callout labels on
   a white plate. Cutting the plate is technically clean and editorially wrong:
   the labels end up dark-on-dark. Those keep the plate, and this makes it look
   deliberate rather than like a stray white rectangle. */
[data-gallery] img.on-plate{
  background:#fff;
  border-radius:var(--r-s);
  padding:10px;
}
.pthumb img{ background:transparent }

/* ------------------------------------------------- case study teaser */

/*
  The wide feature card — the newest article on the front page, and the top
  of the News archive. Built from the same tokens as .patrolcard so it reads
  as part of the set, but laid out as a wide banner so a landscape photograph
  is not cropped to a sliver.

  It is one <a> wrapping everything — spans rather than block elements inside,
  because an <a> may not contain a <div> in valid HTML and browsers silently
  reparent the markup, which breaks the grid.
*/
.casecard {
	display: grid;
	grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
	align-items: stretch;
	gap: 0;
	overflow: hidden;
	border: 1px solid var(--line);
	border-radius: var(--r);
	background: var(--panel);
	color: inherit;
	text-decoration: none;
	transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}

.casecard:hover {
	transform: translateY(-3px);
	border-color: var(--blue);
	box-shadow: var(--shadow);
}

.casecard:focus-visible {
	outline: 2px solid var(--gold);
	outline-offset: 3px;
}

.casecard-img {
	display: block;
	position: relative;
	min-height: 240px;
	overflow: hidden;
}

.casecard-img img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/*
	  Biased upward, not centred. These tiles crop a portrait-ish photo into a
	  wide slot, and the subject of a news photograph is almost always in the
	  top half — on the CCID card, dead centre cuts the officers off at the chin.
	*/
	object-position: center 16%;
}

.casecard-body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 10px;
	padding: 34px 36px;
	justify-content: center;
}

.casecard-h {
	font-family: "Sora", system-ui, sans-serif;
	font-weight: 700;
	font-size: clamp(1.25rem, 1.9vw, 1.65rem);
	line-height: 1.14;
	letter-spacing: -.02em;
	color: var(--fg);
}

.casecard-p {
	color: var(--fg-2);
	font-size: .95rem;
	line-height: 1.6;
	max-width: 46ch;
}

@media (max-width: 860px) {
	.casecard { grid-template-columns: 1fr; }
	.casecard-img { min-height: 200px; }
	.casecard-body { padding: 26px 24px 30px; }
}

/* ------------------------------------------------------ article page */

/*
  Masthead for a single post. Full-bleed photograph, dark scrim, centred title.

  It escapes .wrap with the 50vw margin trick rather than living outside the
  section, so the template stays one flow and the band still centres its own
  content. calc(50% - 50vw) is negative on every viewport wider than the wrap,
  and 100vw + the margins is exactly the viewport.
*/
.posthero {
	position: relative;
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	min-height: min(58vh, 460px);
	display: flex;
	align-items: flex-end;
	padding: 150px 0 58px;
	overflow: hidden;
	text-align: center;
	isolation: isolate;
}

.posthero-bg {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 55%;
	z-index: -2;
}

/*
  Dark scrim, heaviest at the bottom where the type sits and thinning upward so
  the photograph still reads. Deliberately NOT theme-tokened: this is an overlay
  on a photograph, not a page surface, and it has to be dark in both themes or
  the text has nothing to sit against. The colour is --ink (#060a14) with alpha,
  so it is still the palette's black rather than a new one.
*/
.posthero.has-img::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(0deg,
		rgba(6, 10, 20, .94) 0%,
		rgba(6, 10, 20, .82) 26%,
		rgba(6, 10, 20, .52) 58%,
		rgba(6, 10, 20, .34) 100%);
}

.posthero-in {
	position: relative;
	max-width: 62ch;
}

/*
  Light type, fixed. The scrim above is dark in BOTH themes, so inheriting the
  theme foreground would give dark-on-dark the moment the viewer is in light
  mode — the exact failure the token system exists to prevent, just inverted.
*/
.posthero.has-img h1,
.posthero.has-img .posthero-in { color: #fff; }

.posthero h1 {
	font-size: clamp(2.1rem, 4.6vw, 3.5rem);
	margin: 0;
	text-wrap: balance;
}

.posthero-k {
	font-size: .72rem;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--gold);
	margin-bottom: 16px;
}
.posthero-k a { color: inherit; text-decoration: none; }
.posthero-k a:hover { text-decoration: underline; }

.posthero-m {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	margin-top: 22px;
	font-size: .84rem;
	color: rgba(255, 255, 255, .78);
}
.posthero-m a { color: #fff; text-decoration: none; }
.posthero-m a:hover { text-decoration: underline; }
.posthero-m .dot {
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: currentColor;
	opacity: .5;
}

/* No photograph: fall back to page colours rather than white on white. */
.posthero:not(.has-img) {
	min-height: 0;
	padding-bottom: 10px;
	border-bottom: 1px solid var(--line);
}
.posthero:not(.has-img) .posthero-m { color: var(--fg-2); }
.posthero:not(.has-img) .posthero-m a { color: var(--blue); }

/*
  Article body. Centred rather than left-aligned in a wide wrap, so it sits
  under the centred masthead instead of drifting to one side of it.
*/
.postbody {
	max-width: 68ch;
	margin-inline: auto;
}

/* Figures may break the reading column — a photograph at 68ch is small. */
.postbody > figure {
	width: min(112%, 100vw - 44px);
	margin-inline: calc(50% - min(56%, 50vw - 22px));
}

@media (max-width: 700px) {
	.posthero { padding: 124px 0 44px; min-height: 0; }
	.postbody > figure { width: 100%; margin-inline: 0; }
}

/* ---------------------------------------------------- headline stats */

/*
  A band of figures under the intro. Every number is quoted from the article
  itself — see stats() in inc/cli.php.
*/
.statband {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 1px;
	margin: 34px 0 8px;
	background: var(--line);
	border: 1px solid var(--line);
	border-radius: var(--r);
	overflow: hidden;
}

.statcell {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 22px 20px;
	background: var(--panel);
}

.statfig {
	font-family: "Sora", system-ui, sans-serif;
	font-weight: 700;
	font-size: clamp(1.25rem, 2.1vw, 1.7rem);
	line-height: 1.05;
	letter-spacing: -.02em;
	color: var(--blue);
}

.statlab {
	font-size: .82rem;
	line-height: 1.4;
	color: var(--fg-2);
}

@media (max-width: 820px) {
	.statband { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* -------------------------------------- nav over a dark photo masthead */

/*
  Only while the nav is still transparent (.on arrives at 8px of scroll, and
  brings its own scrim). See inrico_body_class() for why this exists: without
  it, light mode paints navy links and the navy wordmark onto a dark
  photograph, and the nav is invisible until the reader scrolls.

  Specificity is doing real work in the logo pair below — the theme rules are
  `:root[data-theme="light"] .logo img.logo-l` at (0,3,1), so anything weaker
  loses and both marks stay wrong.
*/
body.dark-masthead .nav:not(.on) .navlinks > a:not(.btn),
body.dark-masthead .nav:not(.on) .themebtn {
	color: rgba(255, 255, 255, .88);
}

body.dark-masthead .nav:not(.on) .navlinks > a:not(.btn):hover,
body.dark-masthead .nav:not(.on) .navlinks > a:not(.btn).sel {
	color: #fff;
	background: rgba(255, 255, 255, .12);
}

body.dark-masthead .nav:not(.on) .themebtn {
	border-color: rgba(255, 255, 255, .3);
}
body.dark-masthead .nav:not(.on) .themebtn:hover {
	color: #fff;
	background: rgba(255, 255, 255, .14);
	border-color: rgba(255, 255, 255, .45);
}

body.dark-masthead .nav:not(.on) .logo img.logo-l { display: none; }
body.dark-masthead .nav:not(.on) .logo img.logo-d { display: block; }

/* ------------------------------------------------------- industries */

/*
  Alternating photo / copy rows, following the manufacturer's own industry
  pages. The photograph is full-bleed on its side and the copy sits in a
  contained column beside it, so the row reads as one band rather than a card
  floating in a container.
*/
.indjump {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 6px;
}

.indjump a {
	padding: 8px 15px;
	border-radius: 999px;
	border: 1px solid var(--line-2);
	color: var(--fg-2);
	text-decoration: none;
	font-size: .86rem;
	transition: color .25s var(--ease), background .25s var(--ease), border-color .25s var(--ease);
}
.indjump a:hover {
	color: var(--fg);
	background: var(--tint);
	border-color: var(--fg-3);
}

.indrow {
	border-top: 1px solid var(--line);
	/*
	  scroll-margin, not padding: the nav is position:fixed and roughly 72px
	  tall, so an in-page jump from .indjump would otherwise land the heading
	  underneath it.
	*/
	scroll-margin-top: 88px;
}

.indrow-in {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	align-items: center;
	gap: 54px;
	padding: 72px 0;
}

/* Even rows put the picture on the right. */
.indrow.flip .indrow-img { order: 2; }

.indrow-img {
	position: relative;
	aspect-ratio: 4 / 3;
	border-radius: var(--r);
	overflow: hidden;
	border: 1px solid var(--line);
}

.indrow-img img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.indrow-txt h2 {
	font-size: clamp(1.7rem, 3vw, 2.4rem);
	margin: 0 0 14px;
}

/*
  .ch already exists in inrico.css as `.indtxt .ch`, which is scoped to a
  component this template does not use. Restated here rather than widening
  that selector — widening it is exactly the specificity trap in HANDOFF §7.
*/
.indrow-txt .ch {
	font-size: .75rem;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--eyebrow);
	margin: 0 0 10px;
}

.indrow-body {
	color: var(--fg-2);
	line-height: 1.68;
	max-width: 52ch;
	margin: 0 0 26px;
}

.indpicks {
	margin: 0 0 28px;
	padding: 20px 22px;
	border: 1px solid var(--line);
	border-radius: var(--r-s);
	background: var(--tint);
}

.indpicks-h {
	font-size: .72rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--fg-3);
	margin: 0 0 12px;
	font-weight: 600;
}

.indpicks-l {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 2px;
}

.indpicks-l a {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	padding: 9px 0;
	border-bottom: 1px solid var(--line);
	text-decoration: none;
	color: inherit;
}
.indpicks-l li:last-child a { border-bottom: 0; }

.indpicks-n {
	font-weight: 600;
	color: var(--fg);
	font-size: .94rem;
}
.indpicks-l a:hover .indpicks-n { color: var(--blue); }

.indpicks-c {
	flex: 0 0 auto;
	font-size: .78rem;
	color: var(--fg-3);
}

.indcta {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 30px;
	flex-wrap: wrap;
	padding: 34px 36px;
	border: 1px solid var(--line);
	border-radius: var(--r);
	background: var(--panel);
}
.indcta h3 { margin: 0 0 6px; }
.indcta p  { margin: 0; max-width: 56ch; }

@media (max-width: 900px) {
	.indrow-in {
		grid-template-columns: 1fr;
		gap: 30px;
		padding: 52px 0;
	}
	/* the picture leads on every row once they stack — alternating sides is a
	   two-column idea and reads as an inconsistency in one column */
	.indrow.flip .indrow-img { order: 0; }
	.indrow-img { aspect-ratio: 16 / 9; }
}

/* ---------------------------------------------------- client logos */

/*
  Continuously scrolling proof strip. The track holds the list twice and moves
  by exactly -50%, so the wrap lands on an identical frame — see
  inrico_render_clients() for why the duplication is in markup.
*/
.cstrip {
	--cstrip-gap: 18px;
	position: relative;
	overflow: hidden;
	/* Fades the strip into the page at both ends instead of letting logos get
	   guillotined by the container edge. */
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}

.cstrip-track {
	display: flex;
	align-items: center;
	gap: var(--cstrip-gap);
	width: max-content;
	/*
	  The trailing gap is load-bearing, not padding for looks.

	  flex `gap` only fills BETWEEN items, so 96 tiles carry 95 gaps — while two
	  passes of 48 span 96 gaps' worth of distance. -50% therefore lands half a
	  gap short and the loop visibly ticks backwards 9px every cycle. Adding one
	  trailing gap makes the track exactly twice the per-pass span, so -50% is
	  exact. Measured, not assumed: half-track 8919px vs pass span 8928px.
	*/
	padding-right: var(--cstrip-gap);
	/*
	  No css animation here. wpfx.js drives the transform in px/second, because
	  a reduced-motion webview clamps css animation-duration to 0.01ms and the
	  strip becomes a blur. The keyframes below stay only as the no-js fallback.
	*/
	animation: cstrip-run var(--cstrip-dur, 60s) linear infinite;
}

/* Pause on hover so a visitor can actually read a logo they recognised. */
.cstrip:hover .cstrip-track { animation-play-state: paused; }

@keyframes cstrip-run {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(-50%, 0, 0); }
}

/*
  Someone who asked the OS for less motion should not be handed an endlessly
  moving strip. The logos stay, the movement stops, and the track wraps so all
  48 are still reachable.
*/
/*
  Reduced motion is handled in wpfx.js, which simply runs slower. It is not
  handled here because a css rule cannot win against a webview that clamps
  every animation to 0.01ms regardless of what the page asks for.
*/

.ctile {
	flex: 0 0 auto;
	width: 168px;
	height: 96px;
	display: grid;
	place-items: center;
	padding: 12px 16px;
	border-radius: var(--r-s);
	border: 1px solid var(--line);
	/*
	  Every tile is white, in BOTH themes, and that is deliberate. These are
	  other companies' trademarks: most are supplied as dark ink with no
	  transparency, so on the dark theme they would sit in an invisible box, and
	  recolouring someone else's mark to fit our palette is not ours to do.
	*/
	background: #fff;
}

/*
  The twelve supplied on a dark plate get a PURE BLACK tile, not the panel dark.
  build_clients.py crops each logo to its ink but the plate travels with it, so
  on #10141c every one of them showed a slightly-darker rectangle floating
  inside a slightly-lighter tile. Matching black exactly makes the plate
  invisible and the mark reads as sitting on the tile.
*/
.ctile.on-dark { background: #000; border-color: rgba(255, 255, 255, .14); }

.ctile img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
	display: block;
}

@media (max-width: 620px) {
	.ctile { width: 132px; height: 78px; padding: 10px 12px; }
	/* set the variable, not `gap` — padding-right has to track it or the seam
	   comes back at the smaller size */
	.cstrip { --cstrip-gap: 12px; }
}

/*
  The strip's own section. Tighter than a normal .sec because it is supporting
  evidence for the stat band above it, not a section in its own right — and it
  must not break the rhythm between the hero and "Where most fleets start".
*/
.cstrip-sec { padding: 44px 0 56px; }

.cstrip-h {
	margin: 0 0 22px;
	font-size: .78rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--fg-3);
	text-align: center;
}

/* --------------------------------------------------- Africa coverage */

/*
  A full-bleed band, deliberately short. Keagan asked for full width but not
  full height — this is a statement of reach on the way down the page, not a
  second hero that stops it.
*/
.covsec {
	position: relative;
	padding: 76px 0 0;
	overflow: hidden;
}

/*
  Clear air between the end of the paragraph and the top of the film, so the
  text reads as the band's heading rather than a caption laid over the picture.
*/
.covsec-head { text-align: center; margin-bottom: clamp(34px, 4.2vw, 56px); }

.covsec-head h2 { margin: 0 auto 14px; max-width: 20ch; }

.covsec-lead {
	color: var(--fg-2);
	line-height: 1.68;
	max-width: 60ch;
	margin: 0 auto;
}

/*
  The globe escapes .wrap. It is capped in height and the SVG crops rather than
  letterboxes, so a wide monitor gets a wide slice of planet instead of a tall
  circle pushing the rest of the page down.
*/
.covmap {
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	line-height: 0;
	/*
	  The film is a night sky in either theme, so the band carries its own dark
	  ground. It starts at the film, not at the top of the section: the fade
	  that used to begin behind the heading put dark text on near-black in
	  light mode.
	*/
	background: #05080f;
}

.covmap svg {
	display: block;
	width: 100%;
	height: clamp(280px, 42vw, 560px);
	object-fit: cover;
}

@media (max-width: 700px) {
	.covsec { padding-top: 54px; }
	.covmap svg { height: clamp(240px, 58vw, 380px); }
}

/* ------------------------------------- light tracing the status rail */

/*
  wpfx.js wraps .statusrail in .railwrap and lays a canvas over it, 22px larger
  on every side so the glow can spill past the border, then draws a point of
  light moving round the border at a constant speed. mountRail() explains why
  this replaced the rotating conic gradient that was here before.

  In wp.css rather than inrico.css because inrico.css is a verbatim copy of the
  prototype stylesheet and gets overwritten on every re-copy.
*/
.railwrap { position: relative; }

.railfx {
	position: absolute;
	pointer-events: none;
	z-index: 1;
}

/*
  The colours the light cycles through, as R, G, B. Brand blue and gold,
  brightened for the dark hero; deepened for light mode, where a pale glow
  disappears into the page. --railfx-core picks a white-hot centre (dark) or a
  solid one (light), and --railfx-blend whether the glow adds light or paints.
*/
:root {
	--railfx-1: 94, 200, 255;
	--railfx-2: 255, 182, 18;
	--railfx-3: 56, 150, 255;
	--railfx-core: white;
	--railfx-blend: lighter;
}
@media (prefers-color-scheme: light) {
	:root:not([data-theme="dark"]) {
		--railfx-1: 4, 107, 210;
		--railfx-2: 217, 119, 6;
		--railfx-3: 2, 132, 199;
		--railfx-core: colour;
		--railfx-blend: normal;
	}
}
:root[data-theme="light"] {
	--railfx-1: 4, 107, 210;
	--railfx-2: 217, 119, 6;
	--railfx-3: 2, 132, 199;
	--railfx-core: colour;
	--railfx-blend: normal;
}

/* ------------------------------------------------ dispatcher video band */

/*
  Full-bleed video with the copy sitting on it. The scrim is heavier on the
  left, where the text is, and opens up on the right so the control room and
  the radio on the desk are actually visible — the same idea as .leadband in
  inrico.css, and the reason the text is not centred over the middle of the
  shot.
*/
.vidband {
	position: relative;
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	min-height: min(74vh, 620px);
	display: flex;
	align-items: center;
	overflow: hidden;
	isolation: isolate;
	border-block: 1px solid var(--line);
	padding: 74px 0;
}

.vidband-bg {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 42%;
	z-index: -2;
	pointer-events: none;
}

.vidband::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	/* Fixed dark, not themed: it sits on a night-lit control room in both
	   themes, and light-mode tokens here would wash the footage out. */
	background: linear-gradient(90deg,
		rgba(4, 7, 14, .95) 0%,
		rgba(4, 7, 14, .88) 34%,
		rgba(4, 7, 14, .55) 62%,
		rgba(4, 7, 14, .30) 100%);
}

/*
  The measure goes on the CHILDREN, not on .vidband-in.
  .vidband-in is also a .wrap, and .wrap carries margin-inline:auto — so capping
  it at 46ch centred that 46ch block in the viewport instead of leaving the copy
  at the wrap's left edge, which is where the scrim is heaviest.
*/
.vidband-in {
	position: relative;
	color: #fff;
}

.vidband-in h2,
.vidband-lead { max-width: 46ch; }

.vidband-in h2 {
	margin: 0 0 16px;
	font-size: clamp(1.9rem, 3.4vw, 2.9rem);
	text-wrap: balance;
}

.vidband-lead {
	color: rgba(255, 255, 255, .82);
	line-height: 1.68;
	margin: 0 0 28px;
}

@media (max-width: 860px) {
	.vidband { min-height: 0; padding: 56px 0; }
	.vidband-in { max-width: none; }
	/* the copy needs the whole width on a phone, so the scrim goes vertical */
	.vidband::after {
		background: linear-gradient(180deg,
			rgba(4, 7, 14, .82) 0%,
			rgba(4, 7, 14, .92) 45%,
			rgba(4, 7, 14, .95) 100%);
	}
}

/* ------------------------------------------- exploded view: lab build */

/*
  Everything here is scoped under .exlab. The live section on the front page
  shares the same classes and must not pick any of this up — see
  page-explode-lab.php for what this is and why it exists separately.
*/
.exlab-intro .ch {
	font-size: .75rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--eyebrow);
	margin: 0 0 10px;
}

.exlab .exlab-grid {
	display: grid;
	grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
	gap: 56px;
	align-items: center;
}

.exlab-copy { max-width: 52ch; }

/* ---- progress rail ---- */

.exlab-rail {
	position: relative;
	height: 3px;
	border-radius: 3px;
	background: var(--line-2);
	margin: 26px 0 22px;
}

.exlab-rail-fill {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: linear-gradient(90deg, var(--blue), var(--gold));
	/*
	  Driven by --p, which the script sets to the scroll fraction. Deliberately
	  a custom property rather than the script writing `transform` directly:
	  the axis then belongs to the stylesheet, so a vertical rail at a narrower
	  breakpoint is a CSS change and not a second code path.
	*/
	transform: scaleX(var(--p, 0));
	transform-origin: left center;
	transition: transform .12s linear;
}

.exlab-pip {
	position: absolute;
	top: 50%;
	left: calc(var(--at) * 100%);
	width: 7px;
	height: 7px;
	margin: -3.5px 0 0 -3.5px;
	border-radius: 50%;
	background: var(--line-2);
	box-shadow: 0 0 0 3px var(--bg, transparent);
}

/* ---- steps ---- */

/*
  .exlist in inrico.css dims every item to 34% until it gains `.on`, and `.on`
  accumulates — by the end of the scroll all four are lit and none of them is
  "the one you are looking at". Here every item stays readable and a single
  `.cur` marks the current part, which is the thing the render is showing.
*/
.exlab .exlist li {
	opacity: 1;
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 14px;
	align-items: start;
	padding: 13px 16px;
	border-left: 2px solid transparent;
	border-radius: var(--r-s);
	transition: background .3s var(--ease), border-color .3s var(--ease);
}

.exlab .exlist li.cur {
	background: var(--tint);
	border-left-color: var(--blue);
}

.exlab-n {
	font-family: "JetBrains Mono", ui-monospace, monospace;
	font-style: normal;
	font-size: .72rem;
	letter-spacing: .06em;
	color: var(--fg-3);
	padding-top: 2px;
	transition: color .3s var(--ease);
}
.exlab .exlist li.cur .exlab-n { color: var(--blue); }

.exlab-t b { display: block; color: var(--fg); font-size: .96rem; }
.exlab-t span { display: block; color: var(--fg-2); font-size: .86rem; line-height: 1.5; margin-top: 3px; }

/* ---- stage ---- */

.exlab-stage { position: relative; }

/*
  A pool of light behind the render. The live version sits the radio on a flat
  panel; this gives it somewhere to be.
*/
.exlab-pool {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 78%;
	aspect-ratio: 1;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: radial-gradient(circle,
		rgba(4, 107, 210, .22) 0%,
		rgba(4, 107, 210, .10) 42%,
		transparent 70%);
	pointer-events: none;
}

.exlab-stage img { position: relative; z-index: 1; }

.exlab-hint {
	position: absolute;
	left: 50%;
	bottom: 4%;
	transform: translateX(-50%);
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 7px 14px;
	border-radius: 999px;
	border: 1px solid var(--line-2);
	background: var(--scrim-2);
	backdrop-filter: blur(8px);
	font-size: .76rem;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--fg-2);
	transition: opacity .5s var(--ease), transform .5s var(--ease);
	z-index: 2;
}
.exlab-hint svg { animation: exlab-nudge 1.9s ease-in-out infinite }
.exlab-hint.gone { opacity: 0; transform: translate(-50%, 10px); pointer-events: none }

@keyframes exlab-nudge {
	0%, 100% { transform: translateY(0) }
	50%      { transform: translateY(3px) }
}

/*
  The current part named next to the render, so the label and the thing it
  labels are in the same glance.
*/
.exlab-cap {
	position: absolute;
	left: 50%;
	top: 5%;
	transform: translate(-50%, -6px);
	padding: 8px 16px;
	border-radius: 999px;
	background: var(--blue);
	color: #fff;
	font-family: "Sora", system-ui, sans-serif;
	font-weight: 600;
	font-size: .84rem;
	white-space: nowrap;
	opacity: 0;
	transition: opacity .35s var(--ease), transform .35s var(--ease);
	z-index: 2;
	pointer-events: none;
}
.exlab-cap.show { opacity: 1; transform: translate(-50%, 0) }

@media (max-width: 900px) {
	.exlab .exlab-grid { grid-template-columns: 1fr; gap: 26px }
	.exlab-copy { max-width: none }
	.exlab-cap { display: none }
}

@media (prefers-reduced-motion: reduce) {
	.exlab-hint svg { animation: none }
}

/* The generated coverage film, in the same slot the SVG occupied. */
.covvid {
	display: block;
	width: 100%;
	height: clamp(280px, 42vw, 560px);
	object-fit: cover;
	background: #05080f;
}

@media (max-width: 700px) {
	.covvid { height: clamp(240px, 58vw, 380px); }
}

/* ------------------------------------------------ global network band */

/*
  Same construction as .vidband, kept separate rather than shared: that one is
  the dispatcher pitch on the home page and will drift as the copy there
  changes, and one band inheriting the other's scrim angle is how two unrelated
  sections end up coupled.
*/
.netband {
	position: relative;
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	min-height: min(62vh, 520px);
	display: flex;
	align-items: center;
	overflow: hidden;
	isolation: isolate;
	border-block: 1px solid var(--line);
	padding: 68px 0;
}

.netband-bg {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 40%;
	z-index: -2;
	pointer-events: none;
}

/*
  Weighted to the left where the copy sits and opening up to the right so the
  arcs stay visible. Fixed dark in both themes — it is a night shot, and light
  tokens here would grey the footage out.
*/
.netband::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(90deg,
		rgba(3, 6, 12, .94) 0%,
		rgba(3, 6, 12, .86) 32%,
		rgba(3, 6, 12, .50) 64%,
		rgba(3, 6, 12, .22) 100%);
}

.netband-in { position: relative; color: #fff; }

.netband-in .ch {
	font-size: .75rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--gold);
	margin: 0 0 12px;
	max-width: 46ch;
}

.netband-in h2 {
	margin: 0 0 16px;
	max-width: 22ch;
	font-size: clamp(1.8rem, 3.2vw, 2.7rem);
	text-wrap: balance;
}

.netband-lead {
	color: rgba(255, 255, 255, .82);
	line-height: 1.68;
	margin: 0;
	max-width: 52ch;
}

@media (max-width: 860px) {
	.netband { min-height: 0; padding: 52px 0; }
	.netband-in h2, .netband-lead, .netband-in .ch { max-width: none; }
	.netband::after {
		background: linear-gradient(180deg,
			rgba(3, 6, 12, .80) 0%,
			rgba(3, 6, 12, .92) 45%,
			rgba(3, 6, 12, .95) 100%);
	}
}

/* ------------------------------------------------------------- pricing */

/*
  Replaces the fleet cost calculator (removed 10 September 2026). One panel,
  copy on the left and the call to action on the right, from the same tokens as
  .indcta so the two read as the same family of component.
*/
.priceband {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 36px;
	flex-wrap: wrap;
	padding: 42px 44px;
	border: 1px solid var(--line);
	border-radius: var(--r);
	background:
		radial-gradient(120% 140% at 100% 0%, rgba(4, 107, 210, .14), transparent 55%),
		var(--panel);
}

.priceband-copy { max-width: 62ch; }

.priceband-copy h2 {
	margin: 0 0 12px;
	font-size: clamp(1.6rem, 2.8vw, 2.3rem);
}

.priceband-lead {
	margin: 0;
	color: var(--fg-2);
	line-height: 1.68;
}

.priceband-cta { display: flex; gap: 12px; flex-wrap: wrap; }

@media (max-width: 700px) {
	.priceband { padding: 30px 26px; }
}

/* ------------------------------------------------- guard patrol band */

/*
  The band itself is .leadband from inrico.css, unchanged. These rules cover
  only what WordPress adds: the button row under the copy, and the native
  <dialog> the card opens.
*/
.patrolband-cta {
	display: flex;
	gap: 11px;
	flex-wrap: wrap;
}

/*
  Native <dialog>, reset to a transparent frame so .modal-in — the prototype's
  panel, already styled in inrico.css — is what the visitor actually sees. The
  browser's own sheet gives a modal dialog a border, padding, a white background
  and a max size, and all four fight the panel.
*/
.patroldlg {
	border: 0;
	padding: 0;
	margin: auto;
	background: transparent;
	color: inherit;
	width: min(760px, calc(100% - 24px));
	max-width: none;
	max-height: none;
	overflow: visible;
}
.patroldlg .modal-in {
	width: 100%;
	scrollbar-width: thin; /* keeps a desktop scrollbar clear of the pinned close button */
}

/*
  The close button is a child of the dialog, not of the panel that scrolls, so
  it stays in the corner while the steps move underneath it. That needs a solid
  face: the prototype's transparent one would let the text show through.
*/
.patroldlg .modal-x {
	z-index: 2;
	background: var(--panel);
}
.patroldlg .modal-x:hover {
	background: linear-gradient(var(--tint), var(--tint)), var(--panel);
}

/* The same veil as the prototype's .modal-bd, on the real backdrop. */
.patroldlg::backdrop {
	background: rgba(2, 5, 12, .72);
	backdrop-filter: blur(6px);
}

.patroldlg-cta {
	display: flex;
	gap: 11px;
	flex-wrap: wrap;
	margin-top: 26px;
}

/* ----------------------------------------------------- support centre */

/*
  A filtered-out row has to actually disappear. `.accp.open`, `.dl` and the
  accordion buttons all set display with a class selector, and a class selector
  beats the browser's own [hidden] rule — so without this, the search box and
  the category pills would "hide" rows that stayed on screen.
*/
#support [hidden] { display: none !important; }

/*
  Each pane carries its own heading for when scripts are off and the five
  sections stack. With the tabs working it would repeat the tab label directly
  above itself, so it stays for screen readers and comes off the screen.
*/
.js-support .spane-h {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}

.sup-watch {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	color: var(--blue);
	font-size: .9rem;
	font-weight: 600;
}
.sup-watch:hover { text-decoration: underline; }

/*
  The certificate and download icons were gold strokes on a gold wash — fine on
  the dark theme, close to invisible on white. Same fix as the eyebrow labels:
  follow the contrast-safe token. The inrico.css background stays as the
  fallback for any browser without color-mix().
*/
.dl .ic svg { stroke: var(--eyebrow); }
.dl .ic { background: color-mix(in srgb, var(--eyebrow) 14%, transparent); }

/* ------------------------------------------- exploded view, home page */

/*
  The exploded view pins a full-height stage and centres the T522A in it, so the
  sections either side already sit a good part of a screen away. Drawing both
  neighbours in by up to 72px closes that up a little without changing the
  scroll length the animation is timed against. Desktop windows tall enough to
  spare the room only; below that the stage has none to give.
*/
@media (min-width: 901px) and (min-height: 700px) {
	body.home .explode { margin-block: calc(-1 * clamp(32px, 6vh, 72px)); }
}


/* -------------------------------------------------- explosion protection */

/*
  The Ex section on an intrinsically safe product, the "Ex certified" tag, and
  the "Special request" price. Amber is the colour the hazardous area world
  already uses for Ex, and it stays clear of the gold best-seller tag.
*/
:root {
	--ex: #f5a524;
	--ex-ink: #f7bd5a;
	--ex-on: #1a1200;
	--ex-soft: rgba(245, 165, 36, .11);
	--ex-line: rgba(245, 165, 36, .40);
}
@media (prefers-color-scheme: light) {
	:root:not([data-theme="dark"]) {
		--ex: #b45309;
		--ex-ink: #92400e;
		--ex-on: #fff;
		--ex-soft: rgba(180, 83, 9, .07);
		--ex-line: rgba(180, 83, 9, .32);
	}
}
:root[data-theme="light"] {
	--ex: #b45309;
	--ex-ink: #92400e;
	--ex-on: #fff;
	--ex-soft: rgba(180, 83, 9, .07);
	--ex-line: rgba(180, 83, 9, .32);
}

.tag.ex { background: var(--ex); color: var(--ex-on); }

.price.request {
	font-family: "Sora", sans-serif;
	font-weight: 600;
	font-size: 1.02rem;
	letter-spacing: .01em;
	color: var(--fg);
}

.hcard-h svg {
	width: 20px;
	height: 20px;
	flex: 0 0 auto;
	fill: none;
	stroke: var(--blue);
	stroke-width: 1.7;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.exsafe {
	border-top: 1px solid var(--line);
	background: radial-gradient(110% 80% at 0% 0%, var(--ex-soft), transparent 58%);
}
.exsafe-head { max-width: 70ch; margin-bottom: 30px; }
.exsafe-head h2 { margin: 14px 0 12px; font-size: clamp(1.7rem, 3vw, 2.4rem); text-wrap: balance; }
.exsafe-head p { margin: 0; line-height: 1.7; }

.exsafe-badge {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 6px 13px 6px 9px;
	border-radius: 999px;
	border: 1px solid var(--ex-line);
	background: var(--ex-soft);
	color: var(--ex-ink);
	font-family: "Sora", sans-serif;
	font-size: .72rem;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
}
.exsafe-badge svg {
	width: 18px;
	height: 18px;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.8;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.exsafe-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 1000px) {
	.exsafe-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.exconds { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
	.exsafe-grid { grid-template-columns: 1fr; }
}

.exmark,
.exconds {
	border: 1px solid var(--line);
	border-radius: var(--r);
	background: var(--panel);
	padding: 22px 22px 20px;
}
.exmark { border-top: 3px solid var(--ex); }

.exmark-k {
	font-family: "Sora", sans-serif;
	font-size: .72rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--fg-3);
}
.exmark-v {
	display: block;
	margin: 10px 0 16px;
	padding: 0;
	background: none;
	border: 0;
	font-family: "JetBrains Mono", monospace;
	font-size: clamp(1.08rem, 1.7vw, 1.38rem);
	font-weight: 500;
	color: var(--fg);
	white-space: normal;
}

.exmark ul,
.exconds ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.exmark li,
.exconds li { position: relative; padding-left: 22px; font-size: .93rem; line-height: 1.55; color: var(--fg-2); }
.exmark li::before {
	content: "";
	position: absolute;
	left: 3px;
	top: .56em;
	width: 7px;
	height: 7px;
	border-radius: 2px;
	background: var(--ex);
	transform: rotate(45deg);
}
.exmark-n {
	margin: 16px 0 0;
	padding-top: 14px;
	border-top: 1px dashed var(--line-2);
	font-size: .86rem;
	line-height: 1.55;
	color: var(--fg-3);
}

.exconds h3 { margin: 0 0 14px; font-size: 1.02rem; }
.exconds li::before {
	content: "!";
	position: absolute;
	left: 0;
	top: .2em;
	width: 15px;
	height: 15px;
	border-radius: 50%;
	background: var(--ex);
	color: var(--ex-on);
	font: 700 .62rem/15px "Sora", sans-serif;
	text-align: center;
}

.excert {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px 18px;
	margin-top: 20px;
	font-size: .92rem;
	color: var(--fg-2);
}
.excert b { font-family: "JetBrains Mono", monospace; font-weight: 500; color: var(--fg); }

.exnotice {
	margin: 16px 0 0;
	padding: 12px 15px;
	border-radius: var(--r-s);
	border: 1px solid rgba(220, 38, 38, .5);
	background: rgba(220, 38, 38, .1);
	color: var(--fg);
	font-size: .88rem;
	line-height: 1.5;
}


/* -------------------------------------------- travelling light on cards */

/*
  wpfx.js lays a canvas inside every [data-trace] box that does not clip its
  children. Negative z-index inside an isolated box puts the light above the
  box's own border and background but under its text.
*/
.has-trace { position: relative; isolation: isolate; }
.tracefx { position: absolute; pointer-events: none; z-index: -1; }

/* ------------------------------ In the box, with the approval cards beside it */

/*
  single-product.php renders In the box (.kitcol) and the approval cards
  (.marks, from inrico_render_marks) in one section. From 1081px they sit side
  by side, and a subgrid puts the two headings on one row even though the
  approvals carry a badge above theirs. Narrower, or without subgrid, they
  stack.
*/
.kitgrid { display: grid; row-gap: 64px; }
@media (min-width: 1081px) {
	.kitgrid.has-marks {
		grid-template-columns: minmax(220px, 1fr) minmax(0, 2.2fr);
		column-gap: 64px;
		row-gap: 0;
	}
	@supports (grid-template-rows: subgrid) {
		.kitgrid.has-marks > .kitcol,
		.kitgrid.has-marks > .marks {
			display: grid;
			grid-row: 1 / span 3;
			grid-template-rows: subgrid;
		}
		.kitgrid.has-marks .marks-badge { grid-row: 1; }
		.kitgrid.has-marks .kitcol > h3,
		.kitgrid.has-marks .marks-title { grid-row: 2; }
		.kitgrid.has-marks .kitcol > .glist,
		.kitgrid.has-marks .marks-body { grid-row: 3; }
	}
}
/* Grid items stretch by default, and the list's left rule has to stop at its last item. */
.kitcol > .glist { align-self: start; }

/* The Ex cards, recoloured from amber to brand blue. */
.marks {
	--ex: #3d94ff;
	--ex-ink: #86c3ff;
	--ex-on: #fff;
	--ex-soft: rgba(61, 148, 255, .11);
	--ex-line: rgba(61, 148, 255, .40);
}
@media (prefers-color-scheme: light) {
	:root:not([data-theme="dark"]) .marks {
		--ex: #046bd2;
		--ex-ink: #045cb4;
		--ex-soft: rgba(4, 107, 210, .07);
		--ex-line: rgba(4, 107, 210, .30);
	}
}
:root[data-theme="light"] .marks {
	--ex: #046bd2;
	--ex-ink: #045cb4;
	--ex-soft: rgba(4, 107, 210, .07);
	--ex-line: rgba(4, 107, 210, .30);
}
.marks-badge { justify-self: start; align-self: start; margin-bottom: 14px; }
.marks-title { margin: 0; }
.marks-lead { margin: 14px 0 22px; max-width: 70ch; line-height: 1.7; }
/* Two cards to a row at most: the column is too narrow for three. */
.marks .exsafe-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 900px; }
@media (max-width: 640px) {
	.marks .exsafe-grid { grid-template-columns: 1fr; }
}

/* ------------------------------------ support: moments in the walkthroughs */

/*
  Each Dispatcher and Guard patrol guide links to the part of its walkthrough
  video that shows how, with the time range beside the label. The Downloads tab
  lists every chapter of both videos under the full video.
*/
.sup-watch-list { display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 12px 0 0; }
.sup-ts {
	display: inline-block;
	padding: 3px 8px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--blue) 12%, transparent);
	color: var(--blue);
	font: 600 .74rem/1.2 "JetBrains Mono", ui-monospace, monospace;
	letter-spacing: .02em;
	white-space: nowrap;
}
.sup-watch .sup-ts { margin-left: 2px; }
.sup-watch:hover .sup-ts { text-decoration: none; }
.dl-video { margin-bottom: 16px; }
.dl-video > .dl { margin-bottom: 8px; }
.chapters {
	list-style: none;
	margin: 0 0 0 20px;
	padding: 2px 0 2px 16px;
	border-left: 1px solid var(--line);
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 2px 18px;
}
.chapters a {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 6px 8px;
	border-radius: 8px;
	color: var(--fg-2);
	font-size: .9rem;
	line-height: 1.35;
}
.chapters a:hover { background: var(--tint-2); color: var(--fg); }
.chapters .sup-ts { flex: 0 0 auto; min-width: 3.4em; text-align: center; }
@media (max-width: 640px) {
	.chapters { grid-template-columns: 1fr; margin-left: 8px; }
}

/* ------------------------------------ walkthrough chapters on platform products */

.walkthrough .walk-lead { margin: 10px 0 0; max-width: 70ch; line-height: 1.7; }
.walkthrough .chapters { margin: 20px 0 0; max-width: 980px; }

/*
 * The footer stays at the bottom of the window on a short page (News with one
 * article, an empty basket) instead of rising to meet the content, which left
 * a band of bare ground under it. body becomes a column and main takes the
 * height that is left. The admin bar's height comes off, so a logged-in editor
 * gets no scrollbar on a short page either. Asked for on 14 September 2026.
 */
body {
	display: flex;
	flex-direction: column;
	min-height: calc(100vh - var(--wp-admin--admin-bar--height, 0px));
}
@supports (min-height: 100dvh) {
	body { min-height: calc(100dvh - var(--wp-admin--admin-bar--height, 0px)); }
}
body > main { flex: 1 0 auto; }
body > footer { flex-shrink: 0; }

/* ------------------------------------------------ news article photos */

/*
 * Two photos side by side: the pair block in wp-import/news/news.json, for
 * portrait shots that would each run a whole screen tall at full width. One
 * column on a phone.
 */
.postbody .pfpair {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 14px;
	margin: 1.8em 0;
}
.postbody .pfpair figure { margin: 0; }
.postbody .pfpair img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--r-s);
}
.postbody .pfpair figcaption {
	margin-top: 10px;
	font-size: .82rem;
	color: var(--fg-2);
}
@media (max-width: 620px) {
	.postbody .pfpair { grid-template-columns: 1fr; }
}

/* A square or portrait photo on its own (class is-narrow), kept to a readable size. */
.prose > figure.is-narrow {
	max-width: 460px;
	margin-inline: auto;
}

/* ------------------------------------------------------ social links */

/* Facebook and Instagram under the footer blurb. */
.fsocial {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin: 18px 0 0;
}
footer .fsocial li { margin: 0; }
.fsocial a {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 7px 14px 7px 11px;
	border: 1px solid var(--line);
	border-radius: 999px;
	font-size: .86rem;
}
.fsocial a:hover { border-color: var(--fg-3); }
.fsocial svg { flex: none; }

/* Links inside an article read as links: the theme sets a { text-decoration: none } everywhere. */
.postbody p a,
.postbody li a {
	color: var(--blue);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}
.postbody p a:hover,
.postbody li a:hover { color: var(--hl-2); }

/* ------------------------------------------------------- wider pages */

/*
 * Wider pages (Keagan, 14 September 2026: everything felt "quite restricted to
 * the middle of the page"). The header runs across the whole window, logo at the
 * left edge and menu at the right; everything else sits in a 1680px column, up
 * from 1240px, with a side gutter that grows with the window. Reading text keeps
 * its own measure (article bodies, section leads, Support answers), so a
 * paragraph never stretches into one long line on a big screen.
 */
:root { --wrap: 1680px; --gutter: clamp(22px, 3.4vw, 72px); }
.wrap,
.exgrid { width: min(var(--wrap), 100% - 2 * var(--gutter)); }
.nav .wrap { width: calc(100% - 2 * var(--gutter)); }
@media (max-width: 620px) {
	.wrap,
	.exgrid,
	.nav .wrap { width: calc(100% - 30px); }
}

/* Support answers and trade terms stay readable in the wider column. */
.accp > * { max-width: 80ch; }

/*
 * The product photo fills its half of the hero but stops growing at 640px (or
 * 72% of the window), so the hero still fits a laptop screen. The width is set
 * because a max-height on a square box would otherwise narrow it as well.
 */
.pshot .main { width: 100%; max-height: min(640px, 72vh); }

/* The approval cards use the room the wider column gives them. */
.kitgrid .marks .exsafe-grid { max-width: none; }

/*
 * Grids with a known number of cards fill the row rather than leaving empty
 * columns: the eight featured products, the four related products and the four
 * suggestions on the missing-page screen run four across, and the News page
 * three. The shop keeps as many columns as fit.
 */
@media (min-width: 1100px) {
	.plist.is-four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
	.plist.is-posts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Article cards carry photographs, so the photo fills its frame instead of sitting inside it like a product shot. */
.plist.is-news .pcard-img,
.plist.is-posts .pcard-img { overflow: hidden; }
.plist.is-news .pcard-img img,
.plist.is-posts .pcard-img img { object-fit: cover; padding: 0; }
.plist.is-posts .pcard-img { aspect-ratio: 16 / 10; }

/* Under the lead story on the home page: two articles side by side, photo beside the headline. */
@media (min-width: 900px) {
	.plist.is-news { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.plist.is-news .card { flex-direction: row; }
	.plist.is-news .pcard-img { flex: 0 0 42%; aspect-ratio: auto; min-height: 220px; }
	.plist.is-news .pcard-b {
		flex: 1 1 auto;
		display: flex;
		flex-direction: column;
		justify-content: center;
		padding: 26px 30px;
		border-top: 0;
		border-left: 1px solid var(--line);
	}
}

/* The quote form: heading and note on the left, the form beside them. */
@media (min-width: 1100px) {
	#quote > .wrap {
		display: grid;
		grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
		column-gap: clamp(48px, 5vw, 110px);
		align-items: start;
	}
	#quote .sec-t { grid-column: 1; grid-row: 1 / span 2; display: block; margin-bottom: 0; }
	#quote > .wrap > :not(.sec-t) { grid-column: 2; }
}

/* Specification tables in two columns on a wide screen, balanced by height. */
@media (min-width: 1200px) {
	.specs { column-count: 2; column-gap: clamp(48px, 5vw, 96px); }
	.specs > h3,
	.specs > p { column-span: all; }
	.specs > h4 { break-after: avoid; }
	.specs tr { break-inside: avoid; }
}

/*
 * A larger logo (Keagan, 14 September 2026: it was "a bit tiny", and South
 * Africa under the name was hard to read). The files are 128px tall, so 60px
 * stays sharp on a high-density screen.
 */
.brand .logo img { height: 60px; }
@media (max-width: 620px) {
	.brand .logo img { height: 44px; }
}

/*
 * The stat sub-lines sit under their figures at every width. The wider rail gave
 * them room to sit beside the bold line, and Keagan wanted them underneath, as
 * before (14 September 2026). A long sub-line wraps inside its cell rather than
 * running into the next one.
 */
.statusrail .v { flex-direction: column; align-items: flex-start; }
.statusrail .v small { white-space: normal; }

/* ------------------------------------ product type and industry pages */

/*
 * page-landing.php. Built from pieces the site already uses (.keyspec, .plist,
 * .indpicks-l, .indjump, .indcta), with a split hero where an industry page has
 * a photograph. Sections sit close together; the last one carries the padding.
 */
.lhero { position: relative; padding: 136px 0 12px; }
.lhero-in { display: grid; grid-template-columns: minmax(0, 1fr); gap: 54px; align-items: center; }
.lhero.has-img .lhero-in { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); }
.lhero h1 { font-size: clamp(2.1rem, 4.2vw, 3.6rem); max-width: 18ch; margin: 10px 0 0; text-wrap: balance; }
.lhero .lead { margin: 20px 0 30px; }
.lhero .cta { display: flex; flex-wrap: wrap; gap: 12px; }
.lhero-img { position: relative; aspect-ratio: 4 / 3; border-radius: var(--r); overflow: hidden; border: 1px solid var(--line); }
.lhero-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.lfacts { margin-top: 48px; }

.lsec { padding: 72px 0 0; }
.lend { padding-bottom: 96px; }

.lpoints { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: 16px; }
.lpoint { border: 1px solid var(--line); border-radius: var(--r); padding: 26px 26px 28px; background: var(--tint-2); }
.lpoint h2 { font-size: 1.12rem; margin: 0 0 10px; }
.lpoint p { margin: 0; color: var(--fg-2); line-height: 1.65; }

.lguide { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr)); gap: 16px; }
.lguide-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px; padding: 22px 24px; border: 1px solid var(--line); border-radius: var(--r); background: var(--panel); }
.lguide-row h3 { font-size: 1.02rem; margin: 0 0 6px; }
.lguide-row p { margin: 0; color: var(--fg-2); font-size: .92rem; line-height: 1.6; }

.lsteps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr)); gap: 16px; }
.lsteps li { display: flex; gap: 16px; padding: 22px; border: 1px solid var(--line); border-radius: var(--r); background: var(--tint-2); }
.lsteps-n { flex: 0 0 auto; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--blue); color: #fff; font-weight: 600; font-size: .9rem; }
.lsteps h3 { font-size: 1rem; margin: 5px 0 6px; }
.lsteps p { margin: 0; color: var(--fg-2); font-size: .92rem; line-height: 1.6; }

.lblocks { display: grid; gap: 44px; }
.lblock { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); gap: 54px; padding-top: 30px; border-top: 1px solid var(--line); }
.lblock h2 { font-size: clamp(1.4rem, 2.2vw, 1.9rem); margin: 0; max-width: 20ch; }
.lblock-txt p { color: var(--fg-2); line-height: 1.72; max-width: 68ch; }
.lblock-txt p:last-child { margin-bottom: 0; }

.lcase { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 44px; align-items: center; padding: 36px; border: 1px solid var(--line); border-radius: var(--r); background: linear-gradient(165deg, var(--panel), var(--ink-2)); }
.lcase h2 { margin: 8px 0 12px; }
.lcase p { color: var(--fg-2); line-height: 1.7; max-width: 60ch; }
.lcase .keyspec { grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 0; }

.lfaq { display: grid; gap: 10px; }
.lfaq details { border: 1px solid var(--line); border-radius: var(--r-s); background: var(--tint-2); }
.lfaq summary { cursor: pointer; list-style: none; display: flex; justify-content: space-between; gap: 16px; padding: 17px 22px; font-family: "Sora", sans-serif; font-weight: 600; }
.lfaq summary::-webkit-details-marker { display: none; }
.lfaq summary::after { content: "+"; color: var(--fg-3); font-weight: 400; }
.lfaq details[open] summary::after { content: "\2212"; }
.lfaq details p { margin: 0; padding: 0 22px 20px; color: var(--fg-2); line-height: 1.7; max-width: 80ch; }

.lrel-h { font-size: .75rem; letter-spacing: .13em; text-transform: uppercase; color: var(--fg-3); margin: 0 0 12px; }
.lrel { margin: 0 0 40px; }

@media (max-width: 900px) {
	.lhero.has-img .lhero-in { grid-template-columns: 1fr; gap: 30px; }
	.lcase { grid-template-columns: 1fr; padding: 28px 24px; }
	.lblock { grid-template-columns: 1fr; gap: 14px; }
}
@media (max-width: 620px) {
	.lhero { padding-top: 112px; }
	.lguide-row { grid-template-columns: 1fr; gap: 12px; }
	.lcase .keyspec { grid-template-columns: 1fr; }
	.lsec { padding-top: 56px; }
}

/* The Industries page rows carry two buttons now: the shortlist, and the industry's own page. */
.indrow-txt .cta { display: flex; flex-wrap: wrap; gap: 12px; }

/* The footer gains an Industries column once those pages exist: five tracks on a wide screen. */
@media (min-width: 1000px) {
	.fgrid:has(> :nth-child(5)) { grid-template-columns: 1.4fr repeat(4, minmax(0, 1fr)); }
}

/* ---------------------------------------- industries photo grid (home) */

/*
 * From the "Channel Open" design concept (15 September 2026): seven photo
 * tiles, the first twice the size, each opening its industry page. Five
 * tracks on a wide screen, so the six smaller tiles fill two rows beside it.
 */
.indgrid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); grid-auto-rows: 220px; gap: 14px; }
.indtile { position: relative; display: block; overflow: hidden; border-radius: var(--r); border: 1px solid var(--line); color: #fff; text-decoration: none; }
.indtile:first-child { grid-column: span 2; grid-row: span 2; }
.indtile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .6s var(--ease); }
.indtile:hover img { transform: scale(1.045); }
/* Fixed dark, like the video bands: white type on a photograph in both themes. */
.indtile::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 30%, rgba(6, 10, 20, .9)); }
.indtile-b { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; display: grid; gap: 4px; padding: 18px 20px; }
.indtile-b b { font-family: "Sora", system-ui, sans-serif; font-weight: 700; font-size: 1.1rem; line-height: 1.15; letter-spacing: -.01em; }
.indtile-b small { font-size: .88rem; color: rgba(234, 240, 250, .84); }
.indtile:first-child .indtile-b { padding: 28px; }
.indtile:first-child .indtile-b b { font-size: clamp(1.5rem, 2.4vw, 2.2rem); }
.indtile:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
@media (max-width: 1100px) {
	.indgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.indtile:first-child { grid-row: span 1; }
}
@media (max-width: 560px) {
	.indgrid { grid-template-columns: 1fr; }
	.indtile:first-child { grid-column: auto; }
}

/* The dispatcher band's label and feature badges, on the video in both themes. */
.vidband-tag { color: rgba(255, 255, 255, .72); }
.vidband-feats { list-style: none; margin: 0 0 30px; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; max-width: 640px; }
.vidband-feats li { padding: 9px 12px; border-radius: 8px; border: 1px solid rgba(234, 240, 250, .24); background: rgba(6, 10, 20, .38); color: #fff; font: 500 .74rem/1 "JetBrains Mono", ui-monospace, monospace; letter-spacing: .08em; text-transform: uppercase; }

/* ---------------------------------------- product summary under the title (1.0.13) */

/* inrico_tidy_short_description() joins old page-builder headings into this one line. */
.pshort .psub { margin: 2px 0 12px; font-family: "Sora", system-ui, sans-serif; font-weight: 600; font-size: 1.15rem; line-height: 1.3; letter-spacing: -.01em; color: var(--fg); }
.pshort > p { margin: 0 0 8px; }
.pshort ul { margin: 10px 0 0; padding-left: 1.15em; }
