/* ============================================================
   indo-2027: catalogue surfaces

   Loaded by inc/assets.php on products, product archives and the
   catalogue page templates, via indo_2027_is_catalogue_view().
   Depends on components.css, which already carries every component
   these screens use: the gallery, the tabs, the spec table, the
   document table, the accordion, the refine rail, the cards and
   the breadcrumb.

   WHAT IS HERE is the section shapes those components sit in, plus
   the two things no component covers: the stored HTML spec table
   that product copy arrives as, and the UMSUG plugin's own markup.

   HOUSE RULES, throughout: border-radius 0 on everything, and one
   transform or colour change at var(--dur-base) var(--easing).
   ============================================================ */


/* ============================================================
   1. Product detail
   BUILD-SPEC 05
   ============================================================ */

.indo-product__crumbs {
	padding-top: var(--space-3);
	/* The trail sat 11px above the gallery frame (go-live audit
	   catalogue-24). */
	padding-bottom: var(--space-2);
}

/*
 * Section rhythm on the product page (catalogue-20). Every section here is a
 * full .indo-section, so the lead's bottom padding and the body's top
 * padding stacked into a 240px dead band between the downloads and the body
 * copy at 1440, and the two body sections did the same (256px). One band of
 * 40 to 64px now separates each block on the same white ground; the spec
 * section keeps its own padding because it is a different ground.
 */
.indo-product__lead { padding-bottom: clamp(40px, 5vw, 64px); }
.indo-product__body { padding-block: clamp(40px, 5vw, 64px); }
.indo-product__lead + .indo-product__body,
.indo-product__body + .indo-product__body { padding-top: 0; }

.indo-product__grid {
	display: grid;
	grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
	gap: var(--space-6);
	align-items: start;
}
/* Both columns may shrink below their content's min-content width: the
   gallery's thumb strip is one scrolling row, and without this its ten
   thumbs widened the media column (970px at 1440) and pushed a phone
   page 330px sideways. */
.indo-product__media,
.indo-product__summary { min-width: 0; }

.indo-product__summary > * + * { margin-top: var(--space-2); }

.indo-product__title {
	min-width: 0;
	margin: 0;
	font-size: var(--fs-d7);
	line-height: var(--lh-display);
	letter-spacing: var(--tracking-display);
	/* The summary column may shrink below min-content (it has to, for the
	   gallery's thumb strip), so a word longer than the column, German
	   "Fussgangeruberweg", must break inside it or it widens the page (QA
	   A-01: +122px at 900). overflow-wrap only breaks a word that cannot fit
	   on its own line; hyphens: auto split titles that fit ("Cros-sing" at
	   1440, QA round two), so hyphenation stays manual. */
	overflow-wrap: anywhere;
	hyphens: manual;
}
/* Two-column layout between 821 and 1100px: the column is 370 to 450px, so
   the display size steps down with the viewport rather than breaking the
   longest translated words. */
@media (min-width: 821px) and (max-width: 1100px) {
	.indo-product__title { font-size: clamp(34px, 3.2vw + 6px, 42px); }
}

.indo-product__summary .lede {
	margin: var(--space-3) 0 0;
	max-width: var(--measure-lede);
}

/*
 * The excerpt, one style whatever the stored HTML says (catalogue-27).
 * indo_2027_product_excerpt_html() has already removed the inline colours,
 * unwrapped the bold, and turned a stored heading or a run of ALL-CAPITALS
 * lead bullets into one kicker line; this sets the list itself.
 */
.indo-product__excerpt { color: var(--indo-charcoal); }
.indo-product__excerpt ul {
	margin: 0;
	padding: 0;
	list-style: none;
}
.indo-product__excerpt li {
	position: relative;
	margin: 0 0 6px;
	padding-left: 18px;
	line-height: var(--lh-body);
}
.indo-product__excerpt li:last-child { margin-bottom: 0; }
.indo-product__excerpt li::before {
	content: '';
	position: absolute;
	top: 0.7em;
	left: 0;
	width: 6px;
	height: 6px;
	background: var(--accent);
}
.indo-product__excerpt a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.indo-product__excerpt a:hover,
.indo-product__excerpt a:focus-visible { color: var(--accent); }
.indo-product__excerpt p { margin: 0 0 var(--space-1); }
.indo-product__excerpt-kicker {
	margin: 0 0 12px;
	font-size: var(--fs-micro);
	font-weight: var(--w-body-bold);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--indo-gray-text);
}

.indo-product__kpi { margin-top: var(--space-3); }

/*
 * The summary column is a size container so the KPI strip can respond to the
 * width it actually has, not to the viewport: at 1024 the two-column product
 * grid leaves the summary about 430px, which is phone-sized. Under 480px the
 * strip becomes compact label-and-value rows (go-live audit catalogue-03:
 * three 114px cells of 28px text pushed the page 30 to 130px sideways).
 */
.indo-product__summary { container-type: inline-size; }

/*
 * Three cells across the 578px summary were 192px each, so figures broke
 * mid-figure at 1440 ("3,000 - / 24,000 lm", "234,000 / hours"; QA of
 * catalogue-07). From 480px of summary width a three-cell strip is two
 * columns with the third cell across both, and every figure holds one line.
 */
@container (min-width: 480px) {
	.indo-product__kpi.indo-spectable--kpi-cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.indo-product__kpi.indo-spectable--kpi-cols-3 .indo-spectable__kpi:nth-child(3) { grid-column: 1 / -1; }
	.indo-product__kpi .indo-spectable__kpivalue {
		font-size: 24px;
		white-space: nowrap;
	}
}

