﻿/* AECA sub-page design systems
----------------------------------------------------------------------------------------------------

The 22 detail pages under Services, Industries and Products. Everything is namespaced under
`.aeca-sub`, and nothing here matches a bare Blocs class, so it cannot reach the home page, About,
Contact, Quote, Insights, Case Studies or the three hub pages.

THREE DESIGNS, NOT ONE
Requested 2026-08-10: each family gets its own design, and none of them copies its hub page. A
visitor should be able to tell which branch of the site they are in before reading a word. Siblings
*inside* a family stay identical to each other -- that is the other half of the same request.

	                SERVICES                  INDUSTRIES                PRODUCTS
	hero            dark navy, asymmetric.    light, centred on white   cinematic, full-bleed image,
	                copy left, a field        above a full-bleed band,  copy bottom-left, spec strip
	                bleeding off the right    facts seated on it
	hero ground     contour plot + control    lit field, plotting       the product name, oversize
	                mark                      grid across the air       and outlined
	grounds         white / pale tint         white / full navy         white / blueprint tint
	headings        index "01" + rule,        centred, rule beneath,    mono kicker, heading left,
	                heading left, lead right  no numbering              hairline under the head
	list style      numbered ledger rows      stacked bordered panels   compact spec rows
	card style      top accent bar, lifts     numbered blue square,     bordered tile, left rule,
	                                          horizontal                no lift
	accent          light blue #16ADEE        deep blue #024DA1         deep blue + red hairline

WHAT IS SHARED
The brand palette, the two typefaces, the container width, the placeholder figure and the underlying
grid geometry. Those are the site's, not the family's -- a page that changed typeface between
sections would read as a different website, which is not what "its own design" means here.

The accordions the Blocs export used are gone from all three. Four of five points arrived collapsed,
so the pages looked empty and the copy was invisible to anyone skimming.

NO PAGE SHOWS A PLACEHOLDER
All three heroes were rebuilt on 2026-08-13. 17 of the 20 detail pages have no photography, and until
that day those 17 opened on a grey plate with "PLACEHOLDER: ..." printed across it -- so most of the
site's depth read as unbuilt. Every hero now has two states: `--photo` where the template sets
`hero_image`, `--graphic` where it does not, same geometry either way, and the graphic state is a
designed ground rather than a holding one. The three grounds are listed in the table above and share
no motif, which is the one place the "tell the branch at a glance" rule is worth the most.

---------------------------------------------------------------------------------------------------- */

/* ====================================================================================================
   SHARED FOUNDATION
   Tokens, typography, the figure, and the bare geometry each family then restyles.
   ==================================================================================================== */

