/* ==========================================================================
   Institutional page furniture — the corporate hub and its spokes.

   Structure lives in Elementor so Omer can move and rewrite anything. The
   LOOK lives here so the three institutional pages cannot drift apart, and
   so a careless drag in the page builder cannot destroy the design.

   Every rule is scoped to .tot-inst, which each top-level Elementor container
   carries as a CSS class. It deliberately does NOT rely on a body class: a
   theme switch or a page-template change can drop that, and the page would
   lose its entire design with nothing to explain why.

   Note the two selector shapes. A class on the scope element itself needs
   `.tot-inst.i-hero`; a class on something inside it needs `.tot-inst .i-card`.
   Getting that wrong silently matches nothing.

   Palette is the plugin's own tokens from tot.css. The yellow is used as a
   FIELD carrying navy text rather than as a hairline: research on B2B and
   institutional design is consistent that high-chroma yellow reads as
   professional at 10-30% coverage against anthracite, and reads childish as
   a thin accent on a dark gradient.
   ========================================================================== */

.tot-inst {
	--i-ink: var(--tot-ink, #1b252f);
	--i-ink-2: #2a3746;
	--i-yellow: var(--tot-yellow, #f8f812);
	--i-paper: var(--tot-paper, #ffffff);
	--i-paper-2: #f0f0f0;
	--i-line: #d5d9de;
	/* One value per role. inst.css and trust.css previously aliased the same tokens to
	   DIFFERENT fallbacks (#4c5665 vs #1f2937 for body, #6e7885 vs #666666 for muted), and since
	   tot.css only loads with [tot_directory] the fallbacks are what actually render: two body
	   greys and two muted greys on the same page. Measured, not theorised. */
	--i-body: var(--tot-body, #1f2937);
	--i-body-strong: #1b252f;
	--i-muted: var(--tot-muted, #666666);
	--i-on-ink: #ffffff;
	--i-on-ink-2: #b9c3ce;
	--i-display: var(--tot-display, "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif);
	--i-label: var(--tot-label, Oswald, "Helvetica Neue", Helvetica, Arial, sans-serif);
}

/* ---------- labels ---------- */
.tot-inst .i-lab,
.tot-inst .i-lab * {
	font-family: var(--i-label);
	font-size: 0.82rem;
	font-weight: 700;
	letter-spacing: 0.11em;
	text-transform: uppercase;
	color: var(--i-muted);
	margin: 0;
}

/* ---------- hero ---------- */
.tot-inst.i-hero {
	background-color: var(--i-ink);
	color: var(--i-on-ink);
}

.tot-inst.i-hero .elementor-heading-title,
.tot-inst.i-hero h1 {
	color: var(--i-on-ink);
}

.tot-inst.i-hero .i-lab,
.tot-inst.i-hero .i-lab * {
	color: var(--i-yellow);
}

.tot-inst.i-hero p {
	color: var(--i-on-ink-2);
}

/* The trust row. A bordered yellow frame rather than four floating tiles:
   it reads as one credential block, which is what a procurement reader is
   looking for above the fold. */
.tot-inst .i-proof {
	border: 2px solid var(--i-yellow);
}

.tot-inst .i-proof > * {
	border-right: 1px solid rgba(248, 248, 18, 0.35);
}

.tot-inst .i-proof > *:last-child {
	border-right: 0;
}

.tot-inst .i-proof strong {
	display: block;
	font-family: var(--i-display);
	font-weight: 800;
	/* Scales with the 1520 shell; at 1140 it stayed at the old flat 1.2rem. */
	font-size: clamp(1.2rem, 1.45vw, 1.5rem);
	color: var(--i-yellow);
	line-height: 1.1;
	font-variant-numeric: tabular-nums;
}

.tot-inst .i-proof span {
	display: block;
	font-size: 0.88rem;
	color: var(--i-on-ink-2);
	line-height: 1.35;
	margin-top: 0.15rem;
}

/* ---------- buttons ---------- */
.tot-inst .i-cta .elementor-button {
	font-family: var(--i-label);
	font-size: 0.86rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	border-radius: 0;
	border: 2px solid var(--i-yellow);
	background-color: var(--i-yellow);
	color: var(--i-ink);
	padding: 0.85rem 1.35rem;
}

/* Scoped to the dark grounds on purpose. Unscoped, this rule renders yellow on white at 1.14:1
   the moment anyone drops an .i-cta button into a plain section: an invisible button. */
.tot-inst.i-hero .i-cta .elementor-button:hover,
.tot-inst.i-band .i-cta .elementor-button:hover {
	background-color: transparent;
	color: var(--i-yellow);
}

.tot-inst .i-cta .elementor-button:hover {
	background-color: var(--i-ink);
	color: var(--i-yellow);
	border-color: var(--i-ink);
}

.tot-inst .i-cta-ghost .elementor-button {
	background-color: transparent;
	color: var(--i-on-ink);
	border-color: #9aa8ba;
}

.tot-inst .i-cta-ghost .elementor-button:hover {
	border-color: var(--i-on-ink);
	background-color: transparent;
}

/* ---------- card grids ---------- */
.tot-inst .i-grid {
	border: 1px solid var(--i-line);
	background: var(--i-line);
	gap: 1px !important;
}

.tot-inst .i-card {
	background: var(--i-paper);
	padding: 1.15rem;
}

.tot-inst .i-card h3,
.tot-inst .i-day-item h3,
.tot-inst .i-card .elementor-heading-title {
	font-family: var(--i-display);
	font-size: 1.15rem;
	line-height: 1.3;
	font-weight: 700;
	color: var(--i-ink);
	margin: 0 0 0.35rem;
}

.tot-inst .i-card p {
	font-size: 1rem;
	line-height: 1.55;
	color: var(--i-body);
	margin: 0;
}

/* A lane marker. Words carry the meaning, colour only reinforces it:
   institutional accessibility guidance is explicit that meaning must never
   be conveyed by colour alone. */
.tot-inst .i-lane {
	display: inline-block;
	font-family: var(--i-label);
	font-size: 0.6rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	padding: 0.18rem 0.45rem;
	border: 1.5px solid var(--i-muted);
	color: var(--i-muted);
	margin-bottom: 0.5rem;
}

.tot-inst .i-lane--open {
	background: var(--i-yellow);
	border-color: var(--i-yellow);
	color: var(--i-ink);
}

/* ---------- the dark figures band ---------- */
.tot-inst.i-band {
	background-color: var(--i-ink);
	color: var(--i-on-ink);
}

.tot-inst.i-band .elementor-heading-title,
.tot-inst.i-band h2 {
	color: var(--i-on-ink);
}

.tot-inst.i-band p {
	color: var(--i-on-ink-2);
}

.tot-inst .i-figs {
	border: 1px solid var(--i-ink-2);
	background: var(--i-ink-2);
	gap: 1px !important;
}

.tot-inst .i-fig {
	background: var(--i-ink);
	padding: 1.1rem 0.9rem;
}

.tot-inst .i-fig strong {
	display: block;
	font-family: var(--i-display);
	font-weight: 800;
	font-size: clamp(1.7rem, 3.4vw, 2.3rem);
	color: var(--i-yellow);
	line-height: 1;
	font-variant-numeric: tabular-nums;
}

.tot-inst .i-fig span {
	display: block;
	font-size: 0.76rem;
	color: var(--i-on-ink-2);
	margin-top: 0.35rem;
	line-height: 1.4;
}

/* ---------- numbered process ---------- */
.tot-inst .i-step-n {
	display: inline-block;
	font-family: var(--i-label);
	font-weight: 700;
	font-size: 0.7rem;
	letter-spacing: 0.08em;
	background: var(--i-yellow);
	color: var(--i-ink);
	padding: 0.14rem 0.42rem;
	margin-bottom: 0.4rem;
}

/* ---------- closing band ---------- */
.tot-inst.i-close {
	background-color: var(--i-yellow);
	color: var(--i-ink);
}

.tot-inst.i-close .elementor-heading-title,
.tot-inst.i-close h2,
.tot-inst.i-close p {
	color: var(--i-ink);
}

.tot-inst.i-close .i-lab,
.tot-inst.i-close .i-lab * {
	color: #4a5460;
}

.tot-inst.i-close .i-cta .elementor-button {
	background-color: var(--i-ink);
	border-color: var(--i-ink);
	color: var(--i-yellow);
}

.tot-inst.i-close .i-cta .elementor-button:hover {
	background-color: transparent;
	color: var(--i-ink);
}

/* Trust signals repeated beside the closing call to action, which is the
   research finding that one should sit within view of every major CTA. */
.tot-inst .i-close-proof {
	border-top: 2px solid rgba(27, 37, 47, 0.35);
	padding-top: 0.9rem;
	margin-top: 1.4rem;
	font-size: 0.9rem;
	font-weight: 700;
	color: #2e3742;
}

/* ---------- theme reset ----------
   Elementor's own kit CSS emits `.elementor-widget-heading .elementor-heading-title`
   at specificity (0,2,0). The first attempt here used `.tot-inst h2` (0,1,1) and
   `.tot-inst .elementor-heading-title` (0,2,0), which LOSE and TIE respectively —
   and the tie went to Elementor, because this stylesheet was being printed before
   elementor-frontend. Measured: every section heading computed rgb(110,193,228),
   Elementor's primary, not the brand navy.

   Two changes fixed it together. The selector below is (0,3,0) so it wins on
   specificity rather than on luck, and the enqueue moved to priority 100 with a
   dependency on elementor-frontend so source order stops working against us. */
.tot-inst h1,
.tot-inst h2,
.tot-inst h3,
.tot-inst .elementor-widget-heading .elementor-heading-title {
	color: var(--i-ink);
	font-family: var(--i-display);
}

.tot-inst.i-hero h1,
.tot-inst.i-hero h2,
.tot-inst.i-hero h3,
.tot-inst.i-hero .elementor-heading-title,
.tot-inst.i-band h2,
.tot-inst.i-band .elementor-heading-title {
	color: var(--i-on-ink);
}

.tot-inst.i-close h2,
.tot-inst.i-close .elementor-heading-title {
	color: var(--i-ink);
}

/* Section headings want room above them that Elementor's default zero margin
   does not give, and the theme's own h2 margin is removed by Elementor. */
.tot-inst h2.elementor-heading-title {
	/* Ceiling raised for the 1520 shell. At the old 2.05rem the H2 rendered 32.8px, which was
	   LARGER than the unstyled H1 above it. */
	font-size: clamp(1.5rem, 2.6vw, 2.55rem);
	line-height: 1.15;
	margin: 0.15rem 0 0.6rem;
}

.tot-inst .i-lab {
	margin-bottom: 0.35rem;
}

/* Paragraphs in a plain white section inherited Elementor's --e-global-color-text, #7a7a7a,
   which measures 4.29:1 and fails AA. Only the four coloured-section variants were setting a
   colour, so every paragraph outside them fell through. (0,1,1); the variants are all (0,2,1)
   or better and keep winning. */
.tot-inst p {
	color: var(--i-body);
}

/* The accordion titles were the worst contrast on the page and they sit in the compliance
   section a procurement reader actually reads: #61ce70 when open and #6ec1e4 when closed, both
   on white, measuring 1.99:1 and 2.02:1. Elementor's own rule is (0,2,0), so this is (0,3,0). */
.tot-inst .elementor-widget-accordion .elementor-accordion-title,
.tot-inst .elementor-widget-accordion .elementor-active .elementor-accordion-title {
	color: var(--i-ink);
	font-family: var(--i-display);
}

/* ---------- layout ----------
   Elementor gives every child container width:100% by default, so a row of
   cards stacks. Rather than set a width on each one in the builder, which is
   six places to get wrong and six places Omer could accidentally change, the
   flex behaviour is declared once here. `e-con` is Elementor's own class for
   a container element.

   flex-basis rather than a fixed width, so the rows reflow on narrow screens
   without a media query per grid. */
.tot-inst .i-grid > .e-con {
	flex: 1 1 15rem;
	width: auto;
}

.tot-inst .i-proof > .elementor-widget {
	flex: 1 1 9rem;
	width: auto;
	padding: 0.75rem 0.9rem;
}

.tot-inst .i-figs > .e-con {
	flex: 1 1 7rem;
	width: auto;
}

.tot-inst .i-cta-row > .elementor-widget {
	width: auto;
	flex: 0 0 auto;
}

@media (max-width: 600px) {
	/* At 375px the five figures wrapped 2 + 2 + 1, leaving the fifth spanning the full width
	   alone against a 1px seam grid. Two clean columns instead. */
	.tot-inst .i-figs > .e-con {
		flex: 1 1 45%;
	}

	/* The proof row's separator landed immediately inside the 2px yellow frame once it wrapped to
	   two columns, because :last-child only clears the fourth item. */
	.tot-inst .i-proof > .elementor-widget:nth-child(2n) {
		border-right: 0;
	}
}

/* The trust panel needs the same page gutter as everything above it. */
.tot-inst .tot-trust {
	margin-top: 0.25rem;
}

/* ==========================================================================
   CONGRESS SPOKE — /services/corporate/congress-programs/

   Appended for the first Phase 2 spoke. Everything here is new class names,
   so nothing above changes and the hub page is unaffected. Reused as-is from
   above: .i-grid, .i-card, .i-lab, .i-cta, .i-lane, .i-band, .i-close.

   🔴 The hero does NOT reuse .i-hero. That class paints an ink background and
   forces white headings, which is right for the hub and would put white text
   on a white ground here. The spoke hero is deliberately light and
   two-column, so the two pages cannot be mistaken for each other. It is a
   separate class for that reason, not by oversight.
   ========================================================================== */

/* ---------- the row direction the grids always assumed ----------
   🔴 Elementor 4 containers default to `flex-direction: column`, so every `.i-grid` and `.i-figs`
   on this page stacked into one column: the three shapes, the six inclusions, the two boundary
   cards and the three figures, all full width, one under another.

   The layout section further down already sets `flex: 1 1 15rem` on `.i-grid > .e-con` and
   `flex: 1 1 7rem` on `.i-figs > .e-con`, which only means anything in a row. So the direction was
   the missing half of a rule that was already half written, not a new opinion about layout.

   Declared here rather than per container in the builder because that is six places to set and six
   places for it to be lost on an edit. `wrap` so a narrow screen still reflows without a media
   query per grid. Elementor's own `.e-con` rule is a single class, so this wins on specificity,
   and anything set explicitly in the builder emits a higher-specificity per-element rule and still
   beats it. */
.tot-inst .i-grid,
.tot-inst .i-figs,
.tot-inst .i-cta-row {
	flex-direction: row;
	flex-wrap: wrap;
}

/* ==========================================================================
   IMAGERY — the hero loop and the picture slots

   Both follow the guide rail's rule: an empty slot HIDES rather than shipping
   a placeholder. Omer fills these himself on the live site, and a grey
   Elementor placeholder or a broken image icon on a procurement page is worse
   than no picture at all. In the Elementor editor the slots are still visible
   and editable, so hiding them on the front end costs him nothing.
   ========================================================================== */

/* ---------- hero loop ----------
   A background video with a CSS scene behind it. The scene is not a nicety:
   it is what shows until the MP4 exists, and it stays as the poster-coloured
   ground behind the video on a slow connection, so the hero is never a white
   rectangle waiting on a download.

   Spec carried from doc 35 section 5, unchanged: 6 seconds, seamless loop,
   under 2 MB, H.264, muted, poster frame set, and POSTER ONLY ON MOBILE. A
   hero video is decoration and it must never cost a phone user the download. */
.tot-inst .i-loop {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	padding: 0 !important;
	pointer-events: none;
	/* Elementor caps every container at the kit's content width and centres it, so `inset: 0`
	   alone gave a 1140px band floating inside a 1440px hero with the brand navy showing down
	   both sides. A background layer has to ignore the content measure. */
	max-width: none !important;
	width: auto;
	margin: 0 !important;
}

/* The scrim. Without it the headline sits on whatever frame the video happens to be showing, and
   contrast becomes a matter of luck. Weighted to the left because the words are left-aligned. */
.tot-inst .i-loop::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 2;
	background: linear-gradient(100deg, rgba(13, 20, 27, 0.95) 0%, rgba(13, 20, 27, 0.82) 52%, rgba(13, 20, 27, 0.45) 100%);
}

.tot-inst .i-loop::after {
	content: "";
	position: absolute;
	z-index: 0;
	inset: -12%;
	background: radial-gradient(46% 58% at 68% 38%, rgba(110, 193, 228, 0.22), transparent 70%);
	animation: i-loop-pan 42s ease-in-out infinite alternate;
}

@keyframes i-loop-pan {
	from { transform: scale(1.04) translate3d(-1%, 0, 0); }
	to   { transform: scale(1.12) translate3d(2%, -1%, 0); }
}

@media (prefers-reduced-motion: reduce) {
	.tot-inst .i-loop::after { animation: none; }
}

.tot-inst .i-loop video {
	position: absolute;
	inset: 0;
	z-index: 1;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Reduced motion and small screens both fall back to the poster frame, which
   the video element paints on its own once `poster` is set. */
@media (prefers-reduced-motion: reduce) {
	.tot-inst .i-loop video { display: none; }
}

@media (max-width: 767px) {
	.tot-inst .i-loop video { display: none; }
}

/* A still image in the same loop slot, for any hero that wants a photo instead of a video.
   Same cover treatment, but it STAYS on mobile and under reduced motion: the video rules above
   exist to save a phone the download and the movement, and a still image costs neither. */
.tot-inst .i-loop img {
	position: absolute;
	inset: 0;
	z-index: 1;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* ---------- the day, as a timeline ----------
   Built for the CSR spoke, whose product is one school day. The day reads top to bottom as an
   itinerary rather than as a card grid, which is also what separates the page from its
   university sibling at a glance. No new vocabulary: the spine is the aside's 2px line, the
   stage chips are the same .i-step-n the shape cards carry, the dot is the accent yellow. */
.tot-inst .i-day {
	border-left: 2px solid var(--i-line);
	padding-left: 2rem;
	display: grid;
	gap: 2.4rem;
	/* 70rem, not 46: every step now carries its own picture slot on the right, so the column
	   is a two-column composition rather than a bare measure. */
	max-width: 70rem;
}

/* Each step is words beside a small picture slot. The slot reuses .i-media, so it crops 4/3,
   shows Omer the dashed drop zone while empty, and hides from guests until a picture lands. */
.tot-inst .i-day-item {
	position: relative;
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1.2rem 2rem;
}

.tot-inst .i-day-item > .e-con:first-child {
	flex: 1 1 26rem;
	max-width: 46rem;
}

.tot-inst .i-day-item > .i-media {
	flex: 1 1 13rem;
	max-width: 18rem;
	margin: 0;
}

.tot-inst .i-day-item::before {
	content: "";
	position: absolute;
	/* centre the dot on the 2px spine: container padding 2rem + border 2px, dot 12px wide */
	left: calc(-2rem - 7px);
	top: 0.3rem;
	width: 12px;
	height: 12px;
	border-radius: 50%;
	background: var(--i-yellow);
	border: 2px solid var(--i-ink);
}

.tot-inst .i-day-item h3 {
	margin: 0.5rem 0 0.4rem;
}

/* ---------- picture slots beside prose ----------
   A two-column row: words on one side, picture on the other. `--flip` puts the
   picture first so consecutive rows alternate rather than marching down one
   edge, which is the difference between a designed page and a template. */
.tot-inst .i-media-row {
	flex-direction: row;
	flex-wrap: wrap;
	/* 🔴 flex-start, not center. Centred, the SHORTER column floats in the middle of the row and
	   leaves its dead space at the bottom: measured 115 to 183px below the last line of the aside,
	   which is most of what Omer was reading as "too much vertical gap". The section padding was
	   only 27px of it. The two columns now start level, which is also what a reader expects of a
	   text column and the note beside it. */
	align-items: flex-start;
	gap: 2rem !important;
}

@media (min-width: 860px) {
	.tot-inst .i-media-row > .e-con {
		flex: 1 1 20rem;
		width: auto;
	}

	.tot-inst .i-media-row--flip {
		flex-direction: row-reverse;
	}
}

/* The slot itself.
   🔴 Empty, it is INVISIBLE to a guest and VISIBLE to anyone logged in. Omer could not find the
   slots because the first version hid them from everybody, which protected the live page and made
   them useless to the person who has to fill them. WordPress puts `logged-in` on the body, so the
   drop zone shows for an editor and never for a visitor. */
/* 🔴 A standalone slot needs a ceiling. As a direct section child (outside any .i-media-row and
   outside .i-day), nothing capped the slot, and `width: 100%` + `aspect-ratio: 4/3` rendered a
   1500 by 1125 placeholder that filled the whole shell — measured on the university and CSR
   pages, 17 Aug 2026. 26rem matches the media-row rail cap, so a slot is the same size wherever
   it stands. Row and timeline rules below set their own tighter flex caps and still win. */
.tot-inst .i-media {
	max-width: 26rem;
}

/* A slot standing alone in a section (a direct child of the boxed inner, outside any row)
   gets the same 36rem the bare rails carry, so "a big slot" is one size everywhere. At the
   26rem safety cap above, the two standalone slots (university, CSR) floated small against a
   thousand pixels of empty shell — the same fault Omer flagged on the event rails. Wrapped
   rails inside rows deliberately stay at 26rem: their aside fills the rail below the picture,
   and widening them re-creates the rail-heavy row imbalance fixed 16 Aug. */
.tot-inst .e-con-inner > .i-media {
	max-width: 36rem;
}

.tot-inst .i-media:not(:has(img)) {
	display: none;
}

body.logged-in .tot-inst .i-media:not(:has(img)),
body.logged-in .tot-inst .i-card-media:not(:has(img)) {
	display: block;
	min-height: 9rem;
	border: 2px dashed var(--i-muted);
	background: repeating-linear-gradient(135deg, transparent, transparent 9px, rgba(0, 0, 0, 0.04) 9px, rgba(0, 0, 0, 0.04) 18px);
	position: relative;
	/* 🔴 Undo any scroll motion on an EMPTY slot, for the editor only.
	   The congress spoke's two-column rows carry a scrolling effect on both halves, and the second
	   half IS this slot. While empty it is `display: none`, so Elementor's observer never resolves
	   it and the inline opacity stays at 0. Logged in, the rule above flips it back to `display:
	   block` and the drop zone would then be a fully transparent box: present, sized, and
	   invisible. That is precisely the failure the comment above records fixing, arriving a second
	   time by a different route. A filled slot is unaffected, because `:not(:has(img))` stops
	   matching the moment a picture lands and the effect animates it in like the other half. */
	opacity: 1 !important;
	transform: none !important;
}

body.logged-in .tot-inst .i-media:not(:has(img))::after,
body.logged-in .tot-inst .i-card-media:not(:has(img))::after {
	content: "Picture slot. Drop an Image widget here. Only you can see this.";
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	padding: 0.9rem;
	text-align: center;
	font-family: var(--i-label);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--i-muted);
}

.tot-inst .i-media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

/* A picture inside a card sits above the copy and spans the padding, so the
   card reads as one object rather than a photo pasted into a box. */
.tot-inst .i-card-media:not(:has(img)) {
	display: none;
}

body.logged-in .tot-inst .i-card-media:not(:has(img)) {
	min-height: 6rem;
	margin: -1.15rem -1.15rem 0.9rem;
}

.tot-inst .i-card-media img {
	display: block;
	width: calc(100% + 2.3rem);
	margin: -1.15rem -1.15rem 0.9rem;
	max-width: none;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

/* ---------- editorial links ----------
   🔴 Omer, 16 Aug 2026: the links here did not look like the links anywhere else on the site.
   He was right, and the old value was further from the site than it needed to be.

   MEASURED on theothertour.com this session, because the previous note in this very block was
   WRONG and is the reason to distrust a remembered number. It claimed the theme's link colour
   computed at 4.16:1. Sampled off 51 in-body links on a live page, the theme renders #6ec1e4,
   which is 2.02:1 against white — less than half of what 1.4.3 asks, not a near miss. Anyone
   re-checking this should re-measure rather than trust this paragraph either.

   #1d74a0 is that same sky blue darkened only as far as it has to go: 5.17:1, passes AA for
   body text, and still reads as the site's blue rather than as navy. The old #12556e passed at
   8.23:1 but had drifted into a different colour, which is exactly what Omer noticed.

   Bold plus a permanent underline is Omer's instruction and it earns its place: it carries the
   link without relying on colour at all, which is 1.4.1, and it is what the live site already
   does to its own links.

   The dark-section override is NOT decorative. #1d74a0 on the anthracite is 3.00:1 and fails,
   so the bands take #6ec1e4, which is 7.70:1 there — the site's literal link colour, used on the
   one ground where it is also the accessible one.

   🔴 Scoped to CLASS-LESS anchors deliberately. `.tot-inst a` also matches the CTA buttons, the
   guide cards and the cluster buttons, every one of which is an anchor carrying a class; bolding
   and underlining those would wreck them. All 38 editorial anchors across the two spokes are
   class-less today, and `:not([class])` is what separates the two populations. It is wrapped in
   `:where()` because :not([class]) otherwise counts as a CLASS for specificity and would outrank
   the components it exists to leave alone — the same trap that once had this file's own guard
   rule beating the components it was written to protect. */
.tot-inst {
	--i-link: #1d74a0;
	--i-link-on-ink: #6ec1e4;
}

.tot-inst a {
	color: var(--i-link);
}

.tot-inst :where(p, li, dd, dt, td, th, blockquote, figcaption) a:where(:not([class])) {
	font-weight: 700;
	text-decoration: underline;
	text-underline-offset: 0.15em;
	text-decoration-thickness: from-font;
}

.tot-inst.i-band a,
.tot-inst .i-brief a {
	color: var(--i-link-on-ink);
}

.tot-inst.i-close a {
	color: var(--i-ink);
}

/* ---------- the open card ----------
   The fourth card in a shapes grid is not a fourth shape, it is the escape hatch: "or none of
   these, tell us your dates". It is the one card that carries NO picture band, and it takes the
   yellow as a FIELD with navy on it so the difference reads at a glance rather than looking like
   a card whose image failed to load.

   Yellow as a field carrying navy text is the sheet's documented usage: high chroma yellow reads
   professional at 10-30% coverage and childish as a hairline. Navy on it measures 13.63:1, and
   the muted step label is lifted to 72% navy, which is 5.91:1 on the same ground where the
   standard --i-muted would have been 2.3:1. */
.tot-inst .i-card--open {
	background-color: var(--i-yellow);
}

.tot-inst .i-card--open h3,
.tot-inst .i-card--open p,
.tot-inst .i-card--open :where(p, li) {
	color: var(--i-ink);
}

.tot-inst .i-card--open .i-step-n {
	color: rgba(27, 37, 47, 0.72);
}

/* ---------- cluster navigation ----------
   The corporate pages were specified as a hub and spokes and then built as three islands: before
   this component, the hub linked to nothing but /contact/, and neither spoke linked to the hub or
   to the other spoke. These are the missing edges.

   🔴 Omer, 16 Aug 2026, authorised pointing at pages that are NOT BUILT YET — "we can handle a few
   days of dead ends". So every sibling ships in the set now, at its planned live URL, and no page
   has to be revisited as each spoke lands. Two consequences to know before anyone panics:
   on LocalWP every one of these 404s, including the two spokes that exist, because they are built
   here at flat slugs; and on staging the unbuilt four will 404 until they are built. Both are
   expected. **Do NOT quietly delete the dead ones** — that undoes a decision Omer made on purpose.

   Omer asked for controls that read as PRESSABLE rather than as more editorial links, which is
   also the honest signal: these leave the page. The affordance is a hard offset in the ink colour,
   a shadow that could have been printed, rather than a gradient or a blur — both of which would be
   foreign to a system whose whole vocabulary is flat fields and square corners. Hover deepens the
   offset and lifts the face; :active drops the face onto the shadow so the button visibly travels
   the distance it was standing above. Nothing here needs JavaScript.

   🔴 The travel is a CSS :active transform, NOT an Elementor animation. Elementor's entrance
   animations do not run on this install at all, and its translateY clamps at an arbitrary resting
   offset instead of returning to 0. This is unrelated machinery and does resolve — but if a future
   hand reaches for an Elementor Motion Effect here, it will not work, and that is not a bug in
   this component. */
.tot-inst .i-cluster {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
	gap: 0.9rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.tot-inst .i-cluster > li {
	display: flex;
	margin: 0;
}

.tot-inst .i-cluster-go {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 0.3rem;
	background-color: var(--i-paper);
	border: 2px solid var(--i-ink);
	border-radius: 0;
	padding: 0.9rem 1.05rem;
	text-decoration: none;
	box-shadow: 4px 4px 0 var(--i-ink);
	transition: box-shadow 0.12s ease, transform 0.12s ease, background-color 0.12s ease;
}

.tot-inst .i-cluster-go:hover,
.tot-inst .i-cluster-go:focus-visible {
	background-color: var(--i-yellow);
	box-shadow: 6px 6px 0 var(--i-ink);
	transform: translate(-2px, -2px);
}

/* The press. Face travels exactly the 4px it was raised, and the shadow goes to nothing, so the
   button ends flush with the page instead of sliding sideways. */
.tot-inst .i-cluster-go:active {
	background-color: var(--i-yellow);
	box-shadow: 0 0 0 var(--i-ink);
	transform: translate(4px, 4px);
}

.tot-inst .i-cluster-go:focus-visible {
	outline: 3px solid var(--i-ink);
	outline-offset: 3px;
}

.tot-inst .i-cluster-t {
	font-family: var(--i-label);
	font-size: 0.9rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	line-height: 1.25;
	color: var(--i-ink);
}

.tot-inst .i-cluster-d {
	font-size: 0.88rem;
	line-height: 1.4;
	color: var(--i-muted);
}

/* Muted grey on the yellow field is 2.3:1. On hover the description has to come up to the ink. */
.tot-inst .i-cluster-go:hover .i-cluster-d,
.tot-inst .i-cluster-go:focus-visible .i-cluster-d,
.tot-inst .i-cluster-go:active .i-cluster-d {
	color: var(--i-ink);
}

/* On the dark grounds a paper face would punch a hole in the section, so the set inverts: the
   face stays the band, the offset becomes the yellow, and hover fills to yellow as it does on
   white. Without this the ink border and ink shadow are invisible against the ink ground and the
   buttons read as floating text. */
.tot-inst.i-band .i-cluster-go,
.tot-inst.i-hero .i-cluster-go,
.tot-inst.i-hero-split .i-cluster-go {
	background-color: transparent;
	border-color: var(--i-on-ink);
	box-shadow: 4px 4px 0 var(--i-yellow);
}

.tot-inst.i-band .i-cluster-go .i-cluster-t,
.tot-inst.i-hero .i-cluster-go .i-cluster-t,
.tot-inst.i-hero-split .i-cluster-go .i-cluster-t {
	color: var(--i-on-ink);
}

.tot-inst.i-band .i-cluster-go .i-cluster-d,
.tot-inst.i-hero .i-cluster-go .i-cluster-d,
.tot-inst.i-hero-split .i-cluster-go .i-cluster-d {
	color: var(--i-on-ink-2);
}

.tot-inst.i-band .i-cluster-go:hover,
.tot-inst.i-band .i-cluster-go:focus-visible,
.tot-inst.i-hero .i-cluster-go:hover,
.tot-inst.i-hero .i-cluster-go:focus-visible,
.tot-inst.i-hero-split .i-cluster-go:hover,
.tot-inst.i-hero-split .i-cluster-go:focus-visible {
	background-color: var(--i-yellow);
	border-color: var(--i-yellow);
	box-shadow: 6px 6px 0 var(--i-on-ink);
}

.tot-inst.i-band .i-cluster-go:hover .i-cluster-t,
.tot-inst.i-band .i-cluster-go:focus-visible .i-cluster-t,
.tot-inst.i-band .i-cluster-go:hover .i-cluster-d,
.tot-inst.i-band .i-cluster-go:focus-visible .i-cluster-d,
.tot-inst.i-hero .i-cluster-go:hover .i-cluster-t,
.tot-inst.i-hero .i-cluster-go:focus-visible .i-cluster-t,
.tot-inst.i-hero .i-cluster-go:hover .i-cluster-d,
.tot-inst.i-hero .i-cluster-go:focus-visible .i-cluster-d,
.tot-inst.i-hero-split .i-cluster-go:hover .i-cluster-t,
.tot-inst.i-hero-split .i-cluster-go:focus-visible .i-cluster-t,
.tot-inst.i-hero-split .i-cluster-go:hover .i-cluster-d,
.tot-inst.i-hero-split .i-cluster-go:focus-visible .i-cluster-d {
	color: var(--i-ink);
}

.tot-inst.i-band .i-cluster-go:focus-visible,
.tot-inst.i-hero .i-cluster-go:focus-visible,
.tot-inst.i-hero-split .i-cluster-go:focus-visible {
	outline-color: var(--i-on-ink);
}

/* The press still reads without the travel: the offset collapsing is the signal, and it survives
   here. A button that reports nothing on click is worse than one that does not move. */
@media (prefers-reduced-motion: reduce) {
	.tot-inst .i-cluster-go {
		transition: none;
	}

	.tot-inst .i-cluster-go:hover,
	.tot-inst .i-cluster-go:focus-visible,
	.tot-inst .i-cluster-go:active {
		transform: none;
	}
}

/* ---------- hero over a full-bleed loop ----------
   🔴 Second version of this hero. The first put the loop in a right-hand column, which Omer
   rejected: he wants it as the hero ground, large. So the video is now full bleed behind the
   words, the same treatment the hub uses.

   The two pages are kept apart by composition rather than by treatment: the hub centres a single
   column and leads with the company, this one is left-aligned to a measure, leads with the product
   name, and carries the credential rule on a hairline instead of the hub's four-cell boxed strip.
   That is a weaker separation than a light hero gave, and it is the right trade because a hero
   video was the explicit ask. */
.tot-inst.i-hero-split {
	position: relative;
	overflow: hidden;
	background-color: var(--i-ink);
	background-image: linear-gradient(150deg, #0d141b 0%, #1b252f 52%, #2c3a48 100%);
	color: var(--i-on-ink);
	min-height: clamp(26rem, 62vh, 40rem);
	display: flex;
	align-items: center;
	/* An absolutely positioned child pins to the PADDING box, so the section's own padding left a
	   20px rim of brand navy down each side of the loop. The section carries no padding; the
	   spacing moves to the boxed child below, which is also what gives the words their measure. */
	padding: 0 !important;
}

.tot-inst.i-hero-split > .e-con {
	padding-block: clamp(3rem, 9vh, 6rem);
}

/* Everything Elementor renders sits above the video and the scrim. */
.tot-inst.i-hero-split > * {
	position: relative;
	z-index: 2;
	width: 100%;
}

.tot-inst.i-hero-split h1,
.tot-inst.i-hero-split .elementor-heading-title {
	font-size: clamp(2.1rem, 5vw, 3.9rem);
	line-height: 1.1;
	font-weight: 800;
	color: var(--i-on-ink);
	max-width: 17ch;
}

.tot-inst.i-hero-split p {
	color: var(--i-on-ink-2);
}

.tot-inst.i-hero-split a {
	color: var(--i-link-on-ink);
}

.tot-inst .i-stand {
	font-size: clamp(1rem, 1.4vw, 1.12rem);
	max-width: 54ch;
}

/* ---------- credential rule ----------
   A rule carrying four facts, rather than the hub's four-cell bordered strip.
   Same information, different furniture, so the two heroes do not rhyme. */
.tot-inst .i-creds {
	border-top: 2px solid var(--i-ink);
	padding-top: 0.9rem;
	margin-top: 1.6rem;
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 1.4rem;
}

.tot-inst .i-creds span {
	font-family: var(--i-label);
	font-size: 0.76rem;
	font-weight: 700;
	letter-spacing: 0.03em;
	color: var(--i-body);
}

.tot-inst .i-creds b {
	color: var(--i-ink);
}

/* The rule was written for a light hero. On the loop it was ink on ink: measured 1.06:1 for the
   labels and 1:1 for the bold values, which is invisible rather than merely low. The hero went
   dark when the video became its ground, and this is what that change dragged with it. */
.tot-inst.i-hero-split .i-creds {
	border-top-color: var(--i-yellow);
}

.tot-inst.i-hero-split .i-creds span {
	color: var(--i-on-ink-2);
}

.tot-inst.i-hero-split .i-creds b {
	color: var(--i-on-ink);
}

/* ---------- the brief panel ----------
   Sits in the right column of the hero. States the transaction: three things
   in, a written programme out. It replaced a two-track schedule diagram that
   was cut on 13 Aug because the first person to read it could not tell what
   it was. Do not put an abstract diagram back in this slot. */
.tot-inst .i-brief {
	background-color: var(--i-ink);
	color: var(--i-on-ink);
	padding: 1.5rem 1.35rem 1.6rem;
}

.tot-inst .i-brief .i-lab,
.tot-inst .i-brief .i-lab * {
	color: var(--i-yellow);
}

.tot-inst .i-brief h2,
.tot-inst .i-brief h3,
.tot-inst .i-brief .elementor-heading-title {
	font-family: var(--i-display);
	font-size: 0.98rem;
	font-weight: 700;
	color: var(--i-on-ink);
	margin: 0 0 0.55rem;
}

.tot-inst .i-brief ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.tot-inst .i-brief li {
	font-size: 0.95rem;
	color: var(--i-on-ink-2);
	display: flex;
	gap: 0.6rem;
	align-items: baseline;
	margin-bottom: 0.42rem;
}

/* Square markers rather than bullets, matching the signage register. The
   colour distinguishes what you send from what you get back, and the two
   lists are also separated by a rule and a heading, so nothing depends on
   colour alone. */
.tot-inst .i-brief li::before {
	content: "";
	flex: 0 0 auto;
	width: 0.5rem;
	height: 0.5rem;
	background: var(--i-yellow);
}

.tot-inst .i-brief-out {
	margin-top: 1.35rem;
	padding-top: 1.35rem;
	border-top: 1px solid var(--i-ink-2);
}

/* Side by side, the separator has to turn with the layout. The stacked rule's `margin-top` still
   applied in a row and pushed the second step down by 1.35rem, so the two halves sat on different
   baselines: a two-column panel that looked like a mistake rather than a pair. */
@media (min-width: 900px) {
	.tot-inst .i-brief.i-split .i-brief-out {
		margin-top: 0;
		padding-top: 0;
		border-top: 0;
		padding-left: 1.6rem;
		border-left: 1px solid var(--i-ink-2);
	}
}

.tot-inst .i-brief-out li::before {
	background: #9aa8ba;
}

/* ---------- guide rail ----------
   🔴 Deliberately NOT a shortcode. Omer adds the guides himself on the live
   site, and the JSON-backed pattern used by the trust panel can only be
   edited by Claude. This is a Text Editor widget holding plain HTML, so a new
   guide is a copied block with a name and a URL changed.

   Links point at the 48 long-form guide pages (/tolga-bensan/), never at
   /guides/<slug>/. Those directory profiles were deleted on 12 Aug 2026 and
   were noindex before that under D-11.

   The rail ships EMPTY. Until a card exists the whole section hides itself,
   because an empty bordered strip on a procurement page reads as a broken
   page rather than as a section awaiting content. On a browser without :has()
   the fallback is that empty strip, which is why .i-guides carries no border
   of its own. */
.tot-inst .i-guides {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(300px, 1fr);
	gap: 1px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	background: var(--i-line);
}

.tot-inst .i-guides:not(:has(.i-guide)) {
	display: none;
}

/* 🔴 `.tot-inst.i-guides-sec`, not `.tot-inst .i-guides-sec`. The section class sits on the same
   element as the scope class, so the descendant form matches nothing — the trap this file's own
   header documents, and it still caught this build. The symptom was not a CSS error: the section
   rendered its heading and standfirst over an empty rail, which is precisely the broken-looking
   page the rule exists to prevent. Found by measuring the computed style, not by reading. */
.tot-inst.i-guides-sec:not(:has(.i-guide)) {
	display: none;
}

/* WCAG 2.2.2 pause control, injected by guides.js rather than authored in the page markup so it
   cannot be deleted while the motion it excuses carries on. Deliberately matched to
   .tot-trust__pause: two auto-advancing rails on one page that offer differently-shaped controls
   read as two unrelated components.

   The 2px border is on --i-muted, not --i-line. 1.4.11 asks 3:1 of a control boundary and the
   line colour measures 1.23:1 against white. */
.tot-inst .i-guides-pause {
	height: 2.3rem;
	padding: 0 0.8rem;
	margin-bottom: 0.6rem;
	border: 2px solid var(--i-muted);
	background: transparent;
	color: var(--i-ink);
	cursor: pointer;
	font-family: var(--i-label);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	line-height: 1;
}

.tot-inst .i-guides-pause:hover {
	border-color: var(--i-ink);
	background: var(--i-yellow);
}

.tot-inst .i-guide {
	scroll-snap-align: start;
	background: var(--i-paper);
	text-decoration: none;
	color: inherit;
	display: grid;
	grid-template-rows: auto 1fr;
	align-content: start;
	border-top: 5px solid transparent;
	transition: border-color 0.12s;
}

.tot-inst .i-guide:hover,
.tot-inst .i-guide:focus-visible {
	border-top-color: var(--i-yellow);
}

/* The portrait well. No guide record carries a portrait today, so the
   typographic fallback is the design rather than a stand-in. A real <img>
   drops into the same well with no layout change. */
.tot-inst .i-guide-media {
	position: relative;
	aspect-ratio: 4 / 3;
	overflow: hidden;
	background-color: var(--i-ink);
	background-image: linear-gradient(145deg, #16202b 0%, #2c3b4a 100%);
}

.tot-inst .i-guide-media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.tot-inst .i-guide-initials {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	font-family: var(--i-display);
	font-weight: 800;
	font-size: clamp(2.4rem, 5vw, 3.4rem);
	letter-spacing: -0.02em;
	color: rgba(255, 255, 255, 0.16);
}

.tot-inst .i-guide-chip {
	position: absolute;
	left: 0;
	bottom: 0;
	background: var(--i-yellow);
	color: var(--i-ink);
	font-family: var(--i-label);
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	padding: 0.26rem 0.55rem;
}

.tot-inst .i-guide-body {
	padding: 1rem 1.1rem 1.2rem;
}

.tot-inst .i-guide-body h3 {
	font-family: var(--i-display);
	font-size: 1.12rem;
	font-weight: 700;
	color: var(--i-ink);
	margin: 0 0 0.3rem;
}

.tot-inst .i-guide-body p {
	font-size: 0.87rem;
	color: var(--i-body);
	margin: 0 0 0.5rem;
}

.tot-inst .i-guide-go {
	font-family: var(--i-label);
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--i-ink);
	border-bottom: 3px solid var(--i-yellow);
	padding-bottom: 0.1rem;
	display: inline-block;
}

.tot-inst .i-guide:hover .i-guide-go {
	background: var(--i-yellow);
}

/* ---------- we do / we do not ----------
   The page's real differentiator. A buyer who has been let down by a supplier
   that quietly expanded its own scope is looking for a boundary they can
   check, and two columns make it checkable in a way a paragraph does not.
   The heading in each column carries the meaning; the yellow tag only
   reinforces it. */
.tot-inst .i-bound-tag {
	display: inline-block;
	font-family: var(--i-label);
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	padding: 0.16rem 0.45rem;
	margin-bottom: 0.6rem;
	border: 1.5px solid var(--i-muted);
	color: var(--i-muted);
}

.tot-inst .i-bound-yes .i-bound-tag {
	background: var(--i-yellow);
	border-color: var(--i-yellow);
	color: var(--i-ink);
}

/* Scoped to the boundary panel, NOT to the shared .i-card. An earlier draft
   styled .i-card ul/li directly, which would have reached into every card on
   the hub page too. Shared classes stay untouched while two sessions are
   building against one stylesheet. */
.tot-inst .i-bound-list {
	margin: 0;
	padding-left: 1.1rem;
}

.tot-inst .i-bound-list li {
	font-size: 0.88rem;
	color: var(--i-body);
	margin-bottom: 0.35rem;
}

/* ---------- FAQ ----------
   Elementor's own Toggle widget, restyled. Native rather than custom markup
   so Omer can add and reorder questions in the builder.

   🔴 No FAQPage schema anywhere near this. Google dropped the rich result on
   7 May 2026. The block earns its place as citable content for AI answers and
   as the most procurement-friendly thing on the page, not as markup. If a
   plugin offers to add the schema back, decline. */
.tot-inst .i-faq .elementor-toggle-item {
	border-bottom: 1px solid var(--i-line);
}

/* 🔴 BOTH class names. Elementor's Accordion widget emits `.elementor-tab-title`; the Toggle
   widget emits `.elementor-toggle-title`. This page uses Toggle, so every rule here matched
   nothing and the FAQ titles rendered at the theme's own colour: measured 2.02:1 against white,
   less than half the 4.5:1 that 1.4.3 asks. Nine headings, every one failing, on the section whose
   whole job is being read by procurement.

   Toggle titles are anchors without an href, so the theme's link colour reached them and no
   link-colour fix could, since they are not links. */
.tot-inst .i-faq .elementor-tab-title,
.tot-inst .i-faq .elementor-toggle-title {
	font-family: var(--i-display);
	/* Must stay above the answer body below it, which is 1.06rem. */
	font-size: 1.15rem;
	font-weight: 700;
	color: var(--i-ink);
	padding: 0.9rem 0;
	border: 0;
}

.tot-inst .i-faq .elementor-tab-content,
.tot-inst .i-faq .elementor-toggle-content {
	font-size: 0.92rem;
	color: var(--i-body);
	border: 0;
	padding: 0 0 1rem;
	max-width: 66ch;
}

.tot-inst .i-faq .elementor-toggle-icon {
	color: var(--i-muted);
}

/* The first question ships open. A closed accordion reads as an empty section
   on first paint, and this block is doing procurement work. */
.tot-inst .i-faq .elementor-tab-title.elementor-active,
.tot-inst .i-faq .elementor-toggle-title.elementor-active {
	color: var(--i-ink);
}

/* ==========================================================================
   POST RAIL — [tot_posts], the CTA card rail

   Merged from the corporate-hub branch on 14 Aug 2026, and re-extracted rule
   by rule rather than taken as a diff. The automatic merge had interleaved
   this section with the guide rail above it, because `.tot-posts__go` and
   `.i-guide-go` are nine near-identical declarations apart. The result was
   `.tot-inst .i-guide-go` left unclosed with `.tot-posts__body` swallowed
   inside it: brace-balanced, so it passed every syntax check, but under CSS
   nesting the whole post rail only applied inside a guide link.

   Neither test suite could see it. CSS is not tested, and the damage was in
   the branch BEFORE this merge, not caused by it.
   ========================================================================== */

/* ================= post CTA rail — [tot_posts] =================
   Large call-to-action cards, one per article, opening in a new tab. Shares the
   carousel behaviour and the control styling with the trust panel; only the card
   itself is different. Placeholder posts for now: Omer swaps the `ids` attribute
   once the real articles are chosen. */
.tot-posts__h {
	font-family: var(--i-display);
	font-weight: 700;
	color: var(--i-ink);
	margin: 0 0 0.4rem;
}

.tot-posts__stand {
	color: var(--i-body);
	margin: 0 0 0.9rem;
	max-width: 62ch;
}

.tot-posts__ctrl {
	display: flex;
	align-items: center;
	gap: 0.35rem;
	justify-content: flex-end;
	margin-bottom: 0.6rem;
}

.tot-posts__rail {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(272px, 1fr);
	gap: 1px;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scroll-padding-left: 6px;
	padding: 6px;
	background: var(--i-line);
	border: 1px solid var(--i-line);
}

.tot-posts__card {
	scroll-snap-align: start;
	will-change: transform;
	background: var(--i-paper);
	text-decoration: none;
	color: inherit;
	display: grid;
	grid-template-rows: auto 1fr;
	align-content: start;
	border-top: 5px solid transparent;
	transition: border-color 0.12s;
}

.tot-posts__card:hover,
.tot-posts__card:focus-visible {
	border-top-color: var(--i-yellow);
}

.tot-posts__media {
	position: relative;
	display: block;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: var(--i-ink);
}

.tot-posts__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.5s ease;
}

.tot-posts__card:hover .tot-posts__media img {
	transform: scale(1.045);
}

/* Shown when a post has no featured image. A flat brand ground rather than a
   broken-image box or a grey rectangle. */
.tot-posts__ph {
	position: absolute;
	inset: 0;
	background:
		radial-gradient(58% 70% at 72% 22%, rgba(110, 193, 228, 0.3), transparent 68%),
		linear-gradient(145deg, #16202b 0%, #2c3b4a 100%);
}

.tot-posts__cat {
	position: absolute;
	left: 0;
	bottom: 0;
	background: var(--i-yellow);
	color: var(--i-ink);
	font-family: var(--i-label);
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	padding: 0.26rem 0.55rem;
}

.tot-posts__card:hover .tot-posts__go {
	background: var(--i-yellow);
}

.tot-posts__card:focus-visible {
	outline: 0;
	box-shadow: 0 0 0 3px var(--i-ink), 0 0 0 6px var(--i-yellow);
}

/* "opens in a new tab", announced but not shown. Surprise tab-opening is a
   standard accessibility complaint and procurement now tests for it. */
.tot-posts__vh {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}


/* ================= post CTA rail — [tot_posts] ================= Large call-to-action cards, one per article, opening in a new tab. Shares the carousel behaviour and the control styling with the trust panel; only the card itself is different. Placeholder posts for now: Omer swaps the `ids` attribute once the real articles are chosen. */ .tot-posts__h {
	font-family: var(--i-display);
	font-weight: 700;
	color: var(--i-ink);
	margin: 0 0 0.4rem;
}


.tot-posts__go {
	font-family: var(--i-label);
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--i-ink);
	border-bottom: 3px solid var(--i-yellow);
	padding-bottom: 0.1rem;
	display: inline-block;
}


.tot-posts__title {
	font-family: var(--i-display);
	font-size: 1.04rem;
	font-weight: 700;
	line-height: 1.26;
	color: var(--i-ink);
}

.tot-posts__excerpt {
	font-size: 0.85rem;
	color: var(--i-body);
	line-height: 1.5;
}


/* ================= motion effects — the reduced-motion guard =================
   The hub's scroll motion is Elementor Pro SCROLLING EFFECTS, set per element on post 170 and
   carried in the exported template JSON. It is deliberately not declared here. This block is the
   accessibility half, and it has to live in CSS because Elementor does not do it.

   🔴 Elementor's own motion-fx.css only zeroes the TRANSITION DURATION under
   `prefers-reduced-motion: reduce`. That removes the easing and leaves the movement: its JS still
   writes `transform` and `opacity` inline on every scroll event. A reader who has asked their
   system for less motion still gets the full travel, merely snapped rather than eased. Checking
   that the vendor "supports" the media query is not the same as checking what it does.

   `!important` in a stylesheet beats an inline style that carries no `!important`, which is what
   neutralises Elementor's inline writes.

   🔴 Both selector shapes are required. The ten section containers carry `tot-inst` themselves, so
   they need `.tot-inst.elementor-motion-effects-element`; the hero widgets, the grid cards and the
   figures sit INSIDE the scope and need the descendant form. One shape alone silently covers half
   the page, which is the same trap this file documents at the theme-reset block. */
@media (prefers-reduced-motion: reduce) {

	.tot-inst.elementor-motion-effects-element,
	.tot-inst .elementor-motion-effects-element {
		transform: none !important;
		opacity: 1 !important;
	}

}


/* 🔴 A standing backstop, and a warning.
   This page uses Elementor SCROLLING effects, which hide nothing. It deliberately does NOT use
   Elementor ENTRANCE animations (fadeInUp and friends), which were built here on 15 Aug 2026 and
   reverted the same day because they do not work on this install: all ten sections stayed
   `visibility: hidden` after a full-page scroll, `elementor-invisible` was never removed, and no
   animations stylesheet loaded. Settings written into post meta by WP-CLI bypass the save pipeline
   Elementor uses to decide which assets a page needs.

   The rule below costs nothing today and means that if anyone does add an entrance animation
   later, a reader with scripting off gets the content instead of a blank band. It cannot help when
   JS loads and then throws, so it is a backstop, not a licence to use entrance animations. */
@media (scripting: none) {

	.tot-inst.elementor-invisible,
	.tot-inst .elementor-invisible {
		visibility: visible !important;
	}
}


/* A split hero WITHOUT a full-bleed video behind it.
   `.i-hero-split` zeroes its padding on purpose, so the congress hero's loop can bleed to the
   edges and the inner `i-split` columns carry the insets. The study spoke reuses the same
   left-aligned composition but has no video and no split columns, so with padding zeroed its
   headline ran flat against the browser edge. This is the exception, at (0,3,0) so it beats the
   base rule without touching it, and the congress hero is unaffected.

   Deliberately CSS rather than an Elementor padding setting: Elementor's control emits all four
   sides, so setting only top and bottom writes `padding: 72px 0px 72px 0px` and silently zeroes
   the inline gutter again. That was tried first. */
.tot-inst.i-hero-split.i-hero-plain {
	/* `!important` matches the base rule, which carries it so an absolutely positioned video child
	   pins to the padding box rather than leaving a navy rim down each side of the loop. This hero
	   has no such child, so the reason for the zero does not apply to it. */
	padding-inline: clamp(1.15rem, 4vw, 3rem) !important;
	padding-block: clamp(3rem, 7vw, 5.5rem) !important;
	min-height: 0;
}


/* ---- the aside column ----
   The right half of a two-column row was dead space: the prose is capped at 78ch and the picture
   slot beside it is invisible while empty, so at desktop width half the page was blank. There are
   currently ZERO images in the media library, so "place an image widget" had nothing to place.

   The secondary material moves here instead: the pull quote, the cited source, the guide quote.
   They are apparatus rather than argument, they read perfectly well beside the prose rather than
   under it, and they fill the column with something true today. The empty `.i-media` slot sits
   directly above, so a picture drops in later without moving any of this. */
.tot-inst .i-aside {
	border-top: 2px solid var(--i-line);
	padding-top: 1rem;
}

.tot-inst .i-aside .i-pull {
	margin-top: 0;
	border-left: 0;
	padding-left: 0;
	max-width: none;
}

.tot-inst .i-aside .i-src {
	margin-top: 1rem;
	max-width: none;
}

.tot-inst .i-aside .i-gq {
	margin-top: 0;
	border-top: 0;
	padding-top: 0;
	max-width: none;
}

/* The columns are no longer equal. Prose takes about three fifths, the aside two, which is what a
   78ch measure and a short quote actually want. */
@media (min-width: 860px) {

	/* Push the two columns to the outer edges rather than letting the text column grow and carry
	   its slack on the right. Prose stays at a readable measure, the aside sits against the right
	   edge, and the row spans the shell instead of ending two thirds of the way across. That is
	   what "the right side is empty" actually was: not a missing picture, but a 78ch measure
	   floating in a 1520 shell with nothing holding the far edge. */
	.tot-inst .i-media-row {
		justify-content: space-between;
	}

	.tot-inst .i-media-row > .e-con:first-child {
		flex: 1 1 30rem;
		max-width: 42rem;
	}

	.tot-inst .i-media-row > .e-con:last-child {
		flex: 1 1 18rem;
		max-width: 26rem;
	}

	/* A bare slot that IS the rail grows into the row's slack. The 26rem rail cap above is sized
	   for a wrapped rail that carries an aside under its picture; a row whose second column is
	   ONLY an .i-media left a dead gutter wider than the image itself (measured 432px on the
	   event page, 17 Aug 2026, and Omer flagged it). The prose column is pinned to its edge by
	   the row's space-between, so widening the slot moves nothing else. 36rem keeps the 4/3
	   image near the prose column's height, which is the balance the rows are tuned to. */
	/* :last-child matters: the rail cap above is (0,4,0) with its pseudo-class, and a plain
	   .tot-inst .i-media-row > .i-media at (0,3,0) loses to it silently — measured before this
	   selector gained its own :last-child and the tie-break on source order. */
	.tot-inst .i-media-row > .i-media:last-child {
		flex: 1 1 26rem;
		max-width: 36rem;
	}
}


/* ---- a named guide quote ----
   Doc 31 requires one on every Phase 2 page, and quotations are the highest measured GEO lever at
   +27.8% (T2, Princeton GEO-bench). Sits on a yellow rule rather than in a box, so it reads as
   testimony rather than as another card. */
.tot-inst .i-gq {
	margin: 1.8rem 0 0;
	padding: 1.2rem 0 0;
	border: 0;
	border-top: 2px solid var(--i-yellow);
	max-width: 56ch;
}

.tot-inst .i-gq p {
	font-family: var(--i-display);
	font-size: clamp(1.15rem, 1.7vw, 1.5rem);
	line-height: 1.4;
	font-weight: 700;
	color: var(--i-ink);
	margin: 0;
	max-width: none;
}

.tot-inst .i-gq cite {
	display: block;
	margin-top: 0.7rem;
	font-style: normal;
	font-family: var(--i-label);
	font-size: 0.82rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--i-muted);
}

/* ---- a section pull quote ----
   The same 5px yellow left bar the trust panel's own pull uses, so a reader meets one device on the
   page rather than two that nearly match. */
.tot-inst .i-pull {
	font-family: var(--i-display);
	font-size: clamp(1.15rem, 1.6vw, 1.45rem);
	line-height: 1.45;
	font-weight: 700;
	border-left: 5px solid var(--i-yellow);
	padding-left: 1rem;
	/* 1rem, not 1.8rem. Section padding is only part of a perceived gap; element margins stack on
	   top of it, and this one was adding ~29px to every row that carries a pull quote. */
	margin: 1rem 0 0;
	max-width: 46ch;
	color: var(--i-ink);
}

.tot-inst.i-band .i-pull,
.tot-inst.i-band .i-gq p {
	color: var(--i-on-ink);
}


/* ---- cited sources ----
   Added 15 Aug 2026 after a playbook sweep measured ZERO cited sources on both the hub and the
   congress spoke. GEO-bench (T2, Princeton) puts cited sources at +24.9%, quotations at +27.8% and
   statistics at +25.9%; both pages already had the other two.

   Set a step below body so a source line reads as apparatus rather than as an argument, but not so
   small it fails contrast: 0.94rem on --i-body clears 4.5:1 comfortably. */
.tot-inst .i-src {
	font-size: 0.94rem;
	line-height: 1.55;
	color: var(--i-body);
	max-width: 72ch;
	margin-top: 0.9rem;
}

.tot-inst .i-src + .i-src {
	margin-top: 0.6rem;
}


/* ================= the desktop shell =================
   Elementor boxes every container at `max-width: var(--content-width)`, and its default resolves
   to `min(100%, var(--container-max-width, 1140px))`. On a 1920 screen that is 1140px of page and
   780px of empty margin, which Omer reported on 15 Aug 2026 as dead lanes down both sides.

   🔴 The fix is deliberately NOT the Elementor kit's Content Width setting. That setting is global:
   raising it there would re-lay-out every Elementor page on theothertour.com, most of which nobody
   has looked at since. `--container-max-width` is Elementor's own hook, it is unset by this kit,
   and redefining it under `.tot-inst` widens the institutional pages and nothing else. No
   specificity fight, because the variable is read on the same element that declares it.

   ⚠️ This is the shared institutional stylesheet, so it widens the congress spoke too. That is the
   intended behaviour per doc 36 (three Phase 2 pages, one stylesheet, no drift) rather than an
   accident, but it does change a page that was already reviewed at 1140. */
.tot-inst {
	--container-max-width: 1520px;
	/* 🔴 A gutter, because Elementor's default is 10px and that is not a gutter.
	   Measured at a 1500px viewport, which is just under the 1520 shell so no centring margin
	   exists: the content ran to 10px from the left edge and 25px from the right. That band, roughly
	   1050px to 1520px, is where most laptops sit, so the most common desktop width was the worst
	   looking one. Above 1520 the shell centres and the problem hides, which is why three rounds of
	   screenshots at 1920 never showed it. */
	padding-inline: clamp(1.15rem, 4vw, 3rem);
	/* Vertical rhythm. All three institutional pages had ZERO section padding and relied entirely
	   on widget margins, which works until a section ends in something that has none: the study
	   spoke's guide quote ran straight into the dark band below it with no gap at all. Omer
	   reported the spacing as off. Sections now own their own breathing room, so a section is
	   correctly spaced whatever it happens to end with. The heroes are unaffected: `.i-hero-split`
	   zeroes padding with `!important` and `.i-hero-plain` sets its own. */
	/* 🔴 This value is DOUBLED in the gap a reader sees. Sections sit flush, so the space between
	   two of them is this padding twice: at 2.6rem that was 83px, which Omer reported as too much
	   for the second time. 1.7rem gives 54px between sections, and the widget gap inside a section
	   stays at Elementor's 20px. Measure the gap BETWEEN sections, not the padding on one. */
	padding-block: clamp(0.7rem, 1.1vw, 1.1rem);
}

/* Widening the shell is only half the job. Structure should fill it, prose must not: measured at
   1520, the section intros ran to roughly 264 characters per line and the two-column body to about
   130. Optimal is 45 to 85. So the shell grows, the card grids, the figures band, the record rail
   and the hero proof strip grow with it, and running text keeps a measure a person can actually
   read. `li` is included because the we-do / stays-with-you lists and the FAQ answers would
   otherwise run the full 1520 unchecked. */
.tot-inst .elementor-widget-text-editor p,
.tot-inst .elementor-widget-text-editor li {
	max-width: 78ch;
}


/* ================= type scale for the wide shell =================
   Sizes tuned against a 1140px shell read as undersized once it became 1520. Measured before the
   change at a 1920 viewport: H1 31.5px, H2 32.8px, all running text 14px.

   🔴 The defect this pass exists to fix: the H1 was SMALLER than the H2. The hub hero never had a
   font-size rule at all, so it fell through to Elementor's `h1 { font-size: 2.25em }` on a 14px
   base. The congress spoke's `.i-hero-split` was given a display clamp and this one was missed, so
   the page's largest heading was not its most important one. */

/* Base running text, 14px to 16px.

   🔴 `:not([class])` is load-bearing and was learned the hard way. Without it this rule outranks
   `.tot-inst .i-lab` at (0,2,0) and blew all eleven Oswald labels on the page from 11.5px to 16px:
   "FOR ORGANISATIONS", "SCOPE", every section eyebrow. It also caught `.i-close-proof`, and it is
   what keeps this rule off `.tot-posts__excerpt` and the whole `tot-trust__*` set. In this
   stylesheet a classed paragraph is one the design system has already named and sized, so the base
   size applies to unclassed paragraphs only and any label added later is protected by construction
   rather than by a growing `:not()` list.

   🔴 Scoped to `.tot-inst`, NOT to `.elementor-widget-text-editor`. The first version was scoped to
   the text-editor widget and silently missed seventeen paragraphs that live in other widgets: the
   three FAQ accordion answers and the fourteen record descriptions inside the `[tot_trust]`
   shortcode. They stayed at 14px next to 16px body copy, which is what Omer reported as the small
   text still not being adjusted. Widget type is the wrong axis to scope typography on.

   🔴 `:where()` wraps the `:not()` and is load-bearing for a second reason, found when the guide
   quote on the study page rendered at 17px instead of 24px. An attribute selector counts as a CLASS
   for specificity, so a bare `.tot-inst p:not([class])` is (0,2,1), which TIES every component rule
   of the form `.tot-inst .i-thing p` and then wins on source order because it sits later in the
   file. That silently outranks the component that is supposed to own the element. `:where()`
   contributes ZERO specificity while matching identically, so the rule drops to (0,1,1), components
   win again, and classed paragraphs are still excluded exactly as before. */
.tot-inst p:where(:not([class])),
.tot-inst li:where(:not([class])) {
	font-size: 1.06rem;
	line-height: 1.6;
}

/* Cards keep a tighter measure. (0,3,1) beats the rule above whatever the source order, so this
   does not depend on staying below it in the file. */
.tot-inst .i-card .elementor-widget-text-editor p {
	font-size: 1rem;
}

/* ---------- the picture slots ----------
   🔴 `.i-shot` had no rule anywhere in this stylesheet. The three hub Image widgets carry the class
   and nothing styled it, so each picture rendered at its natural ratio and filled the column: 770
   by 513 against a text column only 230 tall, with the row centre-aligned, which left the copy
   floating in the middle of a wall of image. Omer reported it as the image position being off.

   The styled sibling system is `.i-media`, which owns `aspect-ratio` and `object-fit`. This gives
   `.i-shot` the same treatment in the form the two-column rows need: a controlled band rather than
   a ratio, so the picture stays comparable in height to the text beside it at any shell width.

   🔴 `height` carries `!important` and needs it. Elementor generates per-page CSS into
   `post-170.css` containing `.elementor-170 .elementor-element.elementor-element-XXXXXXX img {
   height: auto }` at (0,3,1), against this rule's (0,2,1). That file is generated per page and
   loads AFTER this stylesheet, so the override cannot be won on specificity or on source order
   without hard-coding a post id that changes on deploy.

   🔴 A FIXED HEIGHT WAS TRIED HERE AND REVERTED, 15 Aug 2026. `height: clamp(14rem, 20vw, 20rem)`
   with `object-fit: cover` did balance the columns, but cover CROPS: it fills the band by cutting
   whatever does not fit, so a portrait photograph lost its top and bottom and a group shot lost
   people. Omer's instruction is that the picture adjusts to the image, not the image to the slot.

   So the slot is fluid: full column width, natural ratio, nothing cropped, whatever gets uploaded.
   The trade is accepted deliberately: a tall image makes a tall row, and the text beside it sits
   centred against that height. If a particular picture ever looks wrong here, the fix is to crop
   the FILE before upload, not to re-add a `cover` that silently mutilates every other one. */
.tot-inst .i-shot img {
	display: block;
	width: 100%;
	height: auto;
}

/* The hub H1. Kept a step below the congress spoke's 3.9rem ceiling: that hero is a two-column
   split where the headline carries the left column alone, this one is centred over a video with a
   proof strip under it, and it should not shout over its own credentials. */
.tot-inst.i-hero h1,
.tot-inst.i-hero h1.elementor-heading-title {
	font-size: clamp(2.2rem, 4.2vw, 3.5rem);
	line-height: 1.08;
	font-weight: 800;
	letter-spacing: -0.02em;
}

/* The hero standfirst, one step above body so the hero reads as three sizes rather than two.
   🔴 `:not(.i-lab)` is load-bearing: the eyebrow is also a `p` inside a text-editor in this
   container, and without the exclusion this rule (0,4,1) would blow the 0.72rem label up to
   1.2rem. */
.tot-inst.i-hero > .e-con-inner > .elementor-widget-text-editor p:not(.i-lab) {
	font-size: clamp(1.05rem, 1.15vw, 1.2rem);
	line-height: 1.55;
}