@container (max-width: 479px) {
	.indo-product__kpi { grid-template-columns: minmax(0, 1fr); }
	/*
	 * Label left, value right, and when the two do not fit one line the value
	 * wraps under the label instead of squeezing it (final-locales-01). The
	 * label used to be capped at 50% of the row, about 150px at 375, so the
	 * one-word Nordic labels (Lysstrømsvedligeholdelse, Ljusflödesbibehållning,
	 * Lichtstroombehoud) broke mid-word with no hyphen. Tighter tracking on
	 * this compact row lets the longest of them hold one line down to 360.
	 */
	.indo-product__kpi .indo-spectable__kpi {
		display: flex;
		flex-flow: row wrap;
		align-items: baseline;
		justify-content: space-between;
		gap: 4px var(--space-1);
		padding: 14px var(--space-1);
	}
	.indo-product__kpi .indo-spectable__kpilabel {
		flex: 0 1 auto;
		max-width: 100%;
		margin: 0;
		letter-spacing: 0.08em;
	}
	.indo-product__kpi .indo-spectable__kpivalue {
		flex: 0 1 auto;
		min-width: 0;
		margin: 0 0 0 auto;
		font-size: 20px;
		text-align: right;
	}
}

.indo-product__actions { margin-top: var(--space-3); }

.indo-product__downloads { margin-top: var(--space-3); }

/*
 * Above the fold (run 21 item 175, extended to every product by go-live audit
 * catalogue-05). The actions row sits straight under the H1: the call-back
 * CTA and the data sheet as a ghost button beside it. Belisha keeps its
 * one-line lede above the row and ION Sign its "Which type?" line after the
 * bullets; see woocommerce/single-product.php. `.indo-product__summary > * + *`
 * already spaces these from their neighbours.
 */
.indo-product__atflede {
	max-width: var(--measure-lede);
	color: var(--fg-2);
}
.indo-product__actions--atf {
	align-items: stretch;
	gap: 12px;
}
/* The data sheet as a ghost button. Its border is restated here because
   chrome.css re-declares `.indo-btn { border: 0 }` after components.css,
   which strips the ghost-light variant's outline everywhere. */
.indo-product__actions .indo-product__sheet {
	border: 1px solid var(--border-strong);
	padding: 15px 29px;
	color: var(--indo-charcoal);
	transition:
		border-color var(--dur-base) var(--easing),
		color var(--dur-base) var(--easing);
}
.indo-product__actions .indo-product__sheet:hover,
.indo-product__actions .indo-product__sheet:focus-visible {
	border-color: var(--accent);
	color: var(--accent);
}
@media (max-width: 600px) {
	/* Two full-width buttons on a phone, the CTA first. */
	.indo-product__actions--atf > .indo-btn { flex: 1 1 100%; }
}

/*
 * On phones and tablets the actions row comes straight after the H1, before
 * Belisha's one-line lede: the translated ledes are two to three lines longer
 * and pushed the German and Finnish call-back button below the 812px fold
 * (QA of catalogue-05). The summary becomes a flex column so the lede can
 * follow the row without changing the source order the desktop layout keeps.
 */
@media (max-width: 820px) {
	.indo-product__summary {
		display: flex;
		flex-direction: column;
	}
	.indo-product__summary > * { order: 3; }
	.indo-product__summary > .indo-eyebrow,
	.indo-product__summary > .indo-product__title { order: 0; }
	.indo-product__summary > .indo-product__actions { order: 1; }
	.indo-product__summary > .indo-product__atflede--top { order: 2; }
}

/* Tablet, one column: a 4:3 frame is 540px tall at 768 and pushed the German
   and Finnish Belisha CTA to y 1013 on a 1024px screen. 16:9 keeps the whole
   product (object-fit: contain) and brings the actions row up by 135px. */
@media (min-width: 601px) and (max-width: 820px) {
	.indo-product__media .indo-gallery__frame { aspect-ratio: 16 / 9; }
}

/*
 * Belisha's compact gallery (item 175 b): on a phone, capping the gallery's
 * height is what gets the H1, the lede and the data-sheet link onto the
 * first screen, the same reason live's own compact rule exists.
 */
@media (max-width: 600px) {
	/* A definite height, not max-height: with max-height the image's
	   height: 100% had nothing to resolve against, laid out at its natural
	   height and was sliced at the 180px edge, cutting the Belisha lamp in
	   half (go-live audit catalogue-11). */
	.indo-product__media--compact .indo-gallery__frame {
		aspect-ratio: auto;
		height: 180px;
	}
	.indo-product__media--compact .indo-gallery__frame img { padding: 12px; }
	.indo-product__media--compact .indo-gallery__thumb { width: 44px; height: 44px; }
}

/* The gallery's thumb row fades at the edge that has more thumbs beyond it,
   the same cue as the spec tab strip (catalogue.js sets data-overflow). */