.aeca-sub {
	/* Local aliases of the tokens in aeca-custom.css, so a brand change flows through, but this
	   file can still be read on its own. */
	--sub-blue: var(--aeca-blue, #024da1);
	--sub-blue-light: var(--aeca-blue-light, #16adee);
	--sub-red: var(--aeca-red, #ec1c24);
	--sub-navy: #012340;
	--sub-navy-2: #01315a;
	--sub-ink: #14212e;
	--sub-muted: #4a5b6b;
	--sub-line: #d7e3ee;
	--sub-tint: #f2f7fb;
	--sub-white: #fff;

	/* Each family overrides these two. Everything below reads them rather than naming a colour, so
	   the family blocks stay short. */
	--sub-accent: var(--sub-blue-light);
	--sub-gap: clamp(56px, 7.5vw, 108px);

	color: var(--sub-ink);
	font-family: var(--aeca-font-body, "Inter", system-ui, sans-serif);
}

.aeca-sub :is(h1, h2, h3, h4, h5, h6) {
	font-family: var(--aeca-font-head, "Outfit", system-ui, sans-serif);
	letter-spacing: -0.015em;
}

.aeca-sub .container {
	max-width: 1180px;
}

.aeca-sub__eyebrow {
	margin: 0 0 0.6rem;
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.74rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	line-height: 1.2;
	text-transform: uppercase;
}

/* ---- Breadcrumb -------------------------------------------------------------------------------- */

.aeca-sub-hero__crumbs {
	margin: 0 0 1.15rem;
	font-size: 0.82rem;
	letter-spacing: 0.02em;
}

.aeca-sub-hero__crumbs ol {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 0.6rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.aeca-sub-hero__crumbs li {
	display: flex;
	gap: 0.6rem;
	align-items: center;
}

.aeca-sub-hero__crumbs li + li::before {
	content: "";
	width: 5px;
	height: 5px;
	border-top: 1px solid currentColor;
	border-right: 1px solid currentColor;
	opacity: 0.6;
	transform: rotate(45deg);
}

.aeca-sub-hero__crumbs a {
	color: inherit;
	text-decoration: none;
}

.aeca-sub-hero__crumbs a:hover,
.aeca-sub-hero__crumbs a:focus {
	text-decoration: underline;
}

/* ---- Placeholder figure ------------------------------------------------------------------------ */

/* Every image on all 22 pages is img/placeholder-image today. The frame, the ratio and the caption
   are what keep the layout legible while the real photography is outstanding; dropping a real file
   in later needs no CSS change. The caption is the brief for whoever supplies it -- delete the
   `caption` key in a template's data array and it disappears. */

.aeca-sub-figure {
	position: relative;
	margin: 0;
	overflow: hidden;
	background: #dce6ef;
}

.aeca-sub-figure img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	aspect-ratio: var(--sub-figure-ratio, 4 / 3);
}

/* ---- Real images: cleared ground, and an uncropped fit ------------------------------------------

   `--clear` is on every supplied image, cut-out or photograph. The `.aeca-sub-figure` grey belongs to
   the placeholder plate above; behind a transparent product render it is a grey rectangle, and a
   photograph covers its frame and never sees it. So it goes as soon as a real file arrives.

   `--contain` is the fit, for a manufacturer cut-out that has to be shown whole. A photograph
   survives a crop because there is more of it outside the frame; a cut-out does not, because the
   crop runs through the object. Note that a cut-out can still want a crop where its dead space sits
   at the edge rather than around the object -- that case keeps the default fit and trims with the
   ratio, so the two classes are independent. */

.aeca-sub-figure--clear {
	background: none;
}

/* The ratio moves from the image to the figure. On a cropped figure the image carries it, because
   the image is the thing being reshaped; here the image must keep its own shape, so the box has to
   hold the slot open instead. */
.aeca-sub-figure--contain {
	aspect-ratio: var(--sub-figure-ratio, 4 / 3);
}

.aeca-sub-figure--contain img {
	aspect-ratio: auto;
	object-fit: contain;
}

.aeca-sub-figure__label {
	position: absolute;
	left: 0;
	bottom: 0;
	max-width: 100%;
	padding: 0.5rem 0.85rem;
	background: rgba(1, 35, 64, 0.86);
	color: #cfe8f7;
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	line-height: 1.3;
	text-transform: uppercase;
}

/* ---- Hero canvas -------------------------------------------------------------------------------

   Shared by all three families since 2026-08-13. The canvas is whatever fills a hero's visual field:
   the supplied photograph on a `--photo` page, one of the three designed grounds on a `--graphic`
   one. Only the box is shared -- it fills its parent and clips to it, and everything about how it
   looks belongs to the family. Each family gives its own parent the `position` this absolute box
   resolves against: the services field, the industries band, the products stage.

   `--hero-position` is the template's focal point, set per page in the data array. It matters because
   these are field photographs and the crop is usually severe: the default centre puts the sky in the
   frame and the aircraft outside it. */

.aeca-sub-hero__canvas {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	background: var(--sub-navy);
}

.aeca-sub-hero__canvas img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: var(--hero-position, 50% 50%);
}

/* ---- Section shell ----------------------------------------------------------------------------- */

.aeca-sub-section {
	padding: var(--sub-gap) 0;
	background: var(--sub-white);
}

.aeca-sub-section--tint {
	background: var(--sub-tint);
}

.aeca-sub-section--navy {
	background: var(--sub-navy-2);
	color: var(--sub-white);
}

.aeca-sub-section__head {
	margin-bottom: clamp(30px, 4vw, 54px);
}

.aeca-sub-section__head h2 {
	margin: 0;
	color: var(--sub-blue);
	font-weight: 600;
	line-height: 1.06;
}

.aeca-sub-section__lead {
	margin: 0;
	color: var(--sub-muted);
	line-height: 1.68;
}

.aeca-sub-section--navy .aeca-sub-section__head h2 {
	color: var(--sub-white);
}

.aeca-sub-section--navy .aeca-sub-section__lead {
	color: rgba(255, 255, 255, 0.78);
}

/* ---- Split (copy beside a figure) -------------------------------------------------------------- */

.aeca-sub-split {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: clamp(28px, 5vw, 68px);
	align-items: center;
}

.aeca-sub-split--flip .aeca-sub-split__media {
	order: -1;
}

/* Without a photograph the split is one column, and its tick list is what fills the width.

   Left as a single column the list would run four items down a 1180px measure, which is both a long
   line to read and a tall stack for what is a summary. Two across keeps the line length close to what
   it was beside the figure and closes the block in two rows. The row gap matches the `li + li` spacing
   the one-column list uses, so a solo split and a split beside a photograph space their items alike.

   `margin-top` is cleared because the grid supplies the gap; leaving both would double the row. */
.aeca-sub-split--solo {
	grid-template-columns: minmax(0, 1fr);
}

.aeca-sub-split--solo .aeca-sub-checks {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	column-gap: clamp(28px, 4vw, 56px);
	row-gap: 0.95rem;
}

.aeca-sub-split--solo .aeca-sub-checks li + li {
	margin-top: 0;
}

.aeca-sub-split__body > p {
	color: var(--sub-muted);
	font-size: 1.03rem;
	line-height: 1.72;
}

.aeca-sub-split__body > p:last-of-type {
	margin-bottom: 0;
}

.aeca-sub-section--navy .aeca-sub-split__body > p {
	color: rgba(255, 255, 255, 0.8);
}

.aeca-sub-checks {
	margin: 1.5rem 0 0;
	padding: 0;
	list-style: none;
}

.aeca-sub-checks li {
	position: relative;
	padding: 0 0 0 2.1rem;
	color: var(--sub-muted);
	font-size: 1rem;
	line-height: 1.65;
}

.aeca-sub-checks li + li {
	margin-top: 0.95rem;
}

.aeca-sub-checks li strong {
	display: block;
	margin-bottom: 0.2rem;
	color: var(--sub-blue);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 1.06rem;
	font-weight: 600;
}

.aeca-sub-section--navy .aeca-sub-checks li {
	color: rgba(255, 255, 255, 0.78);
}

.aeca-sub-section--navy .aeca-sub-checks li strong {
	color: var(--sub-white);
}

/* ---- Band: one wide figure inside a section ----------------------------------------------------

   Added 2026-09-04 with aeca_subpage_section_figure(). It is a `figure` key on an existing section
   rather than a section of its own, so it renders between the body and the section CTA and takes no
   index off the numbering -- see the note above the function in functions/subpages.php.

   The frame is the family's card and not a new object: square corners, the same 1px hairline, the
   same accent stub. What it does not take from the card is the hover -- there is nothing to click,
   and a plate that lifts under the pointer promises a link it does not have.

   The ratio lives on the wrapper rather than on the image so the caption bar sits outside it: the
   band is `image at --sub-band-ratio` plus however tall the caption runs, which keeps a two-line
   caption on a phone from eating into the picture. Both files placed today are already cut to 2:1,
   so `object-fit: cover` has nothing to crop and `position` is only there for a file that is not. */

.aeca-sub-band {
	position: relative;
	margin: clamp(30px, 4vw, 52px) 0 0;
	border: 1px solid var(--sub-line);
	background: var(--sub-white);
}

.aeca-sub-band__frame {
	overflow: hidden;
}

.aeca-sub-band__img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: var(--sub-band-ratio, 2 / 1);
	object-fit: cover;
}

/* Label left, sentence right, on one hairline-separated row. Two columns and not a flex row because
   the label is a fixed short tag and the sentence is what should take the remaining width; `auto`
   plus `minmax(0, 1fr)` does that without a width on either. */
.aeca-sub-band__cap {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: 0.5rem clamp(16px, 2.4vw, 30px);
	align-items: baseline;
	padding: clamp(14px, 1.6vw, 20px) clamp(16px, 2vw, 26px);
	border-top: 1px solid var(--sub-line);
}

.aeca-sub-band__label {
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.2em;
	line-height: 1.4;
	text-transform: uppercase;
	white-space: nowrap;
}

.aeca-sub-band__text {
	color: var(--sub-muted);
	font-size: 0.95rem;
	line-height: 1.62;
}

/* On the tinted ground the white plate is what separates the band from the section, so the caption
   bar keeps the plate rather than going transparent. Nothing to override there -- the rule exists to
   say the navy case is the only one that moves. */
.aeca-sub-section--navy .aeca-sub-band {
	border-color: rgba(255, 255, 255, 0.22);
	background: rgba(255, 255, 255, 0.05);
}

.aeca-sub-section--navy .aeca-sub-band__cap {
	border-top-color: rgba(255, 255, 255, 0.22);
}

.aeca-sub-section--navy .aeca-sub-band__text {
	color: rgba(255, 255, 255, 0.78);
}

/* ---- Cards that are links ---------------------------------------------------------------------- */

/* The anchor covers the whole tile, but only the heading text is inside it, so the link's name is
   "Trinity" and not the paragraph after it. Shared across the three families because the mechanism
   is the same; each family's own card rules still supply the colour and the border. */

.aeca-sub-card--link {
	position: relative;
}

.aeca-sub-card__link {
	color: inherit;
	text-decoration: none;
}

.aeca-sub-card__link::after {
	content: "";
	position: absolute;
	inset: 0;
}

/* The arrow, drawn the same way as the one in the sibling strip so the two read as one affordance. */
.aeca-sub-card__go {
	position: relative;
	display: block;
	width: 26px;
	height: 8px;
	margin-top: 1.5rem;
	border-bottom: 2px solid currentColor;
	color: var(--sub-accent);
	opacity: 0.65;
	transition: transform 0.18s ease, opacity 0.18s ease;
}

.aeca-sub-card__go::after {
	content: "";
	position: absolute;
	right: 0;
	bottom: -4px;
	width: 8px;
	height: 8px;
	border-top: 2px solid currentColor;
	border-right: 2px solid currentColor;
	transform: rotate(45deg);
}

/* Push the arrow to the foot of the tile so a short card and a long one still line up.

   The class is doubled to clear each family's own `.aeca-sub-card p { margin: 0 }`, which is set
   later in this file at the same specificity and was silently winning. It went unnoticed while one
   linked tile sat at the end of a row of five; the three sector tiles on solutions-mobile put three
   of them side by side, where the arrows landing at two different heights is plain. */
.aeca-sub .aeca-sub-card.aeca-sub-card--link .aeca-sub-card__body > p {
	margin-bottom: auto;
}

.aeca-sub-card--link:hover .aeca-sub-card__go,
.aeca-sub-card--link:focus-within .aeca-sub-card__go {
	transform: translateX(5px);
	opacity: 1;
}

.aeca-sub-section--navy .aeca-sub-card__go {
	color: var(--sub-blue-light);
}

/* ---- Cards with an icon, and cards with a disclosure -------------------------------------------- */

/* Both added 2026-09-01 for the Mobile Mapping brief. Every card key they hang off is optional, so
   the nineteen pages that pass neither render byte for byte as they did.

   The disclosure is the one place a fold comes back after the Blocs accordions were stripped, and it
   is deliberately not the same pattern: the card's title and its summary line never collapse, only
   the four supporting points do. A skim gets the whole argument; a reader who wants the detail opens
   one card. See the note at the top of this file for what the original accordions did wrong. */

/* ---- One row per card grid ---------------------------------------------------------------------

AECA's rule of 2026-09-01: the card grids on the detail pages sit on a single row. The renderer sets
the class from the number of cards -- see aeca_subpage_body_cards() for why auto-fit could not do it
and which grids are exempt.

The class is doubled in each selector because all three families set their own
`.aeca-sub-cards { grid-template-columns: ... }` later in this file at the same specificity, and would
otherwise win on source order. */

.aeca-sub .aeca-sub-cards.aeca-sub-cards--cols-3 {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.aeca-sub .aeca-sub-cards.aeca-sub-cards--cols-4 {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* Two columns is only ever asked for explicitly, through a section's `columns`. The renderer still
   never derives it -- a two-card grid is already a row and needs no class. */
.aeca-sub .aeca-sub-cards.aeca-sub-cards--cols-2 {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* ---- Inset grid ---------------------------------------------------------------------------------

Added 2026-09-03 for the six industry tiles on page-solutions-geo.php. A grid that fills every cell of
every row squares off against the 1180px container and reads wider than the heading and lead above it,
which are measure-capped. Pulling it in on both sides is what centres it against that copy.

The padding is symmetrical, so the grid stays centred at every width, and it is a max of 72px a side:
enough to be read as deliberate, not so much that three 376px cards drop under 300px. Tablet and below
get none of it -- the container's own gutters are already the whole margin there, and taking more would
push the cards under a readable measure. */
.aeca-sub .aeca-sub-cards.aeca-sub-cards--inset {
	padding-right: clamp(0px, 5vw, 72px);
	padding-left: clamp(0px, 5vw, 72px);
}

@media (max-width: 991.98px) {
	.aeca-sub .aeca-sub-cards.aeca-sub-cards--inset {
		padding-right: 0;
		padding-left: 0;
	}
}

.aeca-sub-card__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 58px;
	height: 58px;
	margin-bottom: 1.15rem;
	border-radius: 50%;
	background: #eaf6fd;
	color: var(--sub-blue);
}

/* The base .aeca-icon rule is 68px, which would burst the 58px circle, so both states are sized
   here. The PNG artwork is set larger than the drawn SVG because it carries its own padding. */
.aeca-sub-card__icon .aeca-icon {
	width: 30px;
	height: 30px;
}

.aeca-sub-card__icon .aeca-icon--art {
	width: 40px;
	height: 40px;
}

.aeca-sub-section--navy .aeca-sub-card__icon {
	background: rgba(255, 255, 255, 0.1);
	color: var(--sub-white);
}

/* z-index lifts the control clear of a link card's stretched overlay, so a card carrying both `url`
   and `details` still opens. */
/* margin-top:auto is what lines the controls up with each other. The cards are flex columns of
   equal height, so without it the rule and its label sit wherever that card's summary happened to
   end, and three cards whose copy runs to three, three and four lines show three different
   baselines. */
.aeca-sub-card__more {
	position: relative;
	z-index: 1;
	margin-top: auto;
	padding-top: 1.05rem;
	border-top: 1px solid var(--sub-line);
}

/* The summary above it needs the breathing room the auto margin no longer guarantees. Scoped through
   .aeca-sub to outrank each family's own `.aeca-sub-card p { margin: 0 }`, which is set later. */
.aeca-sub .aeca-sub-card:has(.aeca-sub-card__more) .aeca-sub-card__body > p {
	margin-bottom: 1.15rem;
}

/* display:flex is doing two jobs -- it lays out the label against the chevron, and it is what
   removes the default disclosure triangle in WebKit and Firefox. list-style covers the rest. */
.aeca-sub-card__more summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.6rem;
	color: var(--sub-blue);
	cursor: pointer;
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	list-style: none;
	text-transform: uppercase;
}

.aeca-sub-card__more summary::-webkit-details-marker {
	display: none;
}

.aeca-sub-card__more summary:focus-visible {
	outline: 2px solid var(--sub-accent);
	outline-offset: 4px;
}

/* Chevron drawn from two borders, so the control needs no file and takes the text colour with it. */
.aeca-sub-card__more summary::after {
	content: "";
	width: 7px;
	height: 7px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	color: var(--sub-accent);
	transform: translateY(-2px) rotate(45deg);
	transition: transform 0.18s ease;
}

.aeca-sub-card__more[open] summary::after {
	transform: translateY(2px) rotate(-135deg);
}

.aeca-sub-card__more ul {
	margin: 0.95rem 0 0;
	padding: 0;
	list-style: none;
}

.aeca-sub-card__more li {
	position: relative;
	margin-bottom: 0.6rem;
	padding-left: 1.15rem;
	color: var(--sub-muted);
	font-size: 0.94rem;
	line-height: 1.62;
}

.aeca-sub-card__more li:last-child {
	margin-bottom: 0;
}

.aeca-sub-card__more li::before {
	content: "";
	position: absolute;
	top: 0.62em;
	left: 0;
	width: 6px;
	height: 6px;
	background: var(--sub-accent);
}

.aeca-sub-section--navy .aeca-sub-card__more {
	border-top-color: rgba(255, 255, 255, 0.18);
}

.aeca-sub-section--navy .aeca-sub-card__more summary {
	color: var(--sub-white);
}

.aeca-sub-section--navy .aeca-sub-card__more li {
	color: rgba(255, 255, 255, 0.78);
}

/* The same block with the disclosure taken off, for a card that shows its supporting points rather
   than folding them -- `points` instead of `details` in the section array. Everything above already
   applies through the shared class; the only thing this adds is the gap the missing summary row used
   to leave, and the `margin-top: auto` is kept so a row of three still lines its lists up with each
   other when the paragraphs above them run to different lengths. */
.aeca-sub-card__more.is-open {
	padding-top: 1.15rem;
}

.aeca-sub-card__more.is-open ul {
	margin-top: 0;
}

/* ---- Section footer CTA ------------------------------------------------------------------------ */

/* One prompt and one outline button under a section body -- see aeca_subpage_section_cta().

   Deliberately quiet. Three of these run down page-solutions-geo.php and the dark conversion panel
   still closes the page below them, so a filled button here would put four calls to action on one
   page with nothing to separate the last one. An outline button on the section's own ground reads as
   a route out of this section rather than as the page's main action.

   The rule above it is the same hairline the ledger rows and card lists use, so it groups with the
   section rather than floating between two of them. */
.aeca-sub-section__cta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.9rem 1.75rem;
	align-items: center;
	justify-content: space-between;
	margin-top: clamp(28px, 3.4vw, 44px);
	padding-top: clamp(20px, 2.4vw, 28px);
	border-top: 1px solid var(--sub-line);
}

.aeca-sub-section__cta > p {
	max-width: 62ch;
	margin: 0;
	color: var(--sub-muted);
	font-size: 1.02rem;
	line-height: 1.6;
}

/* The typography `.const-button` would have carried, restated here because that class cannot be used
   -- see the note in aeca_subpage_section_cta(). Same uppercase Outfit at the same size as every
   other button on the site; only the colours differ. */
.aeca-sub-section__cta-btn {
	flex: 0 0 auto;
	padding: 0.7rem 1.5rem;
	border: 1px solid var(--sub-blue);
	background: transparent;
	color: var(--sub-blue);
	font-size: 0.95rem;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}

.aeca-sub-section__cta-btn:hover,
.aeca-sub-section__cta-btn:focus-visible {
	border-color: var(--sub-blue);
	background: var(--sub-blue);
	color: var(--sub-white);
}

.aeca-sub-section--navy .aeca-sub-section__cta {
	border-top-color: rgba(255, 255, 255, 0.18);
}

.aeca-sub-section--navy .aeca-sub-section__cta > p {
	color: rgba(255, 255, 255, 0.8);
}

.aeca-sub-section--navy .aeca-sub-section__cta-btn {
	border-color: rgba(255, 255, 255, 0.55);
	color: var(--sub-white);
}

.aeca-sub-section--navy .aeca-sub-section__cta-btn:hover,
.aeca-sub-section--navy .aeca-sub-section__cta-btn:focus-visible {
	border-color: var(--sub-white);
	background: var(--sub-white);
	color: var(--sub-navy);
}

/* ---- Prose: paragraphs laid out in columns ----------------------------------------------------- */

/* See aeca_subpage_body_prose(). `auto-fit` on a 340px floor: two paragraphs run two across on a
   desktop and stack below about 760px, and one paragraph keeps the 68ch cap a solo split gets rather
   than running the full container. */
.aeca-sub-prose {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
	column-gap: clamp(28px, 4vw, 64px);
	row-gap: 1.25rem;
}

.aeca-sub-prose > p {
	max-width: 68ch;
	margin: 0;
	color: var(--sub-muted);
	font-size: 1.03rem;
	line-height: 1.72;
}

.aeca-sub-section--navy .aeca-sub-prose > p {
	color: rgba(255, 255, 255, 0.8);
}

/* ---- Spec table (Products, but defined here with the other tables) ------------------------------ */

/* The Blocs export held these as list items with the label and value run together into one string --
   "Wingspan2.4 m" -- which is unreadable as text and meaningless to a screen reader. A two-column
   table with a row header per spec is what the data actually is.

   TIGHTENED 2026-09-02. It was built at body-copy size on body-copy padding: 16px type in 15/18px
   cells, which is a 57px row. Trinity carries fourteen of them, so the table ran 883px -- taller than
   a laptop viewport for a block whose longest value is "11 m/s in hover phase, 14 m/s during cruise"
   and whose typical one is "5.75 kg". A spec sheet is scanned down the left column and read across;
   it is reference material, not prose, and it does not want prose measure.

   What changed, and why each: type down one step to 0.92rem, which is the size the site already uses
   for the card leads; cell padding roughly halved on the vertical, which is where the height was;
   line-height 1.6 -> 1.45, because a single-line value has nothing to lead against. The row comes out
   at about 40px and the fourteen-row table at about 610px.

   The label column also comes in from 36% to 28%. Nothing in it needs 416px -- the longest label on
   any of the twelve product pages is "Maximum take-off altitude" -- and the width was pushing the two
   halves of each row so far apart that the eye lost the pairing across the middle of the table.

   The table stays full container width rather than being capped. The section's heading row above it
   spans the full 1180px, and a narrower table under a full-width rule reads as an alignment mistake
   rather than as a decision. */

.aeca-sub-specs {
	overflow-x: auto;
}

.aeca-sub-specs table {
	width: 100%;
	border-collapse: collapse;
	background: var(--sub-white);
}

/* The padding is on the TOP. Bootstrap's reboot in css/all.css computes `caption-side: bottom` here,
   so this line renders under the last row, not over the first -- the source note belongs there anyway.
   The rule had its 1rem on the bottom, which put the gap below the caption and left the caption itself
   sitting against the table's last border. It was hard to see at 57px rows; at 42px it is not. */
.aeca-sub-specs caption {
	padding: 0.7rem 0 0;
	color: var(--sub-muted);
	font-size: 0.88rem;
	text-align: left;
}

.aeca-sub-specs th,
.aeca-sub-specs td {
	padding: 0.62rem 0.95rem;
	border-bottom: 1px solid var(--sub-line);
	text-align: left;
	vertical-align: top;
}

.aeca-sub-specs thead th {
	padding-top: 0.4rem;
	padding-bottom: 0.5rem;
	border-bottom: 2px solid var(--sub-blue);
	color: var(--sub-blue);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.66rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.aeca-sub-specs tbody th {
	width: 28%;
	color: var(--sub-ink);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.92rem;
	font-weight: 600;
	line-height: 1.45;
}

.aeca-sub-specs tbody td {
	color: var(--sub-muted);
	font-size: 0.92rem;
	line-height: 1.45;
}

.aeca-sub-specs tbody tr:nth-child(even) {
	background: var(--sub-tint);
}

/* Shown instead of the table where the real numbers are not confirmed. Honest by design: a table of
   invented values is worse than saying the datasheet is available on request. */
.aeca-sub-specs-pending {
	padding: clamp(24px, 3vw, 38px);
	border: 1px dashed #9ab5c8;
	background: var(--sub-white);
}

.aeca-sub-specs-pending p {
	margin: 0;
	color: var(--sub-muted);
	font-size: 1rem;
	line-height: 1.65;
}

.aeca-sub-specs-pending strong {
	display: block;
	margin-bottom: 0.35rem;
	color: var(--sub-blue);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 1.16rem;
	font-weight: 600;
}

/* ---- Stories ----------------------------------------------------------------------------------- */

.aeca-sub-stories {
	display: grid;
	gap: clamp(18px, 2.4vw, 30px);
}

.aeca-sub-story {
	display: grid;
	grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.6fr);
	gap: clamp(20px, 3vw, 46px);
	padding: clamp(24px, 3vw, 38px);
	background: var(--sub-white);
}

.aeca-sub-story h3 {
	margin: 0;
	color: var(--sub-blue);
	font-size: clamp(1.2rem, 1.9vw, 1.55rem);
	font-weight: 600;
	line-height: 1.2;
}

.aeca-sub-story__meta {
	margin: 0.7rem 0 0;
	color: var(--sub-muted);
	font-size: 0.86rem;
	line-height: 1.55;
}

.aeca-sub-story dl {
	margin: 0;
}

.aeca-sub-story dt {
	margin: 0 0 0.25rem;
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.aeca-sub-story dd {
	margin: 0 0 1.15rem;
	color: var(--sub-muted);
	font-size: 1rem;
	line-height: 1.68;
}

.aeca-sub-story dd:last-child {
	margin-bottom: 0;
}

/* ---- Sibling strip ----------------------------------------------------------------------------- */

/* The hairlines are a box-shadow on each cell rather than a 1px gap over a coloured container. The
   container trick is neater to write, but the last row rarely fills, and the container's colour
   showed through the empty tracks as a solid block that looked like a broken card. */

.aeca-sub-siblings {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
	gap: 1px;
}

.aeca-sub-sibling {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 1.4rem;
	min-height: 152px;
	padding: clamp(20px, 2.2vw, 28px);
	text-decoration: none;
	transition: background-color 0.18s ease, color 0.18s ease;
}

.aeca-sub-sibling span:first-child {
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: clamp(1.02rem, 1.4vw, 1.18rem);
	font-weight: 600;
	line-height: 1.3;
}

/* The arrow. Drawn, not an icon font, and it slides on hover. */
.aeca-sub-sibling span:last-child {
	position: relative;
	display: block;
	width: 26px;
	height: 8px;
	border-bottom: 2px solid currentColor;
	opacity: 0.55;
	transition: transform 0.18s ease, opacity 0.18s ease;
}

.aeca-sub-sibling span:last-child::after {
	content: "";
	position: absolute;
	right: 0;
	bottom: -4px;
	width: 8px;
	height: 8px;
	border-top: 2px solid currentColor;
	border-right: 2px solid currentColor;
	transform: rotate(45deg);
}

.aeca-sub-sibling:hover span:last-child,
.aeca-sub-sibling:focus span:last-child {
	transform: translateX(5px);
	opacity: 1;
}


/* ====================================================================================================
   SERVICES
   ----------------------------------------------------------------------------------------------------
   Dark, asymmetric, engineering-report. The page opens on navy with a hairline survey grid, the copy
   and the media sit side by side rather than stacked, and the body of the page is a numbered ledger:
   every point visible, counted, in order. Light blue is the accent throughout.
   ==================================================================================================== */

.aeca-sub--services {
	--sub-accent: var(--sub-blue-light);
}

/* ---- Hero -------------------------------------------------------------------------------------- */

/* ---- Hero: rebuilt 2026-08-13 -------------------------------------------------------------------

   The asymmetry is the same one the 2026-08-10 request asked for -- copy left, media right -- but the
   media is no longer a bordered 5:4 box sitting inside the 1180px container. It is a field anchored
   to the right edge of the VIEWPORT that dissolves into the navy before it reaches the copy, so the
   two halves are one surface with a soft join rather than a page with a picture pasted onto it.

   WHY THE FIELD IS MASKED AND NOT BORDERED. The old panel had a hairline border and a blue corner
   tick, which were doing the job of making a grey placeholder plate look deliberate. With a designed
   ground behind it there is nothing to apologise for, and a border would only re-cut the surface the
   mask exists to join. The corner tick moves onto the contour ground instead, where it belongs. */

.aeca-sub--services .aeca-sub-hero {
	position: relative;
	background: var(--sub-navy);
	color: var(--sub-white);
}

/* The stage carries the survey grid and the whole of the copy; the fact rail sits outside it so the
   grid stops at the rail rather than running under it. */
.aeca-sub--services .aeca-sub-hero__stage {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	padding: clamp(58px, 8vw, 104px) 0 clamp(46px, 6vw, 78px);
}

/* Hairline survey grid over the whole stage. Pure CSS rather than an image so it costs nothing and
   scales at any width; the mask fades it out before it reaches the fact rail. */
.aeca-sub--services .aeca-sub-hero__stage::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background-image:
		linear-gradient(to right, rgba(255, 255, 255, 0.055) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
	background-size: 78px 78px;
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 88%);
	mask-image: linear-gradient(to bottom, #000 0%, transparent 88%);
	pointer-events: none;
}

/* ---- The right-hand field ----------------------------------------------------------------------

   52% of the viewport, bled to the right edge, with its left quarter masked away. On a 1440px screen
   that puts the first opaque pixel around 865px while the copy column ends at ~690px, so the two
   never touch; on a 1280px screen the mask is what keeps them apart, which is why it is a percentage
   of the field and not a fixed distance.

   `inset: 0` rather than a height: the field is exactly as tall as the stage, so the ground and the
   grid always end on the same line. */
.aeca-sub--services .aeca-sub-hero__field {
	position: absolute;
	inset: 0 0 0 auto;
	z-index: 0;
	width: min(52%, 900px);
	-webkit-mask-image: linear-gradient(to right, transparent 0%, #000 26%);
	mask-image: linear-gradient(to right, transparent 0%, #000 26%);
	pointer-events: none;
}

/* ---- A photograph fills the stage --------------------------------------------------------------

   The 52% field above is drawn for the designed ground, which is a motif that wants an edge to stop
   at. A photograph in the same box reads as half a hero: flat navy on the left, picture on the right,
   with a seam down the middle. AECA called it on 2026-08-26 and they are right -- a scene has no
   reason to stop at 52%.

   So a `--photo` services hero takes the whole stage. The horizontal mask goes with the width: it
   existed to keep the field off the copy column, and once the image is full-bleed there is nothing to
   keep apart, only something to read over.

   Only the `--photo` state changes. The six `--graphic` siblings keep the 52% field and its mask
   exactly as they were, so nothing moves on a page without photography. */
.aeca-sub--services .aeca-sub-hero--photo .aeca-sub-hero__field {
	width: 100%;
	-webkit-mask-image: none;
	        mask-image: none;
}

/* Two passes over the photograph, and both are doing a job rather than tinting for its own sake.

   Horizontal: white type on a bright sky is unreadable, so the copy column keeps a ground. It is
   strongest at the left edge, where the headline is, and reaches zero at 72%, so the crew, the
   receiver and the tripod on the right of the frame are seen through nothing at all.

   Vertical: the foot of the image seats against the fact rail instead of being cut off by it. This
   was the whole of the old rule and it is unchanged. */
.aeca-sub--services .aeca-sub-hero--photo .aeca-sub-hero__field::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		linear-gradient(to right, rgba(1, 24, 44, 0.90) 0%, rgba(1, 24, 44, 0.72) 34%, rgba(1, 24, 44, 0.24) 56%, rgba(1, 24, 44, 0) 72%),
		linear-gradient(to top, rgba(1, 24, 44, 0.72) 0%, rgba(1, 24, 44, 0) 34%);
	pointer-events: none;
}

.aeca-sub--services .aeca-sub-hero__stage > .container {
	position: relative;
	z-index: 2;
}

/* Capped so the copy never reaches the field, and measured in px rather than ch because what it has
   to clear is a fraction of the viewport, not a number of characters. */
.aeca-sub--services .aeca-sub-hero__copy {
	max-width: min(100%, 560px);
	padding: clamp(10px, 2vw, 34px) 0;
}

.aeca-sub--services .aeca-sub__eyebrow {
	color: #8fd8f8;
}

.aeca-sub--services .aeca-sub-hero__crumbs {
	color: rgba(255, 255, 255, 0.68);
}

.aeca-sub--services .aeca-sub-hero__crumbs a {
	color: rgba(255, 255, 255, 0.85);
}

.aeca-sub--services .aeca-sub-hero h1 {
	max-width: 16ch;
	margin: 0 0 1.05rem;
	color: var(--sub-white);
	font-size: clamp(2.6rem, 5.4vw, 4.4rem);
	font-weight: 600;
	line-height: 1.02;
}

.aeca-sub--services .aeca-sub-hero__lead {
	max-width: 52ch;
	margin: 0;
	color: rgba(255, 255, 255, 0.84);
	font-size: clamp(1rem, 1.35vw, 1.16rem);
	line-height: 1.68;
}

/* ---- Fact rail ---------------------------------------------------------------------------------
   Across the foot of the hero, divided by vertical hairlines, each cell opening on a short accent
   tick. The tick is the one piece of the retired media frame worth keeping: it was the blue corner
   on the old panel, and it is what stops the rail reading as a plain table of four values. */

.aeca-sub--services .aeca-sub-hero__strip {
	position: relative;
	z-index: 1;
	border-top: 1px solid rgba(255, 255, 255, 0.16);
	background: rgba(1, 18, 34, 0.55);
}

.aeca-sub--services .aeca-sub-facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

.aeca-sub--services .aeca-sub-facts > div {
	position: relative;
	padding: 1.5rem 1.5rem 1.45rem;
	border-right: 1px solid rgba(255, 255, 255, 0.11);
}

.aeca-sub--services .aeca-sub-facts > div::before {
	content: "";
	position: absolute;
	top: 0;
	left: 1.5rem;
	width: 22px;
	height: 2px;
	background: var(--sub-blue-light);
}

.aeca-sub--services .aeca-sub-facts > div:first-child {
	padding-left: 0;
}

.aeca-sub--services .aeca-sub-facts > div:first-child::before {
	left: 0;
}

.aeca-sub--services .aeca-sub-facts > div:last-child {
	border-right: 0;
}

.aeca-sub--services .aeca-sub-facts dt {
	margin: 0 0 0.3rem;
	color: rgba(255, 255, 255, 0.55);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.aeca-sub--services .aeca-sub-facts dd {
	margin: 0;
	color: var(--sub-white);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: clamp(1.05rem, 1.6vw, 1.28rem);
	font-weight: 600;
	line-height: 1.25;
}

/* ---- The designed ground: a contour plot -------------------------------------------------------

   None of the four capability pages has photography, so this is what all four ship. A service here is
   an acquisition or processing method, so the ground is drawn from what those methods produce: rings
   of elevation closing on a survey control mark, the way a contour sheet plots one.

   It has to be told apart from the other two grounds at a glance -- the products wordmark and the
   industries light field -- which is the whole reason there are three of them. Rings read as
   measurement, which is the services claim; nothing else on the site uses a circle at this scale.

   All of it is generated. `repeating-radial-gradient` is what makes the contours cheap: one
   declaration draws every ring, the 1px band is the line and the transparent 26px between bands is
   the interval, so the spacing is a single number to tune. Rings that thin alias badly if the centre
   sits on a subpixel, hence the round percentages. */

.aeca-sub--services .aeca-sub-hero__canvas--contour {
	background:
		radial-gradient(112% 82% at 74% 26%, rgba(22, 173, 238, 0.34) 0%, rgba(22, 173, 238, 0) 58%),
		linear-gradient(146deg, #01345f 0%, #012340 46%, #011a2f 100%);
}

/* The contours. Centred on the control mark below, and faded out at the edges of the field so the
   pattern has no visible last ring -- a hard outer ring would turn the whole thing into a target. */
.aeca-sub--services .aeca-sub-hero__canvas--contour::before {
	content: "";
	position: absolute;
	inset: 0;
	background: repeating-radial-gradient(
		circle at 70% 40%,
		rgba(157, 221, 247, 0.22) 0 1px,
		rgba(157, 221, 247, 0) 1px 27px
	);
	-webkit-mask-image: radial-gradient(78% 74% at 70% 40%, #000 12%, transparent 82%);
	mask-image: radial-gradient(78% 74% at 70% 40%, #000 12%, transparent 82%);
	pointer-events: none;
}

/* A finer grid inside the contours, on the same 46px module the products plate uses. Two families
   sharing a background grid is fine and in fact wanted -- it is the site's plotting paper. What must
   not be shared is the motif drawn on it. */
.aeca-sub--services .aeca-sub-hero__canvas--contour::after {
	content: "";
	position: absolute;
	inset: 0;
	background-image:
		linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
	background-size: 46px 46px;
	pointer-events: none;
}

/* The control mark: a small ringed crosshair at the centre of the contours, in the accent blue. It is
   the one bright thing in the field, so it is where the eye lands after the headline -- which is why
   the contour centre is high and right, diagonally opposite the copy.

   Drawn with a border for the ring and two gradients for the cross, so the whole mark is one element
   and stays centred on its own point at any size. */
.aeca-sub--services .aeca-sub-hero__mark {
	position: absolute;
	top: 40%;
	left: 70%;
	width: 74px;
	height: 74px;
	border: 1px solid rgba(22, 173, 238, 0.75);
	border-radius: 50%;
	background:
		linear-gradient(to right, transparent calc(50% - 0.5px), rgba(22, 173, 238, 0.75) calc(50% - 0.5px) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
		linear-gradient(to bottom, transparent calc(50% - 0.5px), rgba(22, 173, 238, 0.75) calc(50% - 0.5px) calc(50% + 0.5px), transparent calc(50% + 0.5px));
	box-shadow: 0 0 34px rgba(22, 173, 238, 0.32);
	transform: translate(-50%, -50%);
}

/* ---- Section heading: index number, rule, heading left / lead right ---------------------------- */

.aeca-sub--services .aeca-sub-section__head {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
	gap: 1rem clamp(28px, 5vw, 72px);
	align-items: end;
}

.aeca-sub--services .aeca-sub-section__head h2 {
	font-size: clamp(1.95rem, 3.6vw, 3rem);
}

.aeca-sub--services .aeca-sub-section__lead {
	font-size: 1.01rem;
}

.aeca-sub--services .aeca-sub-section__index {
	display: flex;
	gap: 0.85rem;
	align-items: center;
	margin: 0 0 0.75rem;
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.2em;
}

.aeca-sub--services .aeca-sub-section__index::after {
	content: "";
	flex: 0 0 46px;
	height: 1px;
	background: currentColor;
	opacity: 0.6;
}

/* ---- Ledger: numbered rows, hairline separated ------------------------------------------------- */

.aeca-sub--services .aeca-sub-ledger {
	border-top: 1px solid var(--sub-line);
}

.aeca-sub--services .aeca-sub-ledger__row {
	display: grid;
	grid-template-columns: 3.4rem minmax(0, 0.95fr) minmax(0, 1.25fr);
	gap: 0.4rem clamp(18px, 3vw, 44px);
	padding: clamp(20px, 2.6vw, 30px) 0;
	border-bottom: 1px solid var(--sub-line);
}

.aeca-sub--services .aeca-sub-section--navy .aeca-sub-ledger,
.aeca-sub--services .aeca-sub-section--navy .aeca-sub-ledger__row {
	border-color: rgba(255, 255, 255, 0.16);
}

.aeca-sub--services .aeca-sub-ledger__num {
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.92rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	line-height: 1.75;
}

.aeca-sub--services .aeca-sub-ledger__title {
	margin: 0;
	color: var(--sub-blue);
	font-size: clamp(1.08rem, 1.55vw, 1.32rem);
	font-weight: 600;
	line-height: 1.32;
}

.aeca-sub--services .aeca-sub-ledger__body {
	margin: 0;
	color: var(--sub-muted);
	font-size: 1rem;
	line-height: 1.7;
}

/* ---- Cards: top accent bar that fills on hover ------------------------------------------------- */

.aeca-sub--services .aeca-sub-cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(268px, 1fr));
	gap: clamp(16px, 2vw, 26px);
}

.aeca-sub--services .aeca-sub-card {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: clamp(24px, 2.6vw, 34px);
	border: 1px solid var(--sub-line);
	background: var(--sub-white);
	transition: border-color 0.18s ease, transform 0.18s ease;
}

.aeca-sub--services .aeca-sub-card::before {
	content: "";
	position: absolute;
	top: -1px;
	left: -1px;
	width: 54px;
	height: 3px;
	background: var(--sub-accent);
	transition: width 0.22s ease;
}

.aeca-sub--services .aeca-sub-card:hover {
	border-color: #b9d2e6;
	transform: translateY(-3px);
}

.aeca-sub--services .aeca-sub-card:hover::before {
	width: calc(100% + 2px);
}

.aeca-sub--services .aeca-sub-card h3 {
	margin: 0 0 0.7rem;
	color: var(--sub-blue);
	font-size: clamp(1.14rem, 1.7vw, 1.4rem);
	font-weight: 600;
	line-height: 1.26;
}

.aeca-sub--services .aeca-sub-card p {
	margin: 0;
	color: var(--sub-muted);
	font-size: 0.98rem;
	line-height: 1.66;
}

.aeca-sub--services .aeca-sub-card__num {
	margin: 0 0 0.9rem;
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.18em;
}

/* A solo split is the full 1180px container, which is a fine measure for a two-column body and a
   punishing one for a paragraph -- roughly 150 characters a line on the MacBook this is reviewed
   full screen on. Capped for Solutions only: no other family runs prose at this width today, so
   scoping it here moves nothing that is already published. */
.aeca-sub--services .aeca-sub-split--solo .aeca-sub-split__body > p {
	max-width: 68ch;
}

/* ---- Band: the card's accent stub, without the card's hover ------------------------------------ */

.aeca-sub--services .aeca-sub-band::before {
	content: "";
	position: absolute;
	top: -1px;
	left: -1px;
	width: 54px;
	height: 3px;
	background: var(--sub-accent);
}

/* ---- Stories: hairline card with a blue spine -------------------------------------------------- */

.aeca-sub--services .aeca-sub-story {
	border: 1px solid var(--sub-line);
	border-left: 3px solid var(--sub-blue);
}

/* ---- Siblings: white cells, blue on hover ------------------------------------------------------ */

.aeca-sub--services .aeca-sub-sibling {
	background: var(--sub-white);
	box-shadow: 0 0 0 1px var(--sub-line);
	color: var(--sub-blue);
}

.aeca-sub--services .aeca-sub-sibling:hover,
.aeca-sub--services .aeca-sub-sibling:focus {
	background: var(--sub-blue);
	color: var(--sub-white);
}


/* ====================================================================================================
   INDUSTRIES
   ----------------------------------------------------------------------------------------------------
   Light and editorial, and banded. The page opens on white with the copy centred in a narrow column,
   then a full-bleed photograph runs the width of the viewport with the headline facts sitting on it.
   Below that, sections alternate white against full navy, so the page reads as a sequence of bands
   rather than a document. Headings are centred and unnumbered; the deep brand blue is the accent.
   ==================================================================================================== */

.aeca-sub--industries {
	--sub-accent: var(--sub-blue);
	--sub-gap: clamp(62px, 8vw, 118px);
}

/* ---- Hero -------------------------------------------------------------------------------------- */

.aeca-sub--industries .aeca-sub-hero {
	padding: clamp(48px, 6vw, 86px) 0 0;
	background: var(--sub-white);
}

.aeca-sub--industries .aeca-sub-hero__intro {
	max-width: 780px;
	margin: 0 auto;
	padding-bottom: clamp(34px, 4.5vw, 58px);
	text-align: center;
}

.aeca-sub--industries .aeca-sub-hero__crumbs {
	color: var(--sub-muted);
}

.aeca-sub--industries .aeca-sub-hero__crumbs ol {
	justify-content: center;
}

.aeca-sub--industries .aeca-sub-hero__crumbs a {
	color: var(--sub-blue);
}

.aeca-sub--industries .aeca-sub-hero h1 {
	margin: 0 0 1.1rem;
	color: var(--sub-blue);
	font-size: clamp(2.9rem, 6.4vw, 5.2rem);
	font-weight: 600;
	line-height: 0.98;
}

/* The rule under the headline is the industries signature: it appears here, under every section
   heading, and nowhere in the other two families. */
.aeca-sub--industries .aeca-sub-hero h1::after {
	content: "";
	display: block;
	width: 72px;
	height: 4px;
	margin: 1.4rem auto 0;
	background: var(--sub-accent);
}

.aeca-sub--industries .aeca-sub-hero__lead {
	max-width: 62ch;
	margin: 0 auto;
	color: var(--sub-muted);
	font-size: clamp(1.03rem, 1.5vw, 1.22rem);
	line-height: 1.7;
}

/* ---- The band: rebuilt 2026-08-13 ---------------------------------------------------------------

   Full-bleed, and breaking out of the container deliberately: this is the one element on any of the
   20 detail pages that touches both edges of the viewport, and it is what makes an industry page
   recognisable from across the room. That much is unchanged.

   What changed is what is in it. The band used to be the shared grey placeholder plate cropped to
   21:9, with its "PLACEHOLDER: ..." label bleeding off the left edge of the screen and the fact strip
   floating on the grey. All five industry pages shipped that. It is now a designed light field, or a
   photograph on any page that later gets one, with the facts seated on its foot either way.

   The height is a fixed band rather than a ratio. A ratio was right when the content was a 21:9
   placeholder; a drawn ground has no intrinsic shape, and pinning the height means everything drawn
   on it can be positioned in percentages and stay put across every width.

   The facts are laid out by the flex column rather than pinned to the foot with `position: absolute`,
   which is what the old band did. Absolute was fine while the strip was one line of four cells; it
   stops being fine the moment the strip is two rows deep on a narrow screen, because an absolute
   strip overflows a fixed band instead of pushing it taller. Flexed, the band grows to hold whatever
   the strip needs and the drawn ground grows with it, at every width, with no breakpoint. */
.aeca-sub--industries .aeca-sub-hero__band {
	position: relative;
	isolation: isolate;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	overflow: hidden;
	min-height: clamp(280px, 26vw, 400px);
}

.aeca-sub--industries .aeca-sub-hero__band > .container {
	position: relative;
	z-index: 1;
}

/* ---- The designed ground: a lit field -----------------------------------------------------------

   An industry page is about an operating environment, so the ground is that environment read at its
   most abstract: open air, lit from the upper left, with a plotting grid across it. Read it against
   the other two grounds -- the services contour plot and the products wordmark -- and the three have
   nothing in common but the palette, which is the 2026-08-10 request holding.

   THE HILLS ARE GONE. Until 2026-08-14 this ground carried two ridge lines in the lower half, drawn
   as rows of overlapping ellipses. They were removed at the user's request and nothing took their
   place, which leaves the field and the grid doing the whole job. Two consequences, both handled
   below: the grid no longer has to stop short of a silhouette, and the foot of the ramp is now what
   the fact strip sits on.

   This family is the light one, and it stays light: the field runs from a near-white sky down to a
   deep brand blue, not down to navy. The facts are still the only dark thing in the band. */

.aeca-sub--industries .aeca-sub-hero__canvas--field {
	background:
		radial-gradient(78% 96% at 22% 4%, rgba(255, 255, 255, 0.92) 0%, rgba(255, 255, 255, 0) 62%),
		linear-gradient(to bottom, #e8f2fa 0%, #b9d6ee 32%, #6ea6d6 64%, #235f9b 100%);
}

/* Hairline grid. Blue on light here, where the two dark families draw it white on navy -- same
   plotting paper, inverted.

   The mask used to fade out by 64% so the grid never scratched across the near ridge. With the ridges
   gone there is nothing to protect, and stopping that high left the bottom third as bare gradient, so
   it now runs to 88% -- far enough that the grid reaches the fact strip and dies under it rather than
   ending in mid-air. */
.aeca-sub--industries .aeca-sub-hero__canvas--field::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image:
		linear-gradient(to right, rgba(2, 77, 161, 0.09) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(2, 77, 161, 0.09) 1px, transparent 1px);
	background-size: 54px 54px;
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, 0.55) 58%, transparent 88%);
	mask-image: linear-gradient(to bottom, #000 0%, rgba(0, 0, 0, 0.55) 58%, transparent 88%);
	pointer-events: none;
}

/* The two ridge layers stood here until 2026-08-14. Each was a row of wide overlapping ellipses over
   a flat base, sized `rx` in `vw` and `ry` in `%` so the silhouette held its proportions at any
   width. They are gone at the user's request, along with the mobile block that widened their hills.
   Recovering them means restoring both spans in aeca_subpage_hero_ground_industries() as well. */

/* A photograph needs the foot of the band darkened so the fact strip has something to sit on. The
   drawn ground does not: with the ridges gone the field's own ramp finishes deep enough at the foot,
   which is why its bottom stop was taken down to #235f9b when they came out. */
.aeca-sub--industries .aeca-sub-hero--photo .aeca-sub-hero__canvas::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(to top, rgba(1, 26, 48, 0.55) 0%, rgba(1, 26, 48, 0) 46%);
	pointer-events: none;
}

/* Facts as a translucent strip sitting on the foot of the band. */
.aeca-sub--industries .aeca-sub-facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
	background: rgba(1, 35, 64, 0.88);
	color: var(--sub-white);
}

.aeca-sub--industries .aeca-sub-facts > div {
	padding: 1.15rem 1.4rem 1.25rem;
	border-right: 1px solid rgba(255, 255, 255, 0.16);
	text-align: center;
}

.aeca-sub--industries .aeca-sub-facts > div:last-child {
	border-right: 0;
}

.aeca-sub--industries .aeca-sub-facts dt {
	margin: 0 0 0.3rem;
	color: rgba(255, 255, 255, 0.6);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.66rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
}

.aeca-sub--industries .aeca-sub-facts dd {
	margin: 0;
	color: var(--sub-white);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: clamp(0.98rem, 1.4vw, 1.16rem);
	font-weight: 600;
	line-height: 1.25;
}

/* ---- Section heading: centred, ruled, unnumbered ----------------------------------------------- */

.aeca-sub--industries .aeca-sub-section__head {
	max-width: 760px;
	margin-right: auto;
	margin-left: auto;
	text-align: center;
}

/* The counter belongs to the Services design; here the sections are bands, not steps. */
.aeca-sub--industries .aeca-sub-section__index {
	display: none;
}

.aeca-sub--industries .aeca-sub-section__head h2 {
	font-size: clamp(2.1rem, 4.2vw, 3.5rem);
}

.aeca-sub--industries .aeca-sub-section__head h2::after {
	content: "";
	display: block;
	width: 56px;
	height: 3px;
	margin: 1.1rem auto 1.35rem;
	background: var(--sub-accent);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-section__head h2::after {
	background: var(--sub-blue-light);
}

.aeca-sub--industries .aeca-sub-section__lead {
	font-size: 1.06rem;
}

/* ---- Ledger: stacked panels with a ghosted number ---------------------------------------------- */

.aeca-sub--industries .aeca-sub-ledger {
	display: grid;
	gap: clamp(14px, 1.8vw, 22px);
}

.aeca-sub--industries .aeca-sub-ledger__row {
	position: relative;
	overflow: hidden;
	padding: clamp(26px, 3vw, 40px) clamp(24px, 3vw, 44px);
	background: var(--sub-white);
	box-shadow: 0 0 0 1px var(--sub-line);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-ledger__row {
	background: rgba(255, 255, 255, 0.05);
	box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}

/* The number is a watermark rather than a column: oversized, low contrast, behind the copy. */
.aeca-sub--industries .aeca-sub-ledger__num {
	position: absolute;
	top: -0.35em;
	right: 0.3em;
	margin: 0;
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: clamp(4.5rem, 9vw, 8rem);
	font-weight: 700;
	line-height: 1;
	opacity: 0.08;
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-ledger__num {
	color: var(--sub-white);
	opacity: 0.12;
}

.aeca-sub--industries .aeca-sub-ledger__title {
	position: relative;
	margin: 0 0 0.7rem;
	color: var(--sub-blue);
	font-size: clamp(1.2rem, 2vw, 1.6rem);
	font-weight: 600;
	line-height: 1.24;
}

.aeca-sub--industries .aeca-sub-ledger__body {
	position: relative;
	max-width: 82ch;
	margin: 0;
	color: var(--sub-muted);
	font-size: 1.02rem;
	line-height: 1.72;
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-ledger__title {
	color: var(--sub-white);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-ledger__body {
	color: rgba(255, 255, 255, 0.78);
}

/* ---- Cards: horizontal rows led by a filled number square -------------------------------------- */

.aeca-sub--industries .aeca-sub-cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
	gap: clamp(18px, 2.2vw, 30px);
}

.aeca-sub--industries .aeca-sub-card {
	display: flex;
	flex-direction: column;
	padding: clamp(26px, 2.8vw, 38px);
	background: var(--sub-white);
	box-shadow: 0 0 0 1px var(--sub-line);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-card {
	background: rgba(255, 255, 255, 0.05);
	box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}

/* The square cap. Sits above the heading, filled with the accent, and is the industries equivalent
   of the Services top bar -- same job, deliberately not the same shape. */
.aeca-sub--industries .aeca-sub-card::before {
	content: "";
	display: block;
	width: 40px;
	height: 40px;
	margin-bottom: 1.35rem;
	background: var(--sub-accent);
	clip-path: polygon(0 0, 100% 0, 100% 72%, 72% 100%, 0 100%);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-card::before {
	background: var(--sub-blue-light);
}

.aeca-sub--industries .aeca-sub-card h3 {
	margin: 0 0 0.75rem;
	color: var(--sub-blue);
	font-size: clamp(1.2rem, 1.8vw, 1.48rem);
	font-weight: 600;
	line-height: 1.24;
}

.aeca-sub--industries .aeca-sub-card p {
	margin: 0;
	color: var(--sub-muted);
	font-size: 1rem;
	line-height: 1.68;
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-card h3 {
	color: var(--sub-white);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-card p {
	color: rgba(255, 255, 255, 0.78);
}

.aeca-sub--industries .aeca-sub-card__num {
	margin: 0 0 0.5rem;
	color: var(--sub-accent);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.18em;
}

/* ---- Stories: banded panel, no spine ----------------------------------------------------------- */

.aeca-sub--industries .aeca-sub-story {
	box-shadow: 0 0 0 1px var(--sub-line);
}

.aeca-sub--industries .aeca-sub-story h3::after {
	content: "";
	display: block;
	width: 44px;
	height: 3px;
	margin-top: 0.9rem;
	background: var(--sub-accent);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-story {
	background: rgba(255, 255, 255, 0.05);
	box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-story h3 {
	color: var(--sub-white);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-story dd,
.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-story__meta {
	color: rgba(255, 255, 255, 0.78);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-story dt {
	color: var(--sub-blue-light);
}

/* ---- Siblings: solid navy cells that invert ---------------------------------------------------- */

.aeca-sub--industries .aeca-sub-siblings {
	gap: 2px;
}

.aeca-sub--industries .aeca-sub-sibling {
	background: var(--sub-blue);
	color: var(--sub-white);
	text-align: center;
	align-items: center;
}

.aeca-sub--industries .aeca-sub-sibling:hover,
.aeca-sub--industries .aeca-sub-sibling:focus {
	background: var(--sub-navy);
	color: var(--sub-white);
}


/* ====================================================================================================
   PRODUCTS
   ----------------------------------------------------------------------------------------------------
   A datasheet. Light throughout, on a blueprint ground rather than a photograph; the platform sits on
   a plate to the right of the copy; headline figures run as a bordered strip beneath rather than as a
   rail. Headings carry a monospaced-feeling kicker and a hairline, list rows read as label/value
   pairs, and the red brand hairline marks the top of every card -- the only place red appears on any
   of the 22 pages, and the fastest way to tell a product page from the other two.
   ==================================================================================================== */

.aeca-sub--products {
	--sub-accent: var(--sub-blue);
	--sub-gap: clamp(50px, 6.5vw, 92px);
}

/* ---- Hero: one cinematic field -----------------------------------------------------------------

   Redesigned 2026-08-13. What stood here was three generations of hero stacked on each other -- a
   blueprint plate, then a dark full-bleed overlay that overrode it, then a split panel that overrode
   that -- around 350 lines to draw one hero, with the last two disagreeing about whether the ground
   was light or dark. This block is the single replacement for all three. If the hero has to change
   again, edit this; do not layer a fourth generation on top.

   The image is the hero. It fills the stage edge to edge, a two-pass scrim carries the copy in the
   bottom-left quarter, and the headline figures sit beneath it as a light spec strip -- the one part
   of the old datasheet reading worth keeping, and still what separates this from the Services hero
   (which frames its media) and the Industries hero (which bands it).

   `--photo` and `--graphic` are this same hero on two grounds. See the fallback note further down. */

.aeca-sub--products .aeca-sub-hero {
	position: relative;
	isolation: isolate;
	border-bottom: 1px solid var(--sub-line);
	background: var(--sub-navy);
	color: var(--sub-white);
}

/* Copy sits at the foot of the frame. That keeps the top clear, which is where an airframe, a wing
   or a horizon lands in most of these photographs; the large top padding is what reserves it.

   THE HEIGHT IS AN ASPECT RATIO, NOT A NUMBER. The stage is full-bleed, so its shape is
   viewport-width over this height, and that shape decides how much of the photograph survives the
   `cover` crop. At 46vw the frame holds ~2.15:1 at every desktop width, which shows about 70% of a
   3:2 photograph's height -- enough for a subject spread from top to bottom of the frame, such as
   the DJI dock with the aircraft above it (they span ~65% between them).

   This used to cap at 640px. The cap is what broke it: past ~1390px the height stopped growing
   while the width kept going, the frame stretched towards 3:1, and the visible band fell to half the
   photograph, which cropped the aircraft off the top on any wide screen. The cap now sits high
   enough to stay out of the way until ~1700px. Raise the ratio here and every product photograph
   loses height at once -- check DJI first, it is the tightest of the three. */
.aeca-sub--products .aeca-sub-hero__stage {
	position: relative;
	display: flex;
	align-items: flex-end;
	overflow: hidden;
	min-height: clamp(440px, 46vw, 780px);
	padding: clamp(96px, 12vw, 170px) 0 clamp(38px, 4.6vw, 72px);
}

/* The canvas box itself is shared -- see the SHARED FOUNDATION block near the top of this file. Only
   what fills it and what is laid over it belong to this family.

   Two scrim passes, not one. The horizontal pass protects the copy column and lets the right of the
   frame stay near full strength; the vertical pass seats the image against the spec strip so the
   join reads as a fade and not as a cut. Both are needed -- a single diagonal muddies the middle of
   the frame, which is exactly where the product usually is.

   Both passes are tuned around where the product actually sits, roughly 70% across and low in the
   frame. The first version held 0.44 at 64% and faded the bottom over a full 48%, and the two
   compounded straight over the subject: the DJI dock came out under about 0.7 combined, which left
   a third of the photograph showing and read as a washed-out grey block. The horizontal pass now
   drops away by 74% and the vertical fade is less than half as deep, which puts the subject under
   ~0.38 while the copy column stays above 0.8. Move either and check the copy contrast as well as
   the product -- these two numbers trade directly against each other. */
.aeca-sub--products .aeca-sub-hero__canvas::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		linear-gradient(90deg, rgba(1, 20, 38, 0.94) 0%, rgba(1, 24, 44, 0.88) 30%, rgba(1, 28, 52, 0.52) 52%, rgba(1, 32, 58, 0.16) 74%, rgba(1, 35, 64, 0.06) 100%),
		linear-gradient(to top, rgba(1, 18, 34, 0.62) 0%, rgba(1, 18, 34, 0) 28%);
	pointer-events: none;
}

.aeca-sub--products .aeca-sub-hero__stage > .container {
	position: relative;
	z-index: 1;
}

.aeca-sub--products .aeca-sub-hero__copy {
	max-width: min(100%, 640px);
}

.aeca-sub--products .aeca-sub-hero__crumbs {
	color: rgba(255, 255, 255, 0.66);
}

.aeca-sub--products .aeca-sub-hero__crumbs a,
.aeca-sub--products .aeca-sub__eyebrow {
	color: #9dddf7;
}

.aeca-sub--products .aeca-sub-hero h1 {
	max-width: 13ch;
	margin: 0 0 1.15rem;
	color: var(--sub-white);
	font-size: clamp(3rem, 6.4vw, 5.6rem);
	font-weight: 600;
	letter-spacing: -0.045em;
	line-height: 0.97;
}

/* The red hairline. Red is absent from the Services and Industries pages entirely, and on a product
   page it marks the top of every card. Carrying it into the hero is the quickest signal of which of
   the three families a visitor has landed in -- which is the whole point of three hero designs. */
.aeca-sub--products .aeca-sub-hero h1::after {
	content: "";
	display: block;
	width: 58px;
	height: 3px;
	margin-top: clamp(1rem, 1.6vw, 1.4rem);
	background: var(--sub-red);
}

.aeca-sub--products .aeca-sub-hero__lead {
	max-width: 46ch;
	margin: 0;
	color: rgba(255, 255, 255, 0.84);
	font-size: clamp(1rem, 1.35vw, 1.15rem);
	line-height: 1.72;
}

/* ---- The product, on `--plate` pages ------------------------------------------------------------

   A manufacturer cut-out over the same wordmark ground a `--graphic` page shows. The ground stays
   visible around and behind it, which is what keeps a plate page and a bare page reading as one
   design.

   NO TILE. The first version sat the cut-out on a white tile, on the assumption that the supplied
   files were a mix of transparent and flattened and that only a white ground would render both the
   same. The assumption was never checked and it was wrong: three of the four carry real alpha, and
   the fourth is flattened onto #f1f4f9 and is used in a light section where it disappears into the
   tint anyway. So the tile solved a problem that did not exist, and it cost a bright white slab
   across a hero whose whole design is a dark cinematic field. Check the alpha before reintroducing
   anything like it.

   Positioned against the container, not the stage. That aligns the product to the same 1180px grid
   the copy sits on rather than to the viewport edge -- a cut-out has a definite size and looks wrong
   drifting out towards the screen edge the way a photograph can -- and it means it only has to drop
   `position` to fall back into the flow beneath the copy on a narrow screen. */

.aeca-sub--products .aeca-sub-hero__product {
	position: absolute;
	z-index: 1;
	right: 0;
	bottom: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: min(46%, 520px);
	height: clamp(210px, 25vw, 390px);
}

/* A pool of light behind the object, not a panel around it. Several of these products are matte
   black, and a black body on #012340 reads as a dark smudge with no edge; the glow is what gives it
   one. Sized to the box and faded to nothing well inside it, so there is no rim -- the moment this
   has a visible boundary it has become the tile again. */
.aeca-sub--products .aeca-sub-hero__product::before {
	content: "";
	position: absolute;
	inset: -14% -10%;
	background: radial-gradient(closest-side, rgba(157, 221, 247, 0.22) 0%, rgba(157, 221, 247, 0.09) 46%, rgba(157, 221, 247, 0) 74%);
	pointer-events: none;
}

/* `drop-shadow` and not `box-shadow`: it follows the alpha silhouette, so the shadow is cast by the
   airframe or the lens barrel rather than by the rectangle the file happens to occupy. */
.aeca-sub--products .aeca-sub-hero__product img {
	position: relative;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
	filter: drop-shadow(0 26px 34px rgba(0, 6, 14, 0.62));
}

/* A trimmed render. The height stays put and the WIDTH follows the ratio, which is the opposite of
   how the uncropped box is sized -- if the width led, a narrow crop would make the box taller and
   push the product out of the top of the stage. Holding the height means a page can crop as hard as
   it likes and the hero keeps its shape. */
.aeca-sub--products .aeca-sub-hero__product--crop {
	width: auto;
	max-width: min(46%, 520px);
	aspect-ratio: var(--plate-ratio, 4 / 3);
}

.aeca-sub--products .aeca-sub-hero__product--crop img {
	object-fit: cover;
	object-position: var(--plate-position, 50% 50%);
}

/* The ghost goes. It lives bottom-right, which is exactly where the tile now sits, so on a plate page
   it showed as a few letter fragments poking out around the tile edges -- which reads as a mistake
   rather than as a watermark. The rest of the ground stays: gradient, light source and blueprint
   rule are what make the tile look placed on something rather than pasted on a colour.

   Nothing is lost by dropping it. The ghost exists to give a bare page a subject; a plate page has
   one, and it is the product itself. */
.aeca-sub--products .aeca-sub-hero--plate .aeca-sub-hero__ghost {
	display: none;
}

/* The copy has to clear the tile. 42% of the container plus the gap leaves a little under 600px, and
   the h1 is the part that would collide first because it is the widest line. */
.aeca-sub--products .aeca-sub-hero--plate .aeca-sub-hero__copy {
	max-width: min(100%, 560px);
}

/* A plate page needs none of the top padding a photograph page reserves. That padding exists to keep
   the top of the frame clear for an airframe or a horizon; there is no frame here, only a tile, and
   left alone it pushed the hero past 600px of mostly empty ground. */
.aeca-sub--products .aeca-sub-hero--plate .aeca-sub-hero__stage {
	min-height: clamp(400px, 34vw, 560px);
	padding: clamp(56px, 6vw, 92px) 0 clamp(38px, 4.6vw, 72px);
}

/* ---- Spec strip --------------------------------------------------------------------------------
   Under the image, not over it. These are four short label/value pairs that have to be readable at a
   glance, and that is worth more than another 60px of photograph. */

.aeca-sub--products .aeca-sub-hero__strip {
	position: relative;
	z-index: 1;
	padding: clamp(20px, 2.6vw, 32px) 0 clamp(22px, 2.8vw, 34px);
	background: var(--sub-tint);
}

/* ---- The designed ground: the product name -----------------------------------------------------

   Eight of the eleven products have no photography yet. The hero this replaced dropped a grey
   placeholder box and a visible "Placeholder: ..." caption where the product should be, so two
   thirds of the range looked unbuilt. Those pages get a built panel instead: blueprint rule, one
   light source from the top right, and the product name oversize and outlined behind the copy.

   It is a finished state, not a holding state -- nothing on the page announces a missing image. When
   a photograph arrives, add `hero_image` to that template and the page becomes `--photo` with no
   other edit. The brief for the photograph survives as an HTML comment in the meantime.

   This is the ground the other two families' were later built against: services draws a contour plot
   and industries a terrain profile, and none of the three may borrow another's motif. */

.aeca-sub--products .aeca-sub-hero__canvas--wordmark {
	background:
		radial-gradient(115% 85% at 84% 12%, rgba(22, 173, 238, 0.32) 0%, rgba(22, 173, 238, 0) 56%),
		linear-gradient(142deg, #012c52 0%, #012340 44%, #01192e 100%);
}

/* The blueprint rule is the one piece of the retired plate hero worth carrying forward: it is what
   stops the panel reading as a flat colour block. White on navy here, where the old hero drew it
   blue on tint. */
.aeca-sub--products .aeca-sub-hero__canvas--wordmark::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image:
		linear-gradient(to right, rgba(255, 255, 255, 0.055) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
	background-size: 46px 46px;
	pointer-events: none;
}

/* The product name, bled off the bottom right. Outlined rather than filled, because a filled word at
   this size competes with the h1 for the same reading while an outline stays a ground. It repeats
   the h1 word for word, which is why the panel around it is aria-hidden. */
.aeca-sub--products .aeca-sub-hero__ghost {
	position: absolute;
	right: clamp(16px, 4vw, 64px);
	bottom: -0.12em;
	max-width: 66%;
	color: transparent;
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: clamp(4.5rem, 13vw, 13rem);
	font-weight: 700;
	letter-spacing: -0.05em;
	line-height: 0.84;
	text-align: right;
	-webkit-text-stroke: 1px rgba(255, 255, 255, 0.17);
}

/* Headline figures as a bordered strip, closer to the top block of a spec sheet than to a banner. */
.aeca-sub--products .aeca-sub-facts {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
	gap: 1px;
	background: var(--sub-line);
	border: 1px solid var(--sub-line);
}

.aeca-sub--products .aeca-sub-facts > div {
	padding: 1rem 1.25rem 1.1rem;
	background: var(--sub-white);
}

.aeca-sub--products .aeca-sub-facts dt {
	margin: 0 0 0.25rem;
	color: var(--sub-muted);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.65rem;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
}

.aeca-sub--products .aeca-sub-facts dd {
	margin: 0;
	color: var(--sub-blue);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: clamp(1rem, 1.4vw, 1.2rem);
	font-weight: 600;
	line-height: 1.25;
}

/* ---- Section heading: kicker, heading, full hairline -------------------------------------------- */

.aeca-sub--products .aeca-sub-section__head {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
	gap: 0.6rem clamp(28px, 5vw, 64px);
	align-items: end;
	padding-bottom: 1.15rem;
	border-bottom: 2px solid var(--sub-blue);
}

.aeca-sub--products .aeca-sub-section__head h2 {
	font-size: clamp(1.75rem, 3.1vw, 2.5rem);
}

.aeca-sub--products .aeca-sub-section__lead {
	font-size: 0.98rem;
}

/* The index reads as a plate number on a drawing sheet. */
.aeca-sub--products .aeca-sub-section__index {
	display: inline-block;
	margin: 0 0 0.6rem;
	padding: 0.2rem 0.5rem;
	border: 1px solid var(--sub-line);
	color: var(--sub-muted);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.22em;
}

/* ---- Ledger: compact label/value rows ----------------------------------------------------------- */

.aeca-sub--products .aeca-sub-ledger {
	border-top: 1px solid var(--sub-line);
}

.aeca-sub--products .aeca-sub-ledger__row {
	display: grid;
	grid-template-columns: 2.6rem minmax(0, 0.8fr) minmax(0, 1.4fr);
	gap: 0.3rem clamp(16px, 2.5vw, 36px);
	padding: 1.05rem 0;
	border-bottom: 1px solid var(--sub-line);
}

.aeca-sub--products .aeca-sub-ledger__num {
	color: var(--sub-muted);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	line-height: 1.9;
}

.aeca-sub--products .aeca-sub-ledger__title {
	margin: 0;
	color: var(--sub-blue);
	font-size: 1.06rem;
	font-weight: 600;
	line-height: 1.4;
}

.aeca-sub--products .aeca-sub-ledger__body {
	margin: 0;
	color: var(--sub-muted);
	font-size: 0.98rem;
	line-height: 1.66;
}

/* ---- Cards: bordered tiles with a red hairline cap ---------------------------------------------- */

.aeca-sub--products .aeca-sub-cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(258px, 1fr));
	gap: 1px;
	background: var(--sub-line);
	border: 1px solid var(--sub-line);
}

.aeca-sub--products .aeca-sub-card {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: clamp(24px, 2.6vw, 34px);
	background: var(--sub-white);
	transition: background-color 0.18s ease;
}

.aeca-sub--products .aeca-sub-card::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 2px;
	background: var(--sub-red);
	opacity: 0;
	transition: opacity 0.18s ease;
}

.aeca-sub--products .aeca-sub-card:hover {
	background: var(--sub-tint);
}

.aeca-sub--products .aeca-sub-card:hover::before {
	opacity: 1;
}

.aeca-sub--products .aeca-sub-card h3 {
	margin: 0 0 0.65rem;
	color: var(--sub-blue);
	font-size: clamp(1.08rem, 1.6vw, 1.3rem);
	font-weight: 600;
	line-height: 1.28;
}

.aeca-sub--products .aeca-sub-card p {
	margin: 0;
	color: var(--sub-muted);
	font-size: 0.96rem;
	line-height: 1.64;
}

.aeca-sub--products .aeca-sub-card__num {
	margin: 0 0 0.75rem;
	color: var(--sub-muted);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.22em;
}

/* On the one navy section a product page uses (the "why choose" strip), the tiles invert. */
.aeca-sub--products .aeca-sub-section--navy .aeca-sub-cards {
	background: rgba(255, 255, 255, 0.18);
	border-color: rgba(255, 255, 255, 0.18);
}

.aeca-sub--products .aeca-sub-section--navy .aeca-sub-card {
	background: var(--sub-navy-2);
}

.aeca-sub--products .aeca-sub-section--navy .aeca-sub-card:hover {
	background: #023a6b;
}

.aeca-sub--products .aeca-sub-section--navy .aeca-sub-card h3 {
	color: var(--sub-white);
}

.aeca-sub--products .aeca-sub-section--navy .aeca-sub-card p {
	color: rgba(255, 255, 255, 0.78);
}

.aeca-sub--products .aeca-sub-section--navy .aeca-sub-card__num {
	color: var(--sub-blue-light);
}

.aeca-sub--products .aeca-sub-section--navy .aeca-sub-section__head {
	border-bottom-color: var(--sub-blue-light);
}

/* ---- Stories: plain bordered sheet -------------------------------------------------------------- */

.aeca-sub--products .aeca-sub-story {
	border: 1px solid var(--sub-line);
	border-top: 2px solid var(--sub-blue);
}

/* ---- Siblings: bordered tiles, tinted on hover -------------------------------------------------- */

.aeca-sub--products .aeca-sub-sibling {
	background: var(--sub-white);
	box-shadow: 0 0 0 1px var(--sub-line);
	color: var(--sub-blue);
}

.aeca-sub--products .aeca-sub-sibling:hover,
.aeca-sub--products .aeca-sub-sibling:focus {
	background: var(--sub-tint);
	color: var(--sub-blue);
}


/* ====================================================================================================
   BREAKPOINTS
   Every multi-column grid above collapses here. Ordered widest first so the cascade reads top-down.

   A NOTE ON THE `.aeca-sub` PREFIXES BELOW
   A media query adds no specificity. Anything a family block set with two classes
   (`.aeca-sub--products .aeca-sub-hero__copy`) therefore beats a one-class rule down here, and the
   Services and Products heroes once did not collapse at all: at 390px the copy column was 175px
   wide and the plate beside it 155px, so a product name ran three words deep and the photograph was
   a thumbnail. Every rule that has to overrule a family block is written with the same class count
   plus source order. Keep the prefix if you add one.
   ==================================================================================================== */

@media (max-width: 991.98px) {
	.aeca-sub .aeca-sub-split,
	.aeca-sub .aeca-sub-story {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Four across is a 220px column on a tablet, which is narrower than the padding-to-padding space
	   a card needs. Three still holds at ~305px, so only the four-card grids step down. */
	.aeca-sub .aeca-sub-cards.aeca-sub-cards--cols-4 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* With one column the figure belongs after the copy on every split, flipped or not. */
	.aeca-sub-split--flip .aeca-sub-split__media {
		order: 0;
	}

	/* The solo split's tick list follows the same rule as the split it sits in: two across is a tablet
	   and desktop layout, and below that each item takes the full measure. The row gap goes back to
	   the `li + li` spacing, which is now doing the work again. */
	.aeca-sub .aeca-sub-split--solo .aeca-sub-checks {
		grid-template-columns: minmax(0, 1fr);
		row-gap: 0.95rem;
	}

	.aeca-sub--services .aeca-sub-section__head,
	.aeca-sub--products .aeca-sub-section__head {
		grid-template-columns: minmax(0, 1fr);
		align-items: start;
	}

	.aeca-sub--services .aeca-sub-facts > div:first-child {
		padding-left: 1.5rem;
	}

	.aeca-sub--services .aeca-sub-facts > div:first-child::before {
		left: 1.5rem;
	}

	/* ---- Services hero ---------------------------------------------------------------------------

	   The copy stops being a left-hand column and spans the width, so a field pinned to the right
	   half would sit straight under the lead. The field takes the whole stage instead and a scrim
	   goes over it, which is the same move the products hero makes at this width and for the same
	   reason -- see the long note under the products rules below.

	   The scrim is written for both states here, not just `--photo`. A drawn ground under full-width
	   copy needs it as much as a photograph does: the contour rings are pale blue hairlines and body
	   text crossing them is unreadable without something in between. */
	.aeca-sub--services .aeca-sub-hero__field {
		inset: 0;
		width: auto;
		-webkit-mask-image: none;
		mask-image: none;
	}

	.aeca-sub--services .aeca-sub-hero__field::after {
		content: "";
		position: absolute;
		inset: 0;
		background: linear-gradient(to right, rgba(1, 20, 38, 0.9) 0%, rgba(1, 24, 44, 0.78) 54%, rgba(1, 28, 52, 0.58) 100%);
		pointer-events: none;
	}

	/* A photograph needs more than the drawn ground does, and bottom-weighted rather than
	   left-weighted, so the top of the frame -- where the subject usually is -- stays closest to
	   clear. */
	.aeca-sub--services .aeca-sub-hero--photo .aeca-sub-hero__field::after {
		background:
			linear-gradient(90deg, rgba(1, 20, 38, 0.66) 0%, rgba(1, 26, 48, 0.44) 60%, rgba(1, 30, 55, 0.3) 100%),
			linear-gradient(to top, rgba(1, 18, 34, 0.94) 0%, rgba(1, 18, 34, 0.8) 42%, rgba(1, 18, 34, 0.3) 74%, rgba(1, 18, 34, 0) 100%);
	}

	/* The control mark moves up and out to the corner, off the block of copy that now runs the full
	   width, and drops a size with it. The rings stay where they are: they are faint enough under the
	   scrim to pass behind text, and moving their centre without moving the mark would separate the
	   two things that have to agree. */
	.aeca-sub--services .aeca-sub-hero__mark {
		top: 26%;
		left: 82%;
		width: 54px;
		height: 54px;
	}

	/* The products hero keeps its full-bleed image -- it is the design -- but the copy stops being a
	   left-hand column and spans the width, so a left-to-right scrim no longer protects it.

	   The scrim turns bottom-weighted instead of directional. Simply strengthening the horizontal
	   pass was the obvious move and the wrong one: at 390px it took roughly 0.9 alpha across the
	   whole frame to carry the copy, which left a navy rectangle with a photograph theoretically
	   behind it. Weighting it bottom-to-top puts the copy on a near-solid base and leaves the top of
	   the frame -- where the product is -- close to clear, which is the only way the image survives
	   a narrow screen at all. */
	.aeca-sub--products .aeca-sub-hero__stage {
		min-height: clamp(400px, 58vw, 520px);
		padding: clamp(70px, 13vw, 120px) 0 clamp(30px, 4.5vw, 48px);
	}

	.aeca-sub--products .aeca-sub-hero__copy {
		max-width: none;
	}

	.aeca-sub--products .aeca-sub-hero__canvas::after {
		background:
			linear-gradient(90deg, rgba(1, 20, 38, 0.68) 0%, rgba(1, 26, 48, 0.44) 58%, rgba(1, 30, 55, 0.26) 100%),
			linear-gradient(to top, rgba(1, 18, 34, 0.95) 0%, rgba(1, 18, 34, 0.86) 40%, rgba(1, 18, 34, 0.42) 72%, rgba(1, 18, 34, 0.04) 100%);
	}

	/* The ghost is behind copy that now runs full width, so it moves off the right edge and drops a
	   size rather than sitting under the middle of the lead. */
	.aeca-sub--products .aeca-sub-hero__ghost {
		max-width: 84%;
		font-size: clamp(4rem, 17vw, 9rem);
	}

	/* The tile stops being a right-hand column and falls into the flow under the copy, which is the
	   one reason it was positioned against the container rather than the stage. The stage's
	   `align-items: flex-end` would otherwise shrink it to its content, so the width is what holds
	   the shape. */
	.aeca-sub--products .aeca-sub-hero__product {
		position: static;
		width: min(100%, 420px);
		margin: clamp(26px, 5vw, 40px) 0 0;
	}

	/* A trimmed render has to keep leading with one dimension, and here it is the width, because the
	   tile is now a block in the flow and the column decides how wide it is. Without this the rule
	   above sets a width while the base rule still sets a height, both dimensions are fixed,
	   `aspect-ratio` is ignored, and the crop silently stops cropping -- which on Sony meant the
	   Alpha lockup reappeared below 992px and nowhere else. */
	.aeca-sub--products .aeca-sub-hero__product--crop {
		max-width: none;
		height: auto;
	}

	.aeca-sub--products .aeca-sub-hero--plate .aeca-sub-hero__copy {
		max-width: none;
	}

	/* No reserved top band on a plate page: the tile is below the copy now, so nothing needs the top
	   of the frame kept clear, and the height comes from the content. */
	.aeca-sub--products .aeca-sub-hero--plate .aeca-sub-hero__stage {
		min-height: 0;
		padding: clamp(40px, 8vw, 72px) 0 clamp(32px, 5vw, 52px);
	}
}

@media (max-width: 767.98px) {

	/* Below a phone the label and the sentence cannot share a row -- the tag is 0.72rem at 0.2em
	   tracking, so a two-word tag is most of a 390px measure on its own. Stacked, it reads as a
	   kicker over its own caption, which is the same relationship. */
	.aeca-sub-band__cap {
		grid-template-columns: minmax(0, 1fr);
		gap: 0.35rem;
	}

	/* A wide diagram is swiped on a phone rather than shrunk into one. Below 768px the container is
	   about 342px, and a strip of five labelled panels drawn into it gives each panel 68px and each
	   label roughly five pixels of cap height -- a picture of a figure rather than the figure. Holding
	   the image at a fixed height and letting the frame scroll puts the panels back at a size their
	   own labels survive, and the panel cut off at the right edge is what says there is more.

	   `aspect-ratio: auto` has to be restored explicitly: the shared rule sets it from
	   --sub-band-ratio, and with a height and a ratio both in force the width stops following the
	   height and the overflow never happens. Photographs do not get this -- one subject shrinks fine,
	   and a photograph that scrolls just looks broken. */
	.aeca-sub-band--scroll .aeca-sub-band__frame {
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior-x: contain;
	}

	.aeca-sub-band--scroll .aeca-sub-band__img {
		width: auto;
		height: 62vw;
		min-width: 100%;
		max-height: 300px;
		aspect-ratio: auto;
		object-fit: contain;
	}

	/* One row is a desktop rule. Four cards on a phone is four 80px columns, so the count is
	   dropped and the cards stack. */
	.aeca-sub .aeca-sub-cards.aeca-sub-cards--cols-3,
	.aeca-sub .aeca-sub-cards.aeca-sub-cards--cols-4 {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Two classes, because Services caps its h1 at 16ch. A `ch` cap that was a deliberate ragged
	   edge on a 1180px page is a two-word line on a phone. */
	.aeca-sub .aeca-sub-hero h1 {
		max-width: none;
	}

	/* The strip cells were a 152px box holding one line of text and an arrow, with the gap between
	   them stretched to fill the rest. Side by side that reads as a card; stacked six deep on a
	   phone it is six mostly-empty boxes. Height comes from the content instead. */
	.aeca-sub .aeca-sub-sibling {
		gap: 0.9rem;
		min-height: 0;
		padding: 1.15rem 1.2rem;
	}

	/* The number moves onto the same line as the title rather than eating a column of a 390px
	   screen; the body drops beneath both. */
	.aeca-sub--services .aeca-sub-ledger__row,
	.aeca-sub--products .aeca-sub-ledger__row {
		grid-template-columns: 2.4rem minmax(0, 1fr);
	}

	.aeca-sub--services .aeca-sub-ledger__body,
	.aeca-sub--products .aeca-sub-ledger__body {
		grid-column: 2;
	}

	.aeca-sub-facts {
		grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	}

	.aeca-sub--services .aeca-sub-facts > div {
		padding: 1.15rem 1.1rem 1.05rem;
		border-bottom: 1px solid rgba(255, 255, 255, 0.11);
	}

	.aeca-sub--services .aeca-sub-facts > div::before,
	.aeca-sub--services .aeca-sub-facts > div:first-child::before {
		left: 1.1rem;
	}

	.aeca-sub--services .aeca-sub-facts > div:first-child {
		padding-left: 1.1rem;
	}

	/* A label needs proportionally more of a narrow table than of a wide one, so this keeps the same
	   relationship to the 28% above that 42% had to 36%. */
	.aeca-sub-specs tbody th {
		width: 34%;
	}

	/* The band is a drawn field with a fact strip on it, and on a phone that strip is two rows deep.
	   The minimum comes down so the ground is a band behind the facts rather than half a screen of
	   sky above them; the flex column means the band still grows if the strip needs more. */
	.aeca-sub--industries .aeca-sub-hero__band {
		min-height: clamp(330px, 86vw, 410px);
	}

	/* A pair of overrides widened the ridge hills here, because `rx` in `vw` pinched them into cones at
	   390px. Removed with the ridges themselves on 2026-08-14. The field and the grid need no mobile
	   handling: the gradient is in percentages and the grid is a fixed 54px cell at every width. */

	.aeca-sub--services .aeca-sub-hero__stage {
		padding: clamp(42px, 11vw, 72px) 0 clamp(34px, 7vw, 54px);
	}

	/* A 640px-tall hero is most of a phone screen before a word of the page is reached. The image
	   stays, the frame gets shorter, and the display size of the title comes down with it -- 6.4vw
	   of a 390px screen is a 25px headline, which is smaller than the lead beneath it. */
	.aeca-sub--products .aeca-sub-hero__stage {
		min-height: clamp(360px, 74vw, 470px);
		padding: clamp(54px, 15vw, 90px) 0 clamp(26px, 6vw, 40px);
	}

	.aeca-sub--products .aeca-sub-hero h1 {
		font-size: clamp(2.4rem, 10.5vw, 3.4rem);
	}

	.aeca-sub--products .aeca-sub-hero h1::after {
		width: 46px;
		margin-top: 0.9rem;
	}

	.aeca-sub--products .aeca-sub-hero__lead {
		font-size: 1rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.aeca-sub-card,
	.aeca-sub-card::before,
	.aeca-sub-sibling,
	.aeca-sub-sibling span:last-child,
	.aeca-sub-card__go {
		transition: none;
	}

	.aeca-sub-card--link:hover .aeca-sub-card__go,
	.aeca-sub-card--link:focus-within .aeca-sub-card__go {
		transform: none;
	}

	.aeca-sub--services .aeca-sub-card:hover {
		transform: none;
	}

	.aeca-sub-sibling:hover span:last-child,
	.aeca-sub-sibling:focus span:last-child {
		transform: none;
	}
}









/* ====================================================================================
   AECA revision pass, 2026-09-07 -- detail-page family
   ------------------------------------------------------------------------------------
   The three items from that pass that live inside the sub-page families. The site-wide
   ones are in css/aeca-custom.css under the same date.
   ==================================================================================== */


/* 8. THE INDUSTRIES SOLUTION CARDS CARRY AN ICON, NOT A BLUE PATCH.
   ------------------------------------------------------------------------------------
   `.aeca-sub--industries .aeca-sub-card::before` further up this file draws a 40px
   accent square above the heading -- the "square cap". It was the industries answer to
   the Services top bar: a mark that says which family you are in without needing
   artwork. AECA has asked for real icons in that slot instead.

   The cards already support one: pass `icon` on a card item and
   aeca_subpage_body_cards() emits `.aeca-sub-card__icon`. So the work is done in the six
   industries templates, and this rule is only the other half of it -- the square has to
   come off the cards that now have an icon, or the two stack and every card gains 40px
   of blue above its picture.

   `:has()` rather than a modifier class, so a template that adds or drops an icon does
   not also have to remember to add or drop a class. Support is universal in the browsers
   this site targets; in anything older the square simply stays, which is the old design
   rather than a broken one. */
.aeca-sub--industries .aeca-sub-card:has(.aeca-sub-card__icon)::before {
	content: none;
}

/* The icon is sized to sit where the square did, so the heading below it does not move
   and a row mixing an icon card with a plain one still lines its headings up. */
.aeca-sub--industries .aeca-sub-card__icon {
	display: block;
	width: 56px;
	height: 56px;
	margin-bottom: 1.1rem;
}

.aeca-sub--industries .aeca-sub-card__icon .aeca-icon {
	width: 100%;
	height: 100%;
}


/* 9. CASE STUDIES RUN COPY LEFT, IMAGE RIGHT.
   ------------------------------------------------------------------------------------
   AECA's Blocs arrangement: the study's text in a wide column with a supporting image
   beside it, rather than the full-width block of prose this was. Roughly two thirds to
   one third, which is the col-sm-8 / col-sm-4 split from the canvas.

   ONLY WHEN THERE IS AN IMAGE. `--figure` is set by the renderer when the study actually
   carries one, so a study still waiting on artwork keeps the full measure instead of
   leaving a third of the row empty. See aeca_subpage_body_stories(). */
.aeca-sub-story--figure {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
	gap: clamp(24px, 3vw, 44px);
	align-items: start;
}

.aeca-sub-story__figure img {
	display: block;
	width: 100%;
	height: auto;
}

/* The image goes under the copy on a tablet and below. At a third of a 768px row it is
   about 230px wide, which is too small to read and too small to be worth the column. */
@media (max-width: 991.98px) {

	.aeca-sub-story--figure {
		grid-template-columns: 1fr;
	}

	/* Above the copy rather than below it, so a reader meets the picture with the
	   headline instead of after three paragraphs of it. */
	.aeca-sub-story__figure {
		order: -1;
	}
}


/* 10. THE SPECIFICATION TABLES ARE COMPACT.
   ------------------------------------------------------------------------------------
   Two tables side by side above 900px, one below it. The renderer decides whether to
   split -- above six rows -- and emits `--split` when it has; see
   aeca_subpage_body_specs() for why the split is by halves rather than by filling
   across.

   900px, not a Bootstrap breakpoint. The two halves need roughly 380px each to keep a
   label and its value on one line apiece, and the container is at its own gutters by
   then, so this is the width the content stops working at rather than a width the grid
   happens to name. */
.aeca-sub-specs__grid {
	display: grid;
	gap: 0 clamp(28px, 3vw, 52px);
}

@media (min-width: 900px) {
	.aeca-sub-specs--split .aeca-sub-specs__grid {
		grid-template-columns: 1fr 1fr;
	}
}

/* Rows come down from 0.62rem to 0.5rem of vertical padding. Small on its own; over the
   fourteen rows of the Trinity table it is most of a heading's worth of height, and it
   is what stops a two-column table reading as airier than the one-column one it
   replaced. */
.aeca-sub-specs th,
.aeca-sub-specs td {
	padding-top: 0.5rem;
	padding-bottom: 0.5rem;
}

/* The label column can afford to be wider now that the table is half as wide, and a
   label like "Maximum take-off altitude" needs it to stay on one line. */
.aeca-sub-specs--split tbody th {
	width: 46%;
}

/* The source note. It was a <caption>, which Bootstrap's reboot renders at the foot of
   its own table -- fine when there was one table, wrong when there are two, because it
   would print twice. It is now a paragraph belonging to the section, drawn once under
   the pair. The rules match what `.aeca-sub-specs caption` had. */
.aeca-sub-specs__note {
	margin: 0.7rem 0 0;
	color: var(--sub-muted);
	font-size: 0.88rem;
	line-height: 1.5;
	text-align: left;
}

/* Zebra striping is per table, and with two tables side by side the two sets of stripes
   have to start on the same row or the pair reads as misaligned. `nth-child(even)` on
   each tbody does that already -- both start at row 2 -- so nothing is needed here
   beyond saying so, but the odd-length case is worth knowing: a thirteen-row table
   splits 7 and 6, so the right column ends one row short. That is a ragged bottom edge
   by one row, not a striping fault. */


/* ====================================================================================
   AECA revision pass, 2026-09-07 -- second round
   ------------------------------------------------------------------------------------
   Four corrections after AECA reviewed the first round.
   ==================================================================================== */


/* 1. CARDS IN A ROW SHARE THEIR ROW TRACKS.
   ------------------------------------------------------------------------------------
   The complaint, with a screenshot: four cards on the Solutions hub whose titles ran to
   three, one, two and three lines, so the first line of body copy sat at four different
   heights across the row.

   The first round aligned the BOTTOM of those cards -- `margin-bottom: auto` put the
   arrows on one line -- and left the top alone. That was the wrong edge. A reader scans
   down the left of a row and sees the paragraphs start at four different heights long
   before they notice the arrows agree.

   Flexbox cannot fix it: a card has no way to know how tall its neighbour's title is.
   Subgrid can. The card GRID owns three row tracks -- head, body, foot -- every card
   spans all three, and each track is sized to the tallest card in that row. The heads
   therefore share one height, so every body starts on the same line, and the feet share
   one too, which keeps what the first round got right.

   aeca_subpage_body_cards() emits the three wrappers unconditionally for exactly this
   reason; a card that skipped an empty one would span two tracks instead of three and
   throw the whole row out. See the note there.

   ROW-GAP ZERO ON THE CARD. A subgrid inherits its parent's gap, so the card's three
   tracks would otherwise be pushed 18-28px apart INSIDE the card. Only the gaps within
   a card's own span are affected, so the gap between one row of cards and the next is
   untouched -- that one belongs to the parent. Spacing inside a card stays where it has
   always been, on the margins of the h3 and the paragraphs. */
.aeca-sub .aeca-sub-card {
	display: grid;
	grid-template-rows: subgrid;
	grid-row: span 3;
	row-gap: 0;
}

.aeca-sub .aeca-sub-card__head,
.aeca-sub .aeca-sub-card__body,
.aeca-sub .aeca-sub-card__foot {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

/* The body fills its track rather than centring in it, so a short paragraph sits under
   its heading instead of floating in the middle of the space the longest card needs. */
.aeca-sub .aeca-sub-card__body {
	justify-content: flex-start;
}

/* The head holds the icon, the numeral and the title, and the title is the last thing in
   it -- so its bottom margin is what separates head from body, and it has to survive the
   families' own `h3 { margin: 0 0 ... }` rules. Nothing to set here beyond making sure
   the title is not stretched by the flex column. */
.aeca-sub .aeca-sub-card__head > h3 {
	flex: 0 0 auto;
}

/* Fallback for a browser without subgrid. The cards go back to being flex columns, which
   is exactly the behaviour of the first round -- bottoms aligned, tops not -- rather
   than a broken layout. */
@supports not (grid-template-rows: subgrid) {

	.aeca-sub .aeca-sub-card {
		display: flex;
		flex-direction: column;
	}

	.aeca-sub .aeca-sub-card__body {
		flex: 1;
	}
}

/* THE INDUSTRIES SQUARE CAP MOVES ONTO THE HEAD. It was `.aeca-sub-card::before`, an
   in-flow block that was the card's first child. Under subgrid a card's children ARE its
   grid items, so that pseudo-element became a fourth item in a three-track grid and
   pushed everything down a row. On `__head::before` it is back inside a normal flex
   column and draws exactly where it did.

   The `:has()` suppression from the first round moves with it: a card that carries a
   real icon does not also draw the square. */
.aeca-sub--industries .aeca-sub-card::before {
	content: none;
}

.aeca-sub--industries .aeca-sub-card__head::before {
	content: "";
	display: block;
	width: 40px;
	height: 40px;
	margin-bottom: 1.35rem;
	background: var(--sub-accent);
	clip-path: polygon(0 0, 100% 0, 100% 72%, 72% 100%, 0 100%);
}

.aeca-sub--industries .aeca-sub-section--navy .aeca-sub-card__head::before {
	background: var(--sub-blue-light);
}

.aeca-sub--industries .aeca-sub-card__head:has(.aeca-sub-card__icon)::before {
	content: none;
}


/* 3. ONE SPECIFICATION TABLE SHAPE, WHATEVER ITS LENGTH.
   ------------------------------------------------------------------------------------
   The first round split any table over six rows into two side by side, which made
   Trinity Pro (seven rows) and Vector AI (six) render as two different components on the
   same page. AECA asked why. The answer was that the threshold was a bad idea, and what
   was actually wanted was a narrower table.

   So the split is gone -- see aeca_subpage_body_specs() -- and this is the width instead.
   760px is about 65 characters of the value column at this type size, which is where a
   line of prose stops being comfortable to read, and it keeps the label and its value
   close enough to pair by eye.

   LEFT-ALIGNED, NOT CENTRED. The section heading above it is on the container's left
   edge, and a centred table under a left-aligned rule reads as a mistake. */
.aeca-sub-specs {
	max-width: 760px;
}

.aeca-sub-specs tbody th {
	width: 38%;
}

/* Undo the two-table rules from the first round. Kept as an explicit reset rather than
   deleted above, so the diff shows what was withdrawn and why. */
.aeca-sub-specs__grid {
	display: block;
}


/* 5. CASE STUDIES: COPY LEFT, FIGURE RIGHT, ON EVERY STUDY.
   ------------------------------------------------------------------------------------
   The first round made the image optional, so a study with no photograph stayed full
   width -- which meant the two-column shape AECA asked for appeared nowhere, because no
   photographs have been supplied yet.

   Corrected: every study is two columns now. Where there is a photograph it is the
   figure; where there is not, the figure is a drawn panel carrying the sector's own line
   icon on a tint. That is the same `--photo` / `--graphic` pair the sub-page heroes
   already use, so it is a treatment this site has rather than a stand-in, and it carries
   no text addressed to whoever is building the page.

   Swapping a real photograph in later is one `image` key per study and this panel
   disappears for it. */
.aeca-sub-story {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
	gap: clamp(24px, 3vw, 44px);
	align-items: start;
}

.aeca-sub-story__figure img {
	display: block;
	width: 100%;
	height: auto;
}

/* The drawn panel. Square, so it holds the same footprint as a photograph would at this
   column width, and quiet enough that it reads as a marker rather than as a picture
   competing with the copy beside it. */
.aeca-sub-story__figure--graphic {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 4 / 3;
	background:
		linear-gradient(135deg, rgba(22, 173, 238, 0.09), rgba(2, 77, 161, 0.05)),
		var(--sub-tint);
	box-shadow: inset 0 0 0 1px var(--sub-line);
}

.aeca-sub-story__figure--graphic .aeca-icon {
	width: 40%;
	max-width: 96px;
	height: auto;
	opacity: 0.72;
}

/* The figure goes above the copy on a tablet and below. At a third of a 768px row it is
   about 230px wide, which is too small to be worth its own column. */
@media (max-width: 991.98px) {

	.aeca-sub-story {
		grid-template-columns: 1fr;
	}

	.aeca-sub-story__figure {
		order: -1;
		max-width: 420px;
	}
}


/* 5b. THE SECTOR STRIP.
   ------------------------------------------------------------------------------------
   The six industries as a row of buttons directly under the hero, which is what AECA
   built on the Blocs canvas (bloc-242) and asked for here.

   IT IS NOT THE SIBLING STRIP AT THE FOOT. That one shows five of anything and is about
   "what else is here"; this one shows all six industries, always in the registry order,
   with the current page marked and unclickable. It is a position indicator as much as a
   navigation, which is why it sits at the top.

   Three across on a desktop and two on a tablet, so six always fills its rows evenly --
   the same reasoning as the industry tile grids. */
.aeca-sector-strip {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.aeca-sector-strip a,
.aeca-sector-strip span {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 100%;
	min-height: 52px;
	padding: 0.7rem 1rem;
	text-align: center;
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	line-height: 1.25;
	text-transform: uppercase;
	text-decoration: none;
}

.aeca-sector-strip a {
	color: var(--sub-blue);
	box-shadow: inset 0 0 0 1px var(--sub-line);
	transition: background-color 0.16s ease, box-shadow 0.16s ease;
}

.aeca-sector-strip a:hover,
.aeca-sector-strip a:focus-visible {
	background: var(--sub-tint);
	box-shadow: inset 0 0 0 1px var(--sub-blue-light);
}

/* The current page. Filled rather than outlined, and a <span> rather than an <a>, so it
   is not a link to where the reader already is. */
.aeca-sector-strip span {
	background: var(--sub-blue);
	color: #fff;
}

@media (max-width: 767.98px) {
	.aeca-sector-strip {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* The strip's own band. Tight vertical padding -- it is a navigation row sitting between the hero
   and the first real section, not a section of its own, and giving it a section's rhythm would
   push the page's actual opening argument below the fold. */
.aeca-sub-strip {
	padding: clamp(18px, 2.4vw, 28px) 0;
	background: var(--sub-white);
	border-bottom: 1px solid var(--sub-line);
}

/* 4. PAYLOAD CARDS.
   ------------------------------------------------------------------------------------
   The Trinity camera list, shown rather than tabulated. Three across on a desktop, which
   leaves the fifth card starting a second row -- acceptable here because the row is a
   catalogue and not a set of three, and preferable to five cramped columns where a
   product shot would be 150px wide.

   Subgrid again, for the same reason as everywhere else in this pass: the shot, the tag,
   the name, the headline figure and the body each get their own track, so the five names
   sit on one line and the five figures on another and the cards can be read across. */
.aeca-sub-payloads {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(18px, 2vw, 28px);
}

.aeca-sub-payload {
	display: grid;
	grid-template-rows: subgrid;
	grid-row: span 2;
	row-gap: 0;
	background: var(--sub-white);
	box-shadow: 0 0 0 1px var(--sub-line);
}

/* The shot sits on white with the product contained rather than cropped: these are
   cut-outs of hardware, and a cover crop would cut the lens off the front of a camera. */
.aeca-sub-payload__shot {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp(14px, 1.6vw, 22px);
	background: #fff;
	border-bottom: 1px solid var(--sub-line);
}

.aeca-sub-payload__shot img {
	display: block;
	width: 100%;
	height: auto;
}

/* The drawn state, for a payload whose vendor render AECA has not supplied yet. Same
   panel as the case-study figures, so the two read as one decision. */
.aeca-sub-payload__shot--graphic {
	aspect-ratio: 4 / 3;
	background:
		linear-gradient(135deg, rgba(22, 173, 238, 0.09), rgba(2, 77, 161, 0.05)),
		var(--sub-tint);
}

.aeca-sub-payload__shot--graphic .aeca-icon {
	width: 44%;
	max-width: 110px;
	height: auto;
	opacity: 0.72;
}

.aeca-sub-payload__text {
	display: flex;
	flex-direction: column;
	padding: clamp(18px, 2vw, 26px);
}

.aeca-sub-payload__tag {
	margin: 0 0 0.45rem;
	color: var(--sub-blue-light);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	line-height: 1.2;
	text-transform: uppercase;
}

.aeca-sub .aeca-sub-payload h3 {
	margin: 0 0 0.3rem;
	color: var(--sub-blue);
	font-size: clamp(1.08rem, 1.5vw, 1.25rem);
	font-weight: 600;
	line-height: 1.24;
}

/* The one figure that decides the choice, set apart from the prose so the five cards can
   be compared without reading all five paragraphs. */
.aeca-sub .aeca-sub-payload__spec {
	margin: 0 0 0.7rem;
	color: var(--sub-ink);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.95rem;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	line-height: 1.35;
}

.aeca-sub .aeca-sub-payload__body {
	margin: 0;
	color: var(--sub-muted);
	font-size: 0.92rem;
	line-height: 1.6;
}

@media (max-width: 900px) {
	.aeca-sub-payloads { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
	.aeca-sub-payloads { grid-template-columns: minmax(0, 1fr); }
}

@supports not (grid-template-rows: subgrid) {
	.aeca-sub-payload { display: flex; flex-direction: column; }
	.aeca-sub-payload__text { flex: 1; }
}

/* THE FOURTH TRACK, 2026-09-07 third round.
   ------------------------------------------------------------------------------------
   AECA's second screenshot: three Mobile Mapping cards whose titles agreed and whose
   paragraphs agreed, and then the rule above each ticked list sat at three different
   heights. One card's prose ran to five lines and its neighbours' to four, and the prose
   and the list were sharing a track -- so only the top of that track was pinned and
   everything below the longest paragraph drifted.

   `points` and `details` now live in `__extra`, their own track. Four tracks, one span,
   and the rule opens on one line across the row. See aeca_subpage_body_cards(). */
.aeca-sub .aeca-sub-card {
	grid-row: span 4;
}

.aeca-sub .aeca-sub-card__extra {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

/* `margin-top: auto` on `.aeca-sub-card__more` was what pushed the list to the foot of a
   flex card. In its own track it would bottom-align the list inside that track instead,
   which reintroduces the drift one level down. The track placement does the job now. */
.aeca-sub .aeca-sub-card__extra > .aeca-sub-card__more {
	margin-top: 0;
}

@supports not (grid-template-rows: subgrid) {

	/* Back to a flex column, where the auto margin is still the right mechanism. */
	.aeca-sub .aeca-sub-card__extra {
		margin-top: auto;
	}
}

/* THE PAYLOAD SHOTS ARE FULL-BLEED RENDERS NOW, not cut-outs on white.
   ------------------------------------------------------------------------------------
   AECA supplied Quantum Systems' own payload renders on 2026-09-07: the pod opened on a
   grey studio gradient, one series, same angle and light across all four. They carry
   their own ground, so the white plate and the padding this slot had -- both written for
   a cut-out floating on white -- would put a frame around a frame.

   The graphic fallback keeps its own rules below and is unaffected; with all four
   payloads now photographed, nothing on the site renders it, but the Trinity range can
   grow and the next payload may arrive without a render. */
.aeca-sub-payload__shot:not(.aeca-sub-payload__shot--graphic) {
	display: block;
	padding: 0;
	background: var(--sub-tint);
}

.aeca-sub-payload__shot:not(.aeca-sub-payload__shot--graphic) img {
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

/* THE SIBLING STRIP'S TWO GROUPS.
   ------------------------------------------------------------------------------------
   Added with the split in aeca_subpage_siblings(): on a page that belongs to a range,
   the range links sit in their own labelled group above everything else.

   The label is the only new furniture. It is set small and uppercase so it reads as a
   divider between two sets of links rather than as a second section heading under the
   one already above it -- there is one heading here, and it belongs to the section. */
.aeca-sub-siblings-group + .aeca-sub-siblings-group {
	margin-top: clamp(22px, 2.6vw, 34px);
}

.aeca-sub-siblings__label {
	margin: 0 0 0.75rem;
	color: var(--sub-muted);
	font-family: var(--aeca-font-head, "Outfit", sans-serif);
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	line-height: 1.2;
	text-transform: uppercase;
}

/* The range group is the one the reader is most likely to want, so it takes the accent
   for its label and a rule down its left edge to tie its links together as a set. */
.aeca-sub-siblings-group:first-child .aeca-sub-siblings__label {
	color: var(--sub-blue);
}

/* FOUR PAYLOADS GO TWO BY TWO, not three and a stray.
   ------------------------------------------------------------------------------------
   The grid is three across, which was right when the section held five. Trinity now has
   four -- MicaSense came off on 2026-09-07 -- and four in a three-column grid is a row of
   three with one card marooned underneath.

   Two by two also suits what these cards are. The renders are the reason the section
   exists, and at half the container they are about 560px wide instead of 370px, which is
   the difference between seeing the sensor inside the pod and guessing at it.

   `:has(> :nth-child(4):last-child)` is exactly "has four children" -- the fourth is also
   the last -- so a fifth payload silently returns the row to three across and no rule has
   to be remembered. */
.aeca-sub-payloads:has(> :nth-child(4):last-child) {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 900px) {
	.aeca-sub-payloads:has(> :nth-child(4):last-child) {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 560px) {
	.aeca-sub-payloads:has(> :nth-child(4):last-child) {
		grid-template-columns: minmax(0, 1fr);
	}
}