.indo-gallery__thumbs[data-overflow="end"] {
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent);
	mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent);
}
.indo-gallery__thumbs[data-overflow="start"] {
	-webkit-mask-image: linear-gradient(to left, #000 calc(100% - 56px), transparent);
	mask-image: linear-gradient(to left, #000 calc(100% - 56px), transparent);
}
.indo-gallery__thumbs[data-overflow="both"] {
	-webkit-mask-image: linear-gradient(to right, transparent, #000 56px, #000 calc(100% - 56px), transparent);
	mask-image: linear-gradient(to right, transparent, #000 56px, #000 calc(100% - 56px), transparent);
}

/* --- Products in the same category, closing the page (catalogue-32) ---
   Four cards across on the full rail; the archive's own auto-fill grid
   drops to two and one on narrower screens. */
.indo-product-related .indo-productgrid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
@media (max-width: 820px) {
	.indo-product-related .indo-section-head {
		grid-template-columns: minmax(0, 1fr);
		gap: 8px;
		margin-bottom: var(--space-3);
	}
	.indo-product-related .indo-sectiontitle { margin-bottom: 0; }
}

/*
 * The gallery column follows the reader down the summary (final-desktop-05).
 * The media column ended at y 716 at 1440 while the summary ran to 1302 on
 * AIR2 (586px of blank white, 335px on ION Sign, 248px on TopLink). Sticky
 * under the fixed header from the two-column layout up; the summary is the
 * taller column on every product, so the gallery stays in view beside the
 * bullets, the figures and the downloads and releases with the grid.
 */
@media (min-width: 821px) {
	.indo-product__media {
		position: sticky;
		top: calc(var(--chrome-h) + var(--space-3));
	}
}

/* --- Body prose (final-desktop-04) ---
   indo_2027_normalise_body() has already turned the Elementor-era bold
   subheads into h3, unwrapped the bold runs and lifted the brochure
   banners out. This sets what is left in TopLink's style: h3 in the theme
   scale, cyan square bullets as in the summary, images inside the column. */
.indo-product__prose h3 {
	margin-top: var(--space-4);
	margin-bottom: 0;
}
.indo-product__prose > h3:first-child { margin-top: 0; }
.indo-product__prose h3 + * { margin-top: var(--space-1); }
.indo-product__prose ul {
	margin-left: 0;
	padding: 0;
	list-style: none;
}
.indo-product__prose li {
	position: relative;
	margin: 0 0 8px;
	padding-left: 18px;
	line-height: var(--lh-body);
}
.indo-product__prose li:last-child { margin-bottom: 0; }
.indo-product__prose li::before {
	content: '';
	position: absolute;
	top: 0.7em;
	left: 0;
	width: 6px;
	height: 6px;
	background: var(--accent);
}
.indo-product__prose strong { font-weight: var(--w-body-bold); }
.indo-product__prose img {
	max-width: 100%;
	height: auto;
}
.indo-product__prose iframe { max-width: 100%; }

/* The brochure banners, as one strip under the prose on the full rail. */
.indo-product__figures {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 12px;
	margin-top: var(--space-5);
}
.indo-product__prose:empty + .indo-product__figures,
.indo-product__figures:first-child { margin-top: 0; }
.indo-product__figures--single { grid-template-columns: minmax(0, 1fr); max-width: var(--indo-prose); }
.indo-product__figure {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	background: var(--bg-soft-2);
}
@media (max-width: 600px) {
	.indo-product__figures {
		grid-template-columns: minmax(0, 1fr);
		gap: 8px;
		margin-top: var(--space-4);
	}
}

/* --- Body sections: the "To Specify" and "Spectrums" tabs --- */

.indo-product__section + .indo-product__section { margin-top: var(--space-4); }

.indo-product__sectiontitle {
	margin: 0 0 var(--space-2);
	padding-bottom: 14px;
	border-bottom: 2px solid var(--indo-charcoal);
	font-size: var(--fs-micro);
	font-weight: var(--w-body-bold);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--accent);
}

/* --- Technical specification --- */

.indo-product-spec__tabs { margin-top: var(--space-3); }

/*
 * A readable spec table (catalogue-23). At 1440 the rows ran 1,100px with
 * the value pinned to the far right, 1,000px from its key, and nothing but
 * hairlines between rows. The table and its tab strip now stop at 880px,
 * the value sits left-aligned in the second track beside its key, and the
 * rows alternate white on the paper ground.
 */
.indo-product-spec .indo-spectable--rows,
.indo-product-spec .indo-tabs,
.indo-product-spec__group { max-width: 880px; }
.indo-product-spec .indo-spectable__row {
	grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
	padding: 14px var(--space-1);
}
.indo-product-spec .indo-spectable__row:nth-child(odd) { background: var(--bg); }
.indo-product-spec .indo-spectable__value { text-align: left; }

@media (max-width: 600px) {
	.indo-product-spec .indo-spectable__row {
		grid-template-columns: minmax(0, 1fr);
		padding: 12px;
	}
}

.indo-product-spec__group {
	margin: var(--space-3) 0 var(--space-1);
	font-size: var(--fs-17);
	font-weight: var(--w-body-bold);
	color: var(--indo-charcoal);
}

/*
   .indo-spec-table is the class the LIVE DATA carries. Product copy is
   stored as HTML in `yikes_woo_products_tabs` and the spec table comes
   with this class on it; nothing in the theme has ever styled it,
   because the design's own script never returned the rows. The table
   form is styled here for any stored fragment that still renders raw
   (a term description, a prose tab), and the dl form is what
   template-parts/catalogue/spec-tabs.php emits after parsing.
*/
table.indo-spec-table {
	width: 100%;
	border-collapse: collapse;
	margin: var(--space-2) 0;
	font-size: var(--fs-small);
}
table.indo-spec-table th,
table.indo-spec-table td {
	padding: 13px var(--space-1) 13px 0;
	text-align: left;
	vertical-align: top;
	border-bottom: 1px solid var(--border-1);
}
table.indo-spec-table th { font-weight: var(--w-body-medium); color: var(--indo-gray-text); }
table.indo-spec-table td { color: var(--indo-charcoal); }
table.indo-spec-table .indo-spec-group th {
	padding-top: var(--space-3);
	border-bottom: 2px solid var(--indo-charcoal);
	font-size: var(--fs-micro);
	font-weight: var(--w-body-bold);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--accent);
}
table.indo-spec-table tr:first-child .indo-spec-group th,
table.indo-spec-table .indo-spec-group:first-child th { padding-top: 0; }


/* ============================================================
   2. Catalogue index
   BUILD-SPEC 22
   ============================================================ */

.indo-catalogue-index__group + .indo-catalogue-index__group { margin-top: var(--space-6); }

/* The first group starts one band under the hero, not a full section pad
   (catalogue-20: 126px). */
.indo-catalogue-index { padding-top: var(--space-4); }

.indo-catalogue-index__heading {
	margin: 0 0 var(--space-2);
	padding-bottom: var(--space-1);
	border-bottom: 2px solid var(--indo-charcoal);
	font-family: var(--font-body);
	font-size: var(--fs-micro);
	font-weight: var(--w-body-bold);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	/* Brand cyan as 12px text on white is about 2.9:1 and fails AA. The
	   accessible accent where one is defined, otherwise the heading colour.
	   Used on the catalogue index and the family pages. */
	color: var(--accent-text, var(--indo-charcoal));
}
.indo-catalogue-index__heading a {
	color: inherit;
	text-decoration: none;
	text-underline-offset: 3px;
}
.indo-catalogue-index__heading a:hover,
.indo-catalogue-index__heading a:focus-visible { text-decoration: underline; }

@media (max-width: 600px) {
	/*
	 * The group heading is itself the link into that category, and it measured
	 * 15px tall on a phone because an inline element takes only its line box.
	 * inline-flex gives it a real box to hit. 44px per the design's rule for
	 * anything tappable under 600px.
	 */
	.indo-catalogue-index__heading a {
		display: inline-flex;
		align-items: center;
		min-height: var(--tap-min);
	}
}

/*
   The rules between the cards are each card's own 1px outline, drawn as a
   spread shadow into the 1px gutter; neighbouring outlines land on the same
   pixel, so every rule is one hairline. It used to be the grid's own
   background showing through the gutter, which also painted every EMPTY
   cell of a short last row as a solid grey block (go-live audit
   catalogue-09: 635px of grey at 1024). Now an empty cell is page white.
   The 1px padding keeps the outer outlines inside the grid box.
*/
.indo-catalogue-index__grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
	gap: 1px;
	padding: 1px;
}
.indo-catalogue-index__grid > .indo-card,
.indo-catalogue-index__grid > .indo-card:hover,
.indo-catalogue-index__grid > .indo-card:focus-within {
	box-shadow: 0 0 0 1px var(--border-1);
}


/* ============================================================
   3. Product category archive
   BUILD-SPEC 23
   ============================================================ */

.indo-catalogue-head { border-bottom: 1px solid var(--border-1); }

/* The results start one band under the head, not a full section pad:
   120px of empty page at 1440 (catalogue-20). */
.indo-catalogue-body { padding-top: var(--space-4); }

.indo-catalogue-head__title {
	margin: var(--space-1) 0 0;
	font-size: var(--fs-d9);
	line-height: var(--lh-display);
	letter-spacing: var(--tracking-display);
}

.indo-catalogue-head__lede {
	margin: var(--space-2) 0 0;
	max-width: var(--measure-lede);
}
.indo-catalogue-head__lede p { margin: 0 0 var(--space-1); }
.indo-catalogue-head__lede p:last-child { margin-bottom: 0; }

.indo-catalogue-body__split {
	display: grid;
	grid-template-columns: 250px minmax(0, 1fr);
	gap: var(--space-5);
	align-items: start;
}
/* A term with no child categories has no rail (refine-terms.php prints
   nothing), so the results take the whole row. term-archive.php adds this
   modifier; without it the grid dropped into the 250px track. */
.indo-catalogue-body__split--full { grid-template-columns: minmax(0, 1fr); }

.indo-catalogue-body__bar {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: var(--space-3);
	flex-wrap: wrap;
	padding-bottom: 18px;
	margin-bottom: var(--space-3);
	border-bottom: 1px solid var(--border-1);
}

.indo-catalogue-body__count {
	margin: 0;
	font-family: var(--font-body);
	font-size: var(--fs-small);
	font-weight: var(--w-body);
	line-height: 1.5;
	letter-spacing: normal;
	color: var(--indo-gray-text);
}

.indo-catalogue-body__empty {
	margin: 0;
	font-size: var(--fs-body);
	color: var(--indo-gray-text);
}

.indo-productgrid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
	gap: var(--space-3);
}

/* Odd-count grids (item 14): auto-fill can leave one card alone in the
   final row (19 products is 2 + 2 + ... + 1 at 768, 3 + 3 + ... + 1 at
   1024), which reads as an accident next to the empty width beside it.
   Centring the lone card at its usual column width, rather than
   stretching it edge to edge, makes the row's end look chosen. No rule
   fires unless the count is actually odd for that column count. */
@media (min-width: 601px) and (max-width: 1023px) {
	.indo-productgrid > :last-child:nth-child(odd) {
		grid-column: 1 / -1;
		max-width: calc((100% - var(--space-3)) / 2);
		margin-inline: auto;
	}
}
@media (min-width: 1024px) and (max-width: 1439px) {
	.indo-productgrid > :last-child:nth-child(3n+1) {
		grid-column: 1 / -1;
		max-width: calc((100% - 2 * var(--space-3)) / 3);
		margin-inline: auto;
	}
}

/* --- The refine rail, as real category navigation --- */

.indo-refine--terms .indo-refine__options {
	list-style: none;
	margin: 0;
	padding: 0;
}
.indo-refine--terms .indo-refine__options li { margin: 0; }

.indo-refine__link {
	display: block;
	padding: 9px 0;
	font-size: var(--fs-small);
	color: var(--indo-charcoal);
	text-decoration: none;
	border-bottom: 1px solid var(--border-1);
	transition: color var(--dur-base) var(--easing);
}
.indo-refine__link:hover,
.indo-refine__link:focus-visible { color: var(--accent); }

.indo-refine__link--up {
	color: var(--indo-gray-text);
	font-weight: var(--w-body-medium);
}
.indo-refine__link--up::before {
	content: '\2190';
	margin-right: 8px;
}

@media (max-width: 1024px), (pointer: coarse) {
	/* 40px at 768 (go-live audit catalogue-18). */
	.indo-refine__link {
		display: flex;
		align-items: center;
		min-height: var(--tap-min);
	}
}

/*
 * On a phone the rail folds behind one "Refine by category" button, so the
 * first product reaches the first screen (catalogue-19: the open list pushed
 * it below 812px). refine-terms.php renders the button hidden and the list
 * open; catalogue.js unhides the button, marks the rail .is-collapsible and
 * folds it, so without JavaScript the links simply stay visible. The panel
 * stays in the flow under its button inside the position: relative rail.
 */
.indo-refine__toggle { display: none; }

@media (max-width: 600px) {
	.indo-refine.is-collapsible .indo-refine__head { display: none; }
	.indo-refine.is-collapsible .indo-refine__toggle {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: var(--space-1);
		width: 100%;
		min-height: var(--tap-min);
		padding: 0 var(--space-1);
		border: 1px solid var(--border-3);
		border-radius: var(--radius);
		background: var(--bg);
		font-family: var(--font-body);
		font-size: var(--fs-small);
		font-weight: var(--w-body-bold);
		color: var(--indo-charcoal);
		cursor: pointer;
	}
	.indo-refine__toggle svg { transition: transform var(--dur-base) var(--easing); }
	.indo-refine.is-open .indo-refine__toggle svg { transform: rotate(180deg); }
	.indo-refine.is-collapsible:not(.is-open) .indo-refine__group { display: none; }
	.indo-refine.is-collapsible .indo-refine__group { margin: var(--space-1) 0 0; }
}


/* --- Product cards on the index and the archives ---
   The foot ("View the product") sits on the card's bottom edge, so it lines
   up across a row however long each blurb is (go-live audit catalogue-26:
   feet at y 764 to 884 in one row). The card is already a flex column; its
   body has to be one too for the foot's margin-top: auto to push. */
.indo-card--catalogue .indo-card__body,
.indo-card--product .indo-card__body {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}
.indo-card--catalogue .indo-card__foot,
.indo-card--product .indo-card__foot { margin-top: auto; }

/* The archive card's image band is the same white panel as the product
   gallery (components.css 2.29), with a hairline under it, so white-ground
   photographs and cut-outs sit alike (go-live audit catalogue-22). */
.indo-card--product .indo-card__media {
	background: var(--bg);
	border-bottom: 1px solid var(--border-1);
}
.indo-card--product .indo-card__media img {
	box-sizing: border-box;
	padding: 12px;
}

/* The blurb is up to three short points (indo_2027_product_card_blurb()),
   spans inside the card's <p>, each with a small square marker. */
.indo-card__blurb .indo-card__point {
	position: relative;
	display: block;
	padding-left: 15px;
}
.indo-card__blurb .indo-card__point + .indo-card__point { margin-top: 4px; }
.indo-card__blurb .indo-card__point::before {
	content: '';
	position: absolute;
	top: 0.72em;
	left: 0;
	width: 5px;
	height: 5px;
	background: var(--accent);
}


/* ============================================================
   4. Product family
   BUILD-SPEC 31
   ============================================================ */

.indo-family__rows > * + * { margin-top: 0; }

.indo-family__items .indo-catalogue-index__heading { margin-bottom: var(--space-2); }

/*
 * SkySync, rebuilt in the product page's language (final-desktop-02): an
 * overview of heading and lede beside the benefit list and the downloads,
 * then the body's subheaded lists as cards on the paper band. See
 * page-templates/product-family.php for where each string comes from.
 */
.indo-family__overview-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
	gap: var(--space-6);
	align-items: start;
}
.indo-family__title {
	margin: 0;
	font-size: var(--fs-40);
	line-height: var(--lh-display);
	overflow-wrap: anywhere;
	hyphens: manual;
}
.indo-family__lede {
	margin: var(--space-2) 0 0;
	max-width: var(--measure-lede);
	font-size: var(--fs-lede);
	line-height: 1.55;
	color: var(--fg-2);
}
.indo-family__points {
	margin: 0;
	padding: 0;
	list-style: none;
	color: var(--indo-charcoal);
}
.indo-family__points li {
	position: relative;
	margin: 0;
	padding: 12px 0 12px 22px;
	border-bottom: 1px solid var(--border-2);
	font-size: var(--fs-17);
	line-height: var(--lh-body);
}
.indo-family__points li:first-child { padding-top: 0; }
.indo-family__points li:first-child::before { top: calc(0.8em - 3px); }
.indo-family__points li::before {
	content: '';
	position: absolute;
	top: calc(12px + 0.8em - 3px);
	left: 0;
	width: 6px;
	height: 6px;
	background: var(--accent);
}
.indo-family__downloads { margin-top: var(--space-4); }
/* The body's other opening sentences, under the lede (fcat-qa-01). */
.indo-family__points--intro,
.indo-family__intro { margin-top: var(--space-3); }
.indo-family__points--intro li { color: var(--fg-2); }

.indo-family__cards {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-3);
}
.indo-family__cards--2,
.indo-family__cards--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.indo-family__card {
	min-width: 0;
	padding: var(--space-4) var(--space-3);
	border-top: 2px solid var(--accent);
	background: var(--bg);
}
/* The stored headings are capitals in some locales ("SOFTWARE",
   "STEUERUNG"): set as the site's eyebrow label, they read as a label
   style everywhere rather than as shouted headings. */
.indo-family__cardtitle {
	margin: 0 0 var(--space-2);
	font-family: var(--font-body, inherit);
	font-size: var(--fs-meta);
	font-weight: var(--w-body-bold);
	line-height: 1.4;
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--accent-text);
	overflow-wrap: break-word;
}
.indo-family__points--card li {
	padding-block: 10px;
	font-size: var(--fs-body, 16px);
}
.indo-family__points--card li:last-child { border-bottom: 0; padding-bottom: 0; }
.indo-family__points--card li::before { top: calc(10px + 0.8em - 3px); }

@media (max-width: 1024px) {
	.indo-family__overview-grid { gap: var(--space-4); }
	.indo-family__cards { gap: var(--space-2); }
	.indo-family__card { padding: var(--space-3) var(--space-2); }
}
@media (max-width: 820px) {
	.indo-family__overview-grid,
	.indo-family__cards,
	.indo-family__cards--2,
	.indo-family__cards--4 { grid-template-columns: minmax(0, 1fr); }
	.indo-family__overview-grid { gap: var(--space-3); }
	.indo-family__title { font-size: var(--fs-32, 32px); }
}
@media (max-width: 600px) {
	.indo-family__title { font-size: var(--fs-28); }
	.indo-family__points li { font-size: var(--fs-body, 16px); }
}


/* ============================================================
   5. Gear trays
   BUILD-SPEC 12
   ============================================================ */

/*
   The compatibility list is 94 lantern names. One column is a scroll;
   the point of the list is that a reader can scan it for their own
   lantern, so it sets in columns and never breaks a name across two.
*/
.indo-geartrays__compat ul {
	columns: 3;
	column-gap: var(--space-4);
	list-style: none;
	margin: var(--space-2) 0 0;
	padding: 0;
}
.indo-geartrays__compat li {
	break-inside: avoid;
	margin: 0 0 7px;
	font-size: var(--fs-small);
	color: var(--indo-charcoal);
}
.indo-geartrays__compat li p { margin: 0; }

/* The stored body opens with its own h4. It is this section's heading,
   so it reads as one. */
.indo-geartrays__compat h4 {
	margin: 0;
	padding-bottom: var(--space-1);
	border-bottom: 2px solid var(--indo-charcoal);
	font-size: var(--fs-micro);
	font-weight: var(--w-body-bold);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--accent);
}


/* ============================================================
   6. Document library
   BUILD-SPEC 24
   ============================================================ */

.indo-settabs {
	display: flex;
	gap: var(--space-1);
	flex-wrap: wrap;
	margin-bottom: var(--space-3);
}

.indo-doclib__lede {
	margin: 0 0 var(--space-3);
	max-width: var(--measure-lede);
}
.indo-doclib__lede p { margin: 0 0 var(--space-1); }
.indo-doclib__lede p:last-child { margin-bottom: 0; }

/*
   components.css sizes five fixed columns by nth-child. This table has
   as many columns as the page's own data, so the widths come off a
   custom property instead: the name column takes the slack and every
   other column sizes to its content.
*/
.indo-doctable--set { table-layout: auto; }
.indo-doctable--set .indo-doctable__cell { width: auto; }
.indo-doctable--set .indo-doctable__name { width: 100%; }
.indo-doctable--set .indo-doctable__cell:last-child { width: 1%; white-space: nowrap; }


/* ============================================================
   7. Troubleshooting
   BUILD-SPEC 26
   ============================================================ */

.indo-troubleshooting__lede { margin: 0 0 var(--space-3); }
.indo-troubleshooting__lede p { margin: 0 0 var(--space-1); }
.indo-troubleshooting__lede p:last-child { margin-bottom: 0; }

/*
   The single-body panel. components.css already styles
   .indo-accordion__panel; this only sets the prose inside it, because
   live's answers are paragraphs, lists and the occasional photograph
   rather than the two-term cause-and-remedy the component assumes.
*/
.indo-accordion__panel--prose > * { margin: 0 0 var(--space-1); }
.indo-accordion__panel--prose > *:last-child { margin-bottom: 0; }
.indo-accordion__panel--prose p,
.indo-accordion__panel--prose li {
	font-size: var(--fs-small);
	line-height: var(--lh-body);
	color: var(--indo-gray-text);
}
.indo-accordion__panel--prose ul,
.indo-accordion__panel--prose ol { padding-left: var(--space-2); }
.indo-accordion__panel--prose img {
	display: block;
	max-width: 100%;
	height: auto;
}
.indo-accordion__panel--prose a { color: var(--accent); }


/* ============================================================
   8. Spectrums
   BUILD-SPEC 25
   ============================================================ */

.indo-spectrumspage__lede {
	margin: 0 auto var(--space-5);
	max-width: var(--measure-lede);
	text-align: center;
}
.indo-spectrumspage__lede p { margin: 0 0 var(--space-1); }
.indo-spectrumspage__lede p:last-child { margin-bottom: 0; }

.indo-spectrums {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
	gap: var(--space-4);
}

.indo-spectrum {
	border: 1px solid var(--border-1);
	background: var(--bg);
	transition: border-color var(--dur-base) var(--easing);
}
.indo-spectrum:hover { border-color: var(--accent); }

.indo-spectrum__chart {
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: var(--bg-soft);
}
.indo-spectrum__chart img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.indo-spectrum__body { padding: var(--space-3) var(--space-2) var(--space-3); }

.indo-spectrum__name {
	margin: 0 0 var(--space-1);
	font-size: var(--fs-21);
	font-weight: var(--w-card-title);
	color: var(--indo-charcoal);
}

.indo-spectrum__copy p {
	margin: 0 0 12px;
	font-size: var(--fs-small);
	line-height: var(--lh-body);
	color: var(--indo-gray-text);
	/* Live sets text-align on each stored paragraph, alternating left and
	   right to match the mockup's zig-zag. In a card grid that reads as a
	   mistake, so the stored alignment is overridden. */
	text-align: left !important;
}
.indo-spectrum__copy p:last-child { margin-bottom: 0; }
.indo-spectrum__copy strong,
.indo-spectrum__copy b { color: var(--indo-charcoal); }


/* ============================================================
   9. UMSUG charge code lookup
   BUILD-SPEC 27. This restyles plugins/indo-umsug-lookup's own
   markup; the cascade itself is the plugin's and is untouched.
   ============================================================ */

.indo-umsug {
	margin: var(--space-3) 0;
	border: 1px solid var(--border-2);
	padding: var(--space-4) var(--space-3) var(--space-3);
	background: var(--bg);
}

.indo-umsug__row + .indo-umsug__row { margin-top: var(--space-3); }

/* The date row: a 280px control, its hint, and a rule under both. */
.indo-umsug__row:first-child {
	padding-bottom: var(--space-3);
	border-bottom: 1px solid var(--border-1);
}
.indo-umsug__row:first-child .indo-umsug__field { max-width: 280px; }

.indo-umsug__hint {
	margin: var(--space-1) 0 0;
	font-size: var(--fs-meta);
	color: var(--indo-gray-text);
}

.indo-umsug__field {
	display: block;
	min-width: 0;
}
.indo-umsug__field > span,
.indo-umsug__field legend {
	display: block;
	margin-bottom: 8px;
	font-size: var(--fs-small);
	font-weight: var(--w-body-medium);
	color: var(--indo-charcoal);
}

.indo-umsug__field input[type="date"],
.indo-umsug__field select {
	width: 100%;
	padding: 13px 14px;
	border: 1px solid var(--border-2);
	border-radius: 0;
	background: var(--bg);
	/* 16px is mandatory: anything smaller makes iOS zoom the page on
	   focus, which reads as a layout bug. */
	font-family: var(--font-body);
	font-size: 16px;
	color: var(--indo-charcoal);
	transition: border-color var(--dur-base) var(--easing);
}
.indo-umsug__field input[type="date"]:focus-visible,
.indo-umsug__field select:focus-visible { border-color: var(--accent); }
.indo-umsug__field select:disabled { color: var(--indo-gray-text); }

/* The four selects. */
.indo-umsug__form .indo-umsug__row:nth-child(2) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--space-2-5);
}

.indo-umsug fieldset {
	margin: 0;
	padding: 0;
	border: 0;
	min-width: 0;
}
.indo-umsug fieldset label {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin-right: var(--space-3);
	font-size: var(--fs-small);
	color: var(--indo-charcoal);
}

.indo-umsug__actions {
	display: flex;
	gap: var(--space-1);
	flex-wrap: wrap;
	padding-top: var(--space-1);
}

.indo-umsug__submit,
.indo-umsug__reset {
	border-radius: 0;
	border: 1px solid transparent;
	padding: 15px 30px;
	font-family: var(--font-body);
	font-size: var(--fs-body);
	font-weight: var(--w-body-medium);
	cursor: pointer;
	transition: background-color var(--dur-base) var(--easing);
}
.indo-umsug__submit {
	background: var(--accent);
	border-color: var(--accent);
	color: var(--indo-white);
}
.indo-umsug__submit:hover,
.indo-umsug__submit:focus-visible { background: var(--accent-hover); border-color: var(--accent-hover); }
.indo-umsug__reset {
	background: none;
	border-color: var(--border-2);
	color: var(--indo-charcoal);
}
.indo-umsug__reset:hover,
.indo-umsug__reset:focus-visible { background: var(--bg-soft); }

/* The result panel. */
.indo-umsug__result {
	margin-top: var(--space-3);
	padding: var(--space-3) var(--space-3);
	background: var(--bg-dark);
	color: var(--fg-on-dark);
}
.indo-umsug__result-title {
	margin: 0 0 var(--space-2);
	font-size: var(--fs-micro);
	font-weight: var(--w-body-bold);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--accent);
}
.indo-umsug__result-grid {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: var(--space-1) var(--space-4);
	align-items: center;
	margin: 0;
}
.indo-umsug__result-grid dt {
	font-size: var(--fs-meta);
	text-transform: uppercase;
	letter-spacing: var(--tracking-eyebrow-sm);
	color: var(--fg-on-dark-3);
}
.indo-umsug__result-grid dd { margin: 0; }
.indo-umsug__code {
	font-family: var(--font-numeric);
	font-size: var(--fs-38);
	font-weight: var(--w-numeric);
	color: var(--fg-on-dark);
	cursor: pointer;
}
.indo-umsug__code--alt { font-size: var(--fs-26); color: var(--fg-on-dark-2); }
.indo-umsug__photo-label,
.indo-umsug__copy-hint {
	font-size: var(--fs-meta);
	color: var(--fg-on-dark-3);
}
.indo-umsug__copy-hint { margin: var(--space-2) 0 0; }

.indo-umsug__error {
	margin-top: var(--space-2);
	padding: var(--space-2);
	border-left: 3px solid var(--accent);
	background: var(--bg-soft);
	font-size: var(--fs-small);
	color: var(--indo-charcoal);
}

.indo-umsug__footnote {
	margin: var(--space-3) 0 0;
	font-size: var(--fs-meta);
	color: var(--indo-gray-text);
}
.indo-umsug__footnote a { color: var(--accent); }


/* ============================================================
   10. Responsive: 1024, 900, 820, 600
   ============================================================ */

@media (max-width: 1024px) {
	.indo-spectrums { grid-template-columns: minmax(0, 1fr); }
	.indo-geartrays__compat ul { columns: 2; }
}

@media (max-width: 900px) {
	/*
	   The wide data grid scrolls sideways rather than stacking: a
	   document table whose rows reflow into blocks loses the column
	   that says which version each document is. The wrapper already
	   carries tabindex and a label, so the scroll region is reachable
	   from the keyboard.
	*/
	.indo-doctable__scroll { overflow-x: auto; }
	.indo-doctable--set { min-width: 560px; }
}

@media (max-width: 820px) {
	.indo-product__grid {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--space-4);
	}
	.indo-product__title { font-size: var(--fs-40); }

	.indo-catalogue-body__split {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--space-3);
	}
	.indo-catalogue-head__title { font-size: var(--fs-38); }

	/* The rail sits above the grid, so it reads as a filter row. */
	.indo-refine--terms .indo-refine__options {
		display: flex;
		flex-wrap: wrap;
		gap: 0 var(--space-3);
	}
	.indo-refine__link { border-bottom: 0; }

	.indo-umsug__form .indo-umsug__row:nth-child(2) { grid-template-columns: minmax(0, 1fr); }
	.indo-umsug__code { font-size: var(--fs-32); }
}

@media (max-width: 600px) {
	/*
	 * On a phone the product trail lost its last crumb to a second line that
	 * began with a separator (catalogue-24). The current page is the H1 just
	 * below, so a trail of three or more drops it here and fits one line.
	 */
	.indo-product__crumbs .indo-breadcrumb li:nth-last-child(2):nth-child(n+2) .indo-breadcrumb__sep { display: none; }

	/*
	 * One row in every locale (final-locales-11, fm-22): the German, Italian
	 * and Spanish trails wrapped to three rows at 375 ("Startseite /
	 * Außenbeleuchtung /" then "Autobahnbeleuchtung" alone). On a phone the
	 * trail shows Home, an ellipsis and the parent category, and the parent
	 * truncates with an ellipsis if even that is too long. The middle crumbs
	 * and the current page are hidden visually only, so a screen reader still
	 * hears the whole trail; the ellipsis has empty alternative text.
	 */
	.indo-product__crumbs .indo-breadcrumb {
		flex-wrap: nowrap;
		min-width: 0;
	}
	.indo-product__crumbs .indo-breadcrumb li { flex: 0 0 auto; }
	.indo-product__crumbs .indo-breadcrumb li:nth-child(n+2):nth-last-child(n+3),
	.indo-product__crumbs .indo-breadcrumb li:last-child:nth-child(n+3) {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}
	.indo-product__crumbs .indo-breadcrumb li:nth-last-child(2):nth-child(n+2) {
		flex: 0 1 auto;
		min-width: 0;
	}
	.indo-product__crumbs .indo-breadcrumb li:nth-last-child(2):nth-child(n+3)::before {
		content: '\2026\00a0\00a0/';
		content: '\2026\00a0\00a0/' / '';
		flex: 0 0 auto;
		color: var(--indo-gray);
	}
	.indo-product__crumbs .indo-breadcrumb li:nth-last-child(2):nth-child(n+2) a {
		display: block;
		min-width: 0;
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
		line-height: var(--tap-min);
	}

	.indo-product__title { font-size: var(--fs-30); }
	.indo-catalogue-head__title { font-size: var(--fs-28); }

	/* fm-16: one column ran the 93 lanterns to about 110 lines and 3,000px.
	   Two columns still avoid breaking a name mid-word (break-inside: avoid
	   above) and roughly halve the scroll. */
	.indo-geartrays__compat ul { columns: 2; column-gap: var(--space-2); }

	/*
	 * fm-16: one column ran the category archive and /product-list/ to
	 * 11,960px for 19 products, each card a full-width strip with a small
	 * cut-out in a wide well. Two-up keeps the image legible (contain, on
	 * its own white panel) and the title at one line for every product
	 * name checked (measured: AIR2, ELEMENT, TopLink, Belisha Beacon
	 * Crossing LED Lamps at 20px in a ~163px column wraps to 2 lines,
	 * which .indo-card's flex body and foot-at-bottom already handle).
	 */
	.indo-productgrid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--space-2);
	}
	.indo-productgrid > :last-child:nth-child(odd) {
		grid-column: 1 / -1;
		max-width: calc((100% - var(--space-2)) / 2);
		margin-inline: auto;
	}
	.indo-card--product .indo-card__media { height: 120px; }
	.indo-card--product .indo-card__body { padding: var(--space-1-25) var(--space-1); }
	.indo-card--product .indo-card__title { font-size: var(--fs-17); }
	.indo-card--product .indo-card__spec { display: none; }

	.indo-catalogue-index__grid { grid-template-columns: minmax(0, 1fr); }

	/* The auto 1fr result row stacks. It previously left a 119px value
	   column at 390px, and it must keep stacking. */
	.indo-umsug__result-grid {
		grid-template-columns: minmax(0, 1fr);
		gap: 14px;
	}
	.indo-umsug__code { font-size: var(--fs-32); }

	/* 44px tap targets. */
	.indo-umsug__field input[type="date"],
	.indo-umsug__field select,
	.indo-umsug__submit,
	.indo-umsug__reset,
	.indo-umsug fieldset label,
	.indo-doctable__link {
		min-height: var(--tap-min);
	}
	.indo-umsug__submit,
	.indo-umsug__reset { width: 100%; }
	.indo-settabs .indo-chip { min-height: var(--tap-min); }
}
