/* ==========================================================================
   1. Upper sections
   ========================================================================== */

/* The ground is the wall of the photograph, for the moment before the photograph is in. A finger moving
   across the hero turns the head (assets/js/home-hero.js); up and down it scrolls the page as anywhere. */
.od-hero { position: relative; height: 1024px; height: clamp(640px, 100svh, 1100px); max-height: 1100px; overflow: hidden; background: #596a79; color: var(--od-white); touch-action: pan-y pinch-zoom; }
/* The photograph and what is drawn over it share one frame, so they move as one (the frame carries
   data-od-parallax). The frame is not enlarged for that drift, unlike other pictures: at the top of a page a
   picture can only leave a gap at its upper edge, and only in a window taller than the hero, so the frame
   starts a little above the hero instead and the photograph keeps every pixel it has. */
.od-hero__media { position: absolute; inset: -32px 0 0; }
.od-motion .od-hero__media.od-parallax { scale: 1; }
.od-hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; object-fit: cover; object-position: 50% 38%; }
/* The live picture repaints the photograph with the head turned and three bands of light on it. Its first
   frame is the photograph itself, so it takes over without a jump. Neither it nor the layers below take
   the pointer: the bar reads its colours from the photograph under them (site.js). */
.od-hero__gl { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; pointer-events: none; }
.od-hero--live .od-hero__gl { opacity: 1; transition: opacity 0.4s linear; }
/* The bands at rest, as a picture in the photograph's own frame: what a visitor gets without scripts,
   with reduced motion, without WebGL or after any failure. od-hero-wait is set in the head
   (inc/home-hero.php) while the live picture is on its way, four seconds at most. */
.od-hero__still { pointer-events: none; }
html.od-hero-wait .od-hero__still, .od-hero--live .od-hero__still { display: none; }
/* The shade. The wall of the photograph is a light blue-grey: white text on it alone stands at 2.5 to 3:1.
   This layer deepens the wall in its own colour where texts stand and nowhere else: it is clear over the
   head and where the bands rest. It lies over the picture and under every text, and stays with the texts
   when the picture drifts. The measured figures are kept with the project notes on the home hero. */
.od-hero__shade {
	--od-shade: 14, 22, 31;
	position: absolute; inset: 0; z-index: 1; pointer-events: none;
	background:
		/* the head of the hero, where the large word crosses the lighter wall beside the crown */
		linear-gradient(180deg, rgba(var(--od-shade), 0.12) 0%, rgba(var(--od-shade), 0.12) var(--od-shade-head, 30%), rgba(var(--od-shade), 0) calc(var(--od-shade-head, 30%) + 16%)),
		/* the headline and the line under it, lower left: the lightest part of the wall */
		radial-gradient(ellipse var(--od-shade-reach, 40%) 37% at 7% 72%, rgba(var(--od-shade), 0.50) 0%, rgba(var(--od-shade), 0.49) 42%, rgba(var(--od-shade), 0.40) 62%, rgba(var(--od-shade), 0.22) 80%, rgba(var(--od-shade), 0.08) 92%, rgba(var(--od-shade), 0) 100%),
		/* the side label at the left edge */
		linear-gradient(90deg, rgba(var(--od-shade), 0.24) 0%, rgba(var(--od-shade), 0.12) 6%, rgba(var(--od-shade), 0) 13%),
		/* the foot, under BUILT TO WIN */
		linear-gradient(0deg, rgba(var(--od-shade), 0.36) 0%, rgba(var(--od-shade), 0.30) 6%, rgba(var(--od-shade), 0.16) 13%, rgba(var(--od-shade), 0.05) 19%, rgba(var(--od-shade), 0) 24%),
		/* the tagline, upper right */
		radial-gradient(ellipse 17% 21% at 93% 40%, rgba(var(--od-shade), 0.24) 0%, rgba(var(--od-shade), 0.20) 45%, rgba(var(--od-shade), 0.08) 78%, rgba(var(--od-shade), 0) 100%);
}
.od-hero::before { content: ""; position: absolute; inset: 0 0 auto; height: 150px; z-index: 1; background: linear-gradient(rgba(0, 0, 0, .28), rgba(0, 0, 0, 0)); pointer-events: none; }
.od-hero__inner { position: absolute; inset: 80px 0 0; z-index: 2; display: flex; flex-direction: column; gap: 32px; padding: 20px var(--od-gutter); }
.od-hero__word { margin: 0; font-weight: 700; font-size: clamp(72px, 19.75vw, 160px); line-height: .8; letter-spacing: var(--od-track-display); white-space: nowrap; }
.od-hero__word--second { text-align: right; font-size: clamp(40px, 11.2vw, 90px); }
.od-hero__mid { flex: 1; min-height: 0; display: flex; align-items: flex-end; }
.od-hero__main { flex: 1; min-width: 0; height: 100%; display: flex; flex-direction: column; gap: 16px; }
.od-hero__row { flex: 1; min-height: 0; display: flex; gap: 16px; align-items: flex-start; }
.od-hero__tagline { flex: 1; margin: 0; text-align: right; font-size: var(--od-fs-h5); line-height: 1.4; font-weight: 500; }
.od-hero__heading { max-width: 560px; display: flex; flex-direction: column; gap: 4px; }
.od-hero__title { margin: 0; font-size: var(--od-fs-h3); line-height: 1.3; font-weight: 500; letter-spacing: var(--od-track); text-wrap: balance; }
.od-hero__text { margin: 0; max-width: 400px; font-size: var(--od-fs-b2); line-height: 1.6; font-weight: 500; }
/* The corners: slipped Ls, mirrored to their corner. */
.od-hero__corner { position: absolute; width: 26px; height: 26px; color: var(--od-white); background: var(--od-corner); pointer-events: none; }
.od-hero__corner--tr { top: 0; right: var(--od-gutter); transform: scaleX(-1); }
.od-hero__corner--bl { bottom: 16px; left: var(--od-gutter); transform: scaleY(-1); }
@media (min-width: 1025px) {
	.od-hero__word { font-size: clamp(160px, 14vw, 240px); }
	.od-hero__word--second { font-size: clamp(90px, 7.9vw, 136px); }
}
/* Wide but short windows (a small laptop, a zoomed page): the hero is as tall as the window and its two
   large words follow the height, so the second one is never cut by the bottom edge. */
@media (min-width: 1025px) and (max-height: 760px) {
	.od-hero { height: clamp(520px, 100svh, 1100px); }
	.od-hero__inner { gap: clamp(16px, 4vh, 32px); }
	.od-hero__word { font-size: clamp(110px, min(14vw, 27vh), 240px); }
	.od-hero__word--second { font-size: clamp(62px, min(7.9vw, 15.2vh), 136px); }
	.od-hero__tagline { font-size: clamp(20px, 4.2vh, 32px); }
	.od-hero__title { font-size: clamp(30px, 6.8vh, 52px); }
	/* The large word takes more of a short hero: the shade at the head reaches as far down as it does. */
	.od-hero__shade { --od-shade-head: 44%; }
}
/* The line under the headline is as long in a narrow window as in a wide one, while the shade is a share of
   the hero. Under the wide photograph the shade keeps a least width, so the end of the longest line (the
   French one) stays on it, and never passes half the hero, so the band on the neck keeps its light.
   In vw, the hero being as wide as the window: a gradient size takes no sum of a share and a length. */
@media (min-width: 601px) and (orientation: landscape) {
	.od-hero__shade { --od-shade-reach: max(40vw, min(600px, 50vw)); }
}
@media (max-width: 600px) {
	.od-hero { height: clamp(600px, 100svh, 844px); }
	.od-hero__inner { inset: 64px 0 0; gap: 24px; }
	.od-hero__corner--bl { display: none; }
	/* On phones the three words stand on the lightest part of the photograph: a soft shade behind them
	   alone (the picture is not dimmed anywhere else) brings white on it to 4.5:1 or better. */
	.od-hero__tagline { position: relative; isolation: isolate; }
	.od-hero__tagline::before { content: ""; position: absolute; z-index: -1; top: -18px; bottom: -12px; right: -22px; width: 138px; background: rgba(0, 0, 0, 0.5); filter: blur(16px); pointer-events: none; }
	/* The tall photograph leaves a strip of wall at each side: the left one carries the side label and the first letters of the headline. */
	.od-hero__shade {
		background:
			linear-gradient(180deg, rgba(var(--od-shade), 0.12) 0%, rgba(var(--od-shade), 0.12) 20%, rgba(var(--od-shade), 0) 30%),
			radial-gradient(ellipse 36% 38% at 0% 66%, rgba(var(--od-shade), 0.56) 0%, rgba(var(--od-shade), 0.54) 45%, rgba(var(--od-shade), 0.34) 68%, rgba(var(--od-shade), 0.12) 88%, rgba(var(--od-shade), 0) 100%),
			radial-gradient(ellipse 30% 17% at 100% 87%, rgba(var(--od-shade), 0.34) 0%, rgba(var(--od-shade), 0.30) 45%, rgba(var(--od-shade), 0.10) 82%, rgba(var(--od-shade), 0) 100%),
			linear-gradient(0deg, rgba(var(--od-shade), 0.30) 0%, rgba(var(--od-shade), 0.20) 7%, rgba(var(--od-shade), 0) 16%);
	}
}

/* Hero text: a little wider, and balanced so a single word never sits alone on the last line. */
.od-hero__text { max-width: 470px; text-wrap: balance; }

/* Hero marks. The wordmark is the drawn Slip mark; "Creative & technology" stands under it as one lock-up, held
   by two still slip brackets and aligned to the edge of the O. The headline begins with the prompt and is typed
   once (home.js); BUILT TO WIN is held by a pair of brackets whose closing one rides on the letters as they are
   typed and then blinks as the caret. The orange light on the photograph is untouched by all of this. */
.od-hero__lockup { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(8px, 0.85vw, 14px); }
.od-hero__mark { height: 0.72em; }
.od-hero__ct { display: flex; align-items: center; margin: 0; font-size: clamp(11px, 0.8vw, 13px); line-height: 1.4; font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; white-space: nowrap; }
.od-hero__ct::before, .od-hero__ct::after { content: ""; flex: none; width: 7px; height: 1.5em; color: var(--od-brand); background: var(--od-sb); }
.od-hero__ct::before { margin-right: 0.75em; }
.od-hero__ct::after { margin-left: 0.55em; transform: scaleX(-1); }
/* The side labels are gone; the room they took on the right is kept, so the tagline stays where it stood. */
.od-hero__mid { padding-right: calc(var(--od-fs-b3) * 1.6 + 13px); }
.od-hero__title::before { content: ">"; display: inline-block; margin-right: 0.6em; font-family: var(--od-mono); font-weight: 500; letter-spacing: 0; font-size: 0.42em; vertical-align: 0.42em; color: var(--od-brand); }
.od-hero__win { display: inline-flex; align-items: stretch; gap: 0.16em; }
.od-hero__bk { --h: auto; --w: 0.2em; --s: 0.068em; --slip: 0.075em; height: auto; align-self: stretch; margin: 0.06em 0 0.02em; }
.od-hero__caret { transform: scaleX(-1) translateX(calc(var(--od-cx, 0px) * -1)); }

/* Typing. Letters wait only while the script runs with motion allowed (od-type-on); until they are ready the
   headline is kept out of sight, for three seconds at most, so it never shows and then vanishes. */
html.od-type-on [data-od-type] .od-ch { opacity: 0; }
html.od-type-on [data-od-type] .od-ch.is-on { opacity: 1; }
html.od-motion:not(.od-type-on):not(.od-type-off) .od-hero__title, html.od-motion:not(.od-type-on):not(.od-type-off) .od-hero__win-t { color: transparent; animation: od-type-safe 0s 3s forwards; }
@keyframes od-type-safe { to { color: var(--od-white); } }

/* Who we are. Three lines of display type held by a pair of slip brackets; the closing one blinks while the
   sentence is typed (once, when it comes into view) and then stands. Line breaks are part of the translated
   text (.od-who__line); --od-who-len is the longest line in em per language (lengths.mjs). */
.od-who { --od-who-len: 10.63; background: var(--od-white); color: var(--od-black); }
html[lang^="de"] .od-who { --od-who-len: 14.1; }
html[lang^="fr"] .od-who { --od-who-len: 11.15; }
html[lang^="es"] .od-who { --od-who-len: 10.02; }
html[lang^="it"] .od-who { --od-who-len: 9.65; }
html[lang^="pt"] .od-who { --od-who-len: 12.03; }
.od-who__inner { display: flex; flex-direction: column; gap: clamp(32px, 5vw, 64px); padding: clamp(80px, 12vw, 160px) var(--od-gutter); }
.od-who__label { align-self: flex-start; }
.od-who__frame { --od-who-pad: clamp(28px, 4vw, 64px); position: relative; padding: 0.25em var(--od-who-pad); font-size: max(30px, min(7.4vw, 128px, calc((100vw - 2 * var(--od-gutter) - 2 * var(--od-who-pad)) / var(--od-who-len)))); }
.od-who__text { display: flex; flex-direction: column; margin: 0; font-weight: 700; line-height: 1.04; letter-spacing: var(--od-track-display); }
.od-who__line { display: block; white-space: nowrap; }
.od-who__line:nth-child(2) { text-align: right; color: var(--od-brand); }
.od-who__line:nth-child(3) { padding-left: 18%; }
.od-who__bk { --h: auto; --w: clamp(16px, 2.4vw, 40px); --s: clamp(5px, 0.7vw, 11px); --slip: calc(var(--s) * 1.1); position: absolute; top: 0; bottom: 0; left: 0; height: auto; }
.od-who__caret { left: auto; right: 0; }
.od-who__more { max-width: 36em; margin: 0 0 0 auto; font-size: var(--od-fs-b2); line-height: 1.5; color: var(--od-grey-700); text-wrap: pretty; }
html.od-type-on .od-who:not(.is-typed) .od-who__more { opacity: 0; translate: 0 16px; }
html.od-type-on .od-who__more { transition: opacity 0.8s var(--od-ease), translate 0.8s var(--od-ease); }
@media (max-width: 600px) {
	.od-hero__ct { font-size: 11px; letter-spacing: 0.16em; }
	.od-who__frame { font-size: clamp(30px, 9.6vw, 48px); padding: 0.3em 22px; }
	.od-who__line { white-space: normal; text-wrap: balance; }
	.od-who__line:nth-child(2) { text-align: left; }
	.od-who__line:nth-child(3) { padding-left: 0; }
	.od-who__bk { --w: 12px; --s: 4px; }
}
@media print {
	.od-who__more { opacity: 1 !important; translate: none !important; }
	[data-od-type] .od-ch { opacity: 1 !important; }
}

/* Print: the hero shows its photograph with the bands at rest. */
@media print {
	.od-hero { height: 640px !important; }
	.od-hero__gl { display: none !important; }
	.od-hero__still { display: block !important; }
}

/* ==========================================================================
   The middle of the page: "White and orange" (selected work, clients, the AI statement, services)
   ========================================================================== */
/* White pages set in large black type and one page of flat brand orange set in large white type. Every ground is
   one flat colour. On orange, white is kept for type of 24 px and more; anything smaller is black.

   Sizes per language, in em, measured with design/qa/home-3b-live/scripts/lengths.mjs (measure again when one of
   these texts or its translation changes): --od-sel-len is the longest word of "Selected work.", --od-claim-len
   the longer line of the AI statement set on two lines, --od-offer-a and --od-offer-b the longest service name of
   each column of the list with its slash. */
.od-main {
	--od-mid-w: calc(min(100vw, var(--od-max)) - 2 * var(--od-gutter));
	--od-mid-col: calc((var(--od-mid-w) - 11 * var(--od-gap)) / 12);
	--od-sel-len: 3.72; --od-claim-len: 8.96; --od-offer-a: 11.11; --od-offer-b: 13.12;
}
html[lang^="de"] .od-main { --od-sel-len: 5.61; --od-claim-len: 7.36; --od-offer-a: 14.64; --od-offer-b: 13.89; }
html[lang^="fr"] .od-main { --od-sel-len: 5.07; --od-claim-len: 11.03; --od-offer-a: 13.37; --od-offer-b: 12.95; }
html[lang^="es"] .od-main { --od-sel-len: 6.41; --od-claim-len: 9.63; --od-offer-a: 11.7; --od-offer-b: 14.95; }
html[lang^="it"] .od-main { --od-sel-len: 4.75; --od-claim-len: 10.58; --od-offer-a: 9.81; --od-offer-b: 12.9; }
html[lang^="pt"] .od-main { --od-sel-len: 5.89; --od-claim-len: 9.97; --od-offer-a: 14.04; --od-offer-b: 14.02; }

.od-mid-wrap { width: 100%; max-width: var(--od-max); margin-inline: auto; padding-inline: var(--od-gutter); }
.od-mid-h { margin: 0; font-size: var(--od-fs-h5); line-height: 1.15; font-weight: 600; letter-spacing: var(--od-track); }

/* ---------- Selected work ---------- */
.od-selected { padding: clamp(72px, 9.4vw, 136px) 0 clamp(72px, 9vw, 130px); background: var(--od-white); color: var(--od-black); }
.od-selected__grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--od-gap); align-items: start; }
.od-selected__head { grid-column: 1 / span 7; grid-row: 1; }
.od-selected__title {
	margin: -0.08em 0 0 -0.045em;
	font-size: min(calc((7 * var(--od-mid-col) + 6 * var(--od-gap)) / (var(--od-sel-len) * 1.1)), 20vh, 240px);
	line-height: 0.92; font-weight: 600; letter-spacing: -0.065em;
}
.od-selected__lead { margin: clamp(20px, 2.4vw, 34px) 0 14px; font-size: var(--od-fs-b1); line-height: 1.4; font-weight: 500; }

/* The pieces stand in the grid of the section: the list itself has no box. */
.od-pieces { display: contents; }
.od-piece { list-style: none; min-width: 0; }
.od-piece__link { display: block; color: inherit; text-decoration: none; }
.od-piece__link:focus-visible { outline: 2px solid var(--od-brand); outline-offset: 8px; }
.od-piece__frame { overflow: hidden; background: var(--od-grey-40); }
.od-piece__frame img { display: block; width: 100%; height: auto; transition: scale 0.9s var(--od-ease), clip-path 1s var(--od-ease); }
.od-piece__cap { position: relative; display: flex; flex-direction: column; gap: 4px; padding-top: 16px; }
.od-piece__cap::before { content: ">"; position: absolute; left: 0; top: -4px; font-family: var(--od-mono); font-weight: 500; letter-spacing: 0; font-size: 13px; line-height: 1; color: var(--od-brand-text); opacity: 0; translate: -6px 0; transition: opacity 0.3s var(--od-ease), translate 0.5s var(--od-ease); }
.od-piece__cap > * { margin: 0; }
.od-piece__client { font-size: var(--od-fs-b4); line-height: 1.4; font-weight: 600; }
.od-piece__name { width: fit-content; font-size: clamp(1.125rem, 0.95rem + 0.55vw, 1.5rem); line-height: 1.22; font-weight: 600; letter-spacing: var(--od-track); color: var(--od-grey-900); text-wrap: pretty; transition: color 0.3s var(--od-ease); }
.od-piece__meta { padding-top: 2px; font-size: var(--od-fs-b5); line-height: 1.7; color: var(--od-fg-mute); }
.od-piece__meta data:not(.od-piece__tag) + data:not(.od-piece__tag)::before { content: ", "; }
.od-piece__tag { display: inline-block; margin-left: 10px; padding: 0 8px; border: 1px solid currentColor; border-radius: 999px; font-size: 0.86em; line-height: 1.55; font-weight: 500; white-space: nowrap; }
.od-piece__meta time { margin-left: 10px; font-variant-numeric: tabular-nums; }
.od-piece__link:hover .od-piece__frame img, .od-piece__link:focus-visible .od-piece__frame img { scale: 1.04; }
.od-piece__link:hover .od-piece__cap::before, .od-piece__link:focus-visible .od-piece__cap::before { opacity: 1; translate: none; }
.od-piece__link:hover .od-piece__name, .od-piece__link:focus-visible .od-piece__name { color: var(--od-black); }
.od-piece__link:active .od-piece__frame img { scale: 1.02; transition-duration: 0.2s; }

/* A piece that is still below the window waits closed (assets/js/home.js marks it): its picture is uncovered from
   its foot while it settles, and the caption follows a moment later. */
.od-pieces-live .od-piece__cap { transition: opacity 0.6s var(--od-ease) 0.08s, translate 0.7s var(--od-ease) 0.08s; }
.od-pieces-live .od-piece.is-wait .od-piece__frame img { clip-path: inset(100% 0 0 0); scale: 1.08; }
.od-pieces-live .od-piece.is-wait .od-piece__cap { opacity: 0; translate: 0 16px; }

/* Leaving by a piece. The rest of the section steps back and dims, the part nearest to the chosen piece first
   (--od-out-i, set by the script), while the chosen picture lifts a little; the browser then grows it into the
   hero of the case study. Coming back, the parts come forward again in the opposite order (--od-out-r). */
.od-selected__head, .od-piece { transition: opacity 0.5s var(--od-ease), scale 0.7s var(--od-ease); transition-delay: calc(var(--od-out-r, 0) * 70ms + 120ms); }
.od-piece__frame { transition: translate 0.4s var(--od-ease), scale 0.4s var(--od-ease); }
html.od-piece-out .od-selected__head, html.od-piece-out .od-piece:not(.is-chosen) { opacity: 0.06; scale: 0.97; transition-duration: 0.24s, 0.36s; transition-delay: calc(var(--od-out-i, 0) * 45ms); }
html.od-piece-out .od-piece.is-chosen .od-piece__frame { translate: 0 -8px; scale: 1.012; }
html.od-piece-out .od-piece.is-chosen .od-piece__frame img { scale: 1.04; }
html.od-piece-out .od-piece.is-chosen .od-piece__cap::before { opacity: 1; translate: none; }
/* Back at the piece: its caption is set again, line after line, once the picture is home. */
.od-piece.is-back .od-piece__client, .od-piece.is-back .od-piece__name, .od-piece.is-back .od-piece__meta { animation: od-piece-cap 0.7s var(--od-ease) 0.5s backwards; }
.od-piece.is-back .od-piece__name { animation-delay: 0.58s; }
.od-piece.is-back .od-piece__meta { animation-delay: 0.66s; }
.od-piece.is-back .od-piece__cap::before { animation: od-piece-line 1.6s var(--od-ease) 0.5s backwards; }
@keyframes od-piece-cap { from { opacity: 0; translate: 0 12px; } }
@keyframes od-piece-line { 0% { opacity: 0; translate: -6px 0; } 35%, 70% { opacity: 1; translate: none; } 100% { opacity: 0; translate: -6px 0; } }

/* The way back from a case study: the hero narrows into the piece it grew from (named by the head script in
   inc/work.php). The mirror of the way in: the hero cuts the picture to its own shape and the piece shows it whole,
   and the two are cut alike only while the frame still has the hero's shape, so the piece's picture takes over at
   the very start and is the one that travels. With a mouse a hero printed by the cover shortcode had its picture
   set a little larger than its frame (the room for its drift): for such a piece (od-piece-drift on the page,
   from the piece's od-piece--drift) the picture starts at that size and settles to its own on the way. The
   words of the hero go where they stand. The way out is timed by the case study's own styles. */
@media (prefers-reduced-motion: no-preference) {
	::view-transition-group(od-cs-hero) { overflow: clip; animation-duration: 0.72s; animation-timing-function: cubic-bezier(0.5, 0, 0.1, 1); }
	::view-transition-old(od-cs-hero), ::view-transition-new(od-cs-hero) { height: 100%; object-fit: cover; mix-blend-mode: normal; animation-duration: 0.72s; animation-timing-function: linear; }
	::view-transition-old(od-cs-hero) { animation-name: od-piece-hero-out; }
	::view-transition-new(od-cs-hero) { animation-name: od-piece-hero-in; }
	::view-transition-old(od-cs-title), ::view-transition-old(od-cs-back), ::view-transition-old(od-cs-tags), ::view-transition-old(od-cs-lead) { animation-duration: 0.16s; }
}
@keyframes od-piece-hero-out { 0%, 10% { opacity: 1; } 10.01%, 100% { opacity: 0; } }
@keyframes od-piece-hero-in { 0% { opacity: 0; } 10%, 100% { opacity: 1; } }
@keyframes od-piece-hero-settle { from { scale: 1.16; } }
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
	html.od-piece-drift::view-transition-new(od-cs-hero) { animation: od-piece-hero-in 0.72s linear both, od-piece-hero-settle 0.72s cubic-bezier(0.5, 0, 0.1, 1) both; }
}

/* Wide windows: two stacks that do not line up. The heading stands over the widest piece; the first piece stands
   beside the heading (four columns when it is upright, five when it is wide) and over the third, which rests at
   the foot of its stack; a fourth piece stands alone under both, set in from the left. No piece is wider than two thirds of the window or taller than about three fifths
   of it: each takes the width of its place, or less where its own proportions would make it too tall. */
@media (min-width: 1000px) {
	.od-piece:nth-child(1) { grid-column: 9 / span 4; grid-row: 1 / span 2; justify-self: end; width: min(100%, calc(60vh * var(--od-piece-ar, 0.78))); }
	.od-piece--wide:nth-child(1) { grid-column: 8 / span 5; }
	.od-piece:nth-child(2) { grid-column: 1 / span 6; grid-row: 2 / span 2; margin-top: clamp(48px, 5.6vw, 80px); width: min(100%, calc(62vh * var(--od-piece-ar, 1.2))); }
	.od-piece:nth-child(3) { grid-column: 8 / span 5; grid-row: 3; align-self: end; justify-self: end; margin-top: clamp(56px, 6.6vw, 96px); width: min(100%, calc(60vh * var(--od-piece-ar, 1.8))); }
	.od-piece:nth-child(4) { grid-column: 3 / span 7; grid-row: 4; margin-top: clamp(72px, 8.4vw, 124px); width: min(100%, calc(62vh * var(--od-piece-ar, 1.6))); }
}

/* ---------- Our clients: one line that travels ---------- */
.od-patrons { padding: 0 0 clamp(72px, 9vw, 130px); background: var(--od-white); color: var(--od-black); overflow: hidden; }
.od-patrons__row { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--od-gap); align-items: center; }
.od-patrons__row::before { content: ""; grid-column: 1 / -1; height: 1px; background: var(--od-line); margin-bottom: clamp(36px, 4.4vw, 64px); }
.od-patrons__head { grid-column: 1 / span 3; }
.od-patrons__text { margin: 10px 0 0; max-width: 17em; font-size: var(--od-fs-b4); line-height: 1.5; color: var(--od-fg-mute); }
.od-patrons__line { grid-column: 4 / -1; min-width: 0; }

/* The line of marks. Still, it wraps inside its column and shows each client once (no scripts, reduced motion,
   print). When the script runs it (od-strip-on) it is one row that leaves through the right edge of the window,
   the set repeated behind itself; the script moves the row and brings it back by the length of one set. */
.od-strip { --od-strip-h: clamp(26px, 2.8vw, 44px); --od-strip-gap: clamp(40px, 5.6vw, 96px); }
.od-strip__track { display: flex; flex-wrap: wrap; align-items: center; gap: 28px var(--od-strip-gap); margin: 0; padding: 0; list-style: none; }
.od-strip__item { flex: none; display: flex; align-items: center; }
.od-strip__item[aria-hidden="true"] { display: none; }
.od-strip__link { display: block; color: inherit; transition: opacity 0.3s var(--od-ease); }
.od-strip__link:focus-visible { outline: 2px solid var(--od-brand); outline-offset: 6px; }
.od-strip__logo { display: block; width: auto; max-width: none; height: calc(var(--od-strip-h) * var(--od-strip-k, 1)); transition: scale 0.5s var(--od-ease); }
a.od-strip__link:hover .od-strip__logo, a.od-strip__link:focus-visible .od-strip__logo { scale: 1.07; }
.od-strip__name { font-size: calc(var(--od-strip-h) * 0.62); font-weight: 600; line-height: 1; letter-spacing: -0.03em; white-space: nowrap; }
.od-strip__track:hover .od-strip__link:not(:hover) { opacity: 0.35; }
.od-strip.od-strip-on { overflow: hidden; margin-block: -14px; padding-block: 14px; margin-right: calc((min(100vw, var(--od-max)) - 100vw) / 2 - var(--od-gutter)); }
.od-strip-on .od-strip__track { flex-wrap: nowrap; width: max-content; will-change: transform; }
/* Where the row leaves inside the page (the left edge of its column on wide windows) a mark thins out over its last
   steps instead of being cut; at the window's own edges it simply leaves. */
@media (min-width: 1000px) { .od-strip.od-strip-on { -webkit-mask-image: linear-gradient(to right, transparent, #000 64px); mask-image: linear-gradient(to right, transparent, #000 64px); } }
.od-strip-on .od-strip__item[aria-hidden="true"] { display: flex; }

/* ---------- The AI statement: one page of flat orange ---------- */
.od-claim { position: relative; overflow: clip; padding: clamp(64px, 7vw, 100px) 0 clamp(64px, 7.6vw, 110px); background: var(--od-brand); color: var(--od-white); }
.od-claim :focus-visible { outline-color: var(--od-black); }
.od-claim .od-mid-wrap { position: relative; }
.od-claim__ground { display: none; }
.od-claim__label { --od-lb-dim: rgba(0, 0, 0, 0.68); --od-lb-p: var(--od-black); margin: 0; color: var(--od-black); }
.od-claim__title {
	margin: clamp(22px, 2.6vw, 38px) 0 0 -0.045em;
	font-size: min(calc(var(--od-mid-w) / (var(--od-claim-len) * 1.04)), 22vh, 240px);
	line-height: 0.93; font-weight: 600; letter-spacing: -0.065em; text-wrap: balance;
}
.od-claim__foot { margin-top: clamp(44px, 6.4vw, 92px); display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--od-gap); align-items: end; }
.od-claim__text { grid-column: 7 / -1; margin: 0; font-size: 24px; line-height: 1.34; font-weight: 500; letter-spacing: -0.03em; }
.od-claim__links { grid-column: 1 / span 5; margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.od-claim__go { display: inline-flex; align-items: center; gap: 12px; font-size: 24px; line-height: 1.4; font-weight: 500; letter-spacing: -0.03em; color: inherit; white-space: nowrap; transition: translate 0.2s var(--od-ease); }
.od-claim__go::before { content: ""; flex: none; width: 1.1em; height: 1.1em; background: currentColor; -webkit-mask: url(../../icons/arrow-turn.svg) center / contain no-repeat; mask: url(../../icons/arrow-turn.svg) center / contain no-repeat; transition: margin 0.25s var(--od-ease); }
.od-claim__go:hover::before, .od-claim__go:focus-visible::before { margin-right: 8px; }
.od-claim__go:active { translate: 0 1px; }

/* The words of the statement, each in a mask of its own (made by assets/js/home.js), with room for descenders and
   for the tight tracking inside the mask. */
.od-claim__w { display: inline-block; overflow: hidden; vertical-align: top; padding: 0.08em 0.06em 0.17em; margin: -0.08em -0.06em -0.17em; }
.od-claim__wi { display: inline-block; }

/* The arrival, where the script runs it (od-claim-live). The words wait until the ground stands (is-ground), then
   are written in turn: the label, the statement word by word, the paragraph, the links; they are taken back at
   once if the ground leaves again. With a mouse on a wide window (od-claim--rise) the ground itself is a layer
   that comes up from below, faster than the page, to meet the head of the section, and at the foot the white of
   the next section comes up over the last empty lines the same way; both are moved by transform. Text is only
   ever written on ground that has arrived. */
html.od-claim-live .od-claim__label, html.od-claim-live .od-claim__text, html.od-claim-live .od-claim__links { opacity: 0; translate: 0 16px; transition: opacity 0.16s linear, translate 0s linear 0.16s; }
html.od-claim-live .od-claim__wi { transform: translate3d(0, 112%, 0); transition: transform 0.2s var(--od-ease); }
html.od-claim-live .od-claim.is-ground .od-claim__label { opacity: 1; translate: none; transition: opacity 0.5s var(--od-ease), translate 0.7s var(--od-ease); }
html.od-claim-live .od-claim.is-ground .od-claim__wi { transform: none; transition: transform 0.85s var(--od-ease) calc(var(--od-i, 0) * 60ms + 90ms); }
html.od-claim-live .od-claim.is-ground .od-claim__text { opacity: 1; translate: none; transition: opacity 0.6s var(--od-ease) calc(var(--od-claim-n, 7) * 60ms + 260ms), translate 0.8s var(--od-ease) calc(var(--od-claim-n, 7) * 60ms + 260ms); }
html.od-claim-live .od-claim.is-ground .od-claim__links { opacity: 1; translate: none; transition: opacity 0.6s var(--od-ease) calc(var(--od-claim-n, 7) * 60ms + 380ms), translate 0.8s var(--od-ease) calc(var(--od-claim-n, 7) * 60ms + 380ms); }
/* The keyboard never waits for the writing: with the focus inside the section everything stands at once. */
html.od-claim-live .od-claim:focus-within .od-claim__label, html.od-claim-live .od-claim:focus-within .od-claim__text, html.od-claim-live .od-claim:focus-within .od-claim__links { opacity: 1; translate: none; transition: opacity 0.12s linear; }
html.od-claim-live .od-claim:focus-within .od-claim__wi { transform: none; transition: transform 0.2s var(--od-ease); }
html.od-claim-live .od-claim--rise { background: var(--od-white); }
html.od-claim-live .od-claim--rise .od-claim__ground { display: block; position: absolute; inset: 0; background: var(--od-brand); transform: translate3d(0, var(--od-claim-in, 0px), 0); will-change: transform; }
html.od-claim-live .od-claim--rise::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 240px; background: var(--od-white); transform: translate3d(0, calc(var(--od-claim-out, 0px) * -1), 0); }

/* ---------- Our services: the list ---------- */
.od-offer { padding: clamp(72px, 9vw, 130px) 0 clamp(80px, 10vw, 144px); background: var(--od-white); color: var(--od-black); }
.od-offer__grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--od-gap); align-items: start; }
.od-offer__head { grid-column: 1 / span 3; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.od-offer__list { grid-column: 4 / -1; position: relative; min-width: 0; }
.od-offer__names { position: relative; list-style: none; margin: 0; padding: 0; }
.od-offer__bar { display: none; }
.od-offer__name { margin: 0; font-weight: 500; letter-spacing: -0.05em; }
.od-offer__name a { color: inherit; display: block; }
/* The slash is a mark, not a word: it is not read out (the second declaration, where the browser knows it). */
.od-offer__name a::before { content: "/"; content: "/" / ""; display: inline-block; margin-right: 0.2em; color: var(--od-brand); }
.od-offer__text { margin: 0; }

/* With a mouse on a wide window: two columns, each as wide as its longest name. The lit name stands on a bar of
   orange in white (never under 24 px: below 1100 px of width the longest names would need less, so the list takes
   its other layout there) and its sentence is read at the foot of the left column, which is kept tall enough for
   the longest sentence in any language. One name is lit at a time: the one the pointer was last on or the one with
   the focus (assets/js/home.js keeps it lit); without the script the pointer and the keyboard light a name
   through the rules that follow. */
@media (min-width: 1100px) and (hover: hover) {
	.od-offer { --od-offer-fs: max(24px, min(calc((9 * var(--od-mid-col) + 7 * var(--od-gap) - 52px) / (var(--od-offer-a) + var(--od-offer-b))), 5.6vh, 48px)); --od-offer-row: calc(var(--od-offer-fs) * 1.34); }
	.od-offer__names { display: grid; grid-template-columns: calc(var(--od-offer-a) / (var(--od-offer-a) + var(--od-offer-b)) * (100% - var(--od-gap))) minmax(0, 1fr); column-gap: var(--od-gap); grid-auto-flow: column; grid-template-rows: repeat(6, var(--od-offer-row)); margin-top: calc(var(--od-offer-fs) * -0.2); min-height: calc(var(--od-fs-h5) * 1.15 + var(--od-fs-b3) * 1.6 + 36px + var(--od-fs-b3) * 1.4 * 8); }
	.od-offer__item--a { grid-column: 1; }
	.od-offer__item--b { grid-column: 2; }
	.od-offer__name { font-size: var(--od-offer-fs); line-height: var(--od-offer-row); white-space: nowrap; }
	.od-offer__name a { padding: 0 12px; margin-left: -12px; outline-offset: -2px; transition: translate 0.2s var(--od-ease); }
	.od-offer__name a:active { translate: 3px 0; }
	.od-offer__item.is-lit .od-offer__name a { background: var(--od-brand); color: var(--od-white); }
	.od-offer__item.is-lit .od-offer__name a::before { color: var(--od-white); }
	.od-offer__item.is-lit .od-offer__name a:focus-visible { outline-color: var(--od-black); }
	.od-offer__text { position: absolute; left: calc(-33.333% - var(--od-gap) / 3); bottom: 0.3em; width: calc(33.333% - var(--od-gap) * 2 / 3); padding-right: 6%; max-width: 17em; font-size: var(--od-fs-b3); line-height: 1.4; font-weight: 500; letter-spacing: -0.02em; visibility: hidden; }
	.od-offer__item.is-lit .od-offer__text { visibility: visible; }
	html:not(.od-offer-on) .od-offer__names:hover .od-offer__item.is-lit:not(:hover) .od-offer__name a, html:not(.od-offer-on) .od-offer__names:focus-within .od-offer__item.is-lit:not(:focus-within) .od-offer__name a { background: none; color: inherit; }
	html:not(.od-offer-on) .od-offer__names:hover .od-offer__item.is-lit:not(:hover) .od-offer__name a::before, html:not(.od-offer-on) .od-offer__names:focus-within .od-offer__item.is-lit:not(:focus-within) .od-offer__name a::before { color: var(--od-brand); }
	html:not(.od-offer-on) .od-offer__names:hover .od-offer__item.is-lit:not(:hover) .od-offer__text, html:not(.od-offer-on) .od-offer__names:focus-within .od-offer__item.is-lit:not(:focus-within) .od-offer__text { visibility: hidden; }
	html:not(.od-offer-on) .od-offer__item:hover .od-offer__name a, html:not(.od-offer-on) .od-offer__item:focus-within .od-offer__name a { background: var(--od-brand); color: var(--od-white); }
	html:not(.od-offer-on) .od-offer__item:hover .od-offer__name a::before, html:not(.od-offer-on) .od-offer__item:focus-within .od-offer__name a::before { color: var(--od-white); }
	html:not(.od-offer-on) .od-offer__item:hover .od-offer__text, html:not(.od-offer-on) .od-offer__item:focus-within .od-offer__text { visibility: visible; }

	/* Where the script runs with motion (od-offer-live): the orange is one bar that travels to the lit name, moved
	   and stretched by transform. A name turns white only when the bar has reached it and black again the moment it
	   is left (black reads on the orange, white would not read on the white), so no name is ever white on white.
	   The sentence of the lit name is written from its first line down; the one before it goes at once. */
	html.od-offer-live .od-offer__bar { display: block; position: absolute; z-index: 0; left: 0; top: 0; width: 100px; background: var(--od-brand); transform-origin: 0 0; transition: transform 0.42s var(--od-ease); pointer-events: none; }
	html.od-offer-live .od-offer__names { z-index: 1; }
	html.od-offer-live .od-offer__name a { transition: color 0.08s linear, translate 0.2s var(--od-ease); }
	html.od-offer-live .od-offer__name a::before { transition: color 0.08s linear; }
	html.od-offer-live .od-offer__item.is-lit .od-offer__name a { background: none; transition: color 0.16s linear 0.2s, translate 0.2s var(--od-ease); }
	html.od-offer-live .od-offer__item.is-lit .od-offer__name a::before { transition: color 0.16s linear 0.2s; }
	html.od-offer-live .od-offer__text { visibility: visible; opacity: 0; clip-path: inset(0 0 100% 0); translate: 0 8px; pointer-events: none; transition: opacity 0.1s linear, clip-path 0s linear 0.1s, translate 0s linear 0.1s; }
	html.od-offer-live .od-offer__item.is-lit .od-offer__text { opacity: 1; clip-path: inset(0 0 -12% 0); translate: none; transition: opacity 0.2s linear 0.12s, clip-path 0.6s var(--od-ease) 0.12s, translate 0.6s var(--od-ease) 0.12s; }
	/* The name that is followed leaves in one ink, in a box that fits its words, as the heading it becomes. */
	.od-offer__name a.is-flying { width: fit-content; padding: 0; margin: 0; background: none !important; color: var(--od-black) !important; transition: none !important; }
	.od-offer__name a.is-flying::before { content: none; }
}

/* Narrow windows and touch screens: every sentence stands under its name, nothing is lit. */
@media (max-width: 1099px), (hover: none) {
	.od-offer__grid { grid-template-columns: minmax(0, 1fr); row-gap: clamp(28px, 5vw, 44px); }
	.od-offer__head, .od-offer__list { grid-column: 1; }
	.od-offer__head { flex-direction: row; justify-content: space-between; align-items: baseline; }
	.od-offer__names { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: 20px; }
	.od-offer__name { font-size: min(calc((var(--od-mid-w) - 4px) / max(var(--od-offer-a), var(--od-offer-b))), 40px); line-height: 1.2; white-space: nowrap; }
	.od-offer__text { margin-top: 5px; max-width: 30em; font-size: var(--od-fs-b4); line-height: 1.5; color: var(--od-fg-mute); }
	/* Names can be a little under 24 px here: the slash takes the deeper orange of small orange text. */
	.od-offer__name a::before { color: var(--od-brand-text); }
}
@media (min-width: 700px) and (max-width: 1099px), (min-width: 700px) and (hover: none) {
	.od-offer__names { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--od-gap); grid-auto-flow: column; grid-template-rows: repeat(6, auto); row-gap: 26px; }
	.od-offer__name { font-size: min(calc((var(--od-mid-w) / 2 - 16px) / max(var(--od-offer-a), var(--od-offer-b))), 40px); }
	.od-offer__text { padding-right: 12%; }
}

@media (max-width: 999px) {
	.od-selected__head, .od-piece { grid-column: 1 / -1; }
	.od-selected__title { font-size: min(calc(var(--od-mid-w) / (var(--od-sel-len) * 1.06)), 150px); }
	.od-piece:nth-child(2) { order: 1; margin-top: 44px; }
	.od-piece:nth-child(1) { order: 2; margin: 56px 0 0 26%; }
	.od-piece:nth-child(3) { order: 3; margin: 56px 12% 0 0; }
	.od-piece:nth-child(4) { order: 4; margin: 56px 0 0; }

	.od-patrons__row { row-gap: 32px; }
	.od-patrons__head, .od-patrons__line { grid-column: 1 / -1; }
	.od-strip { --od-strip-h: 32px; --od-strip-gap: 44px; }
	.od-strip.od-strip-on { margin-inline: calc(var(--od-gutter) * -1); }

	.od-claim__title { font-size: min(calc(var(--od-mid-w) / (var(--od-claim-len) * 0.62)), 150px); }
	.od-claim__foot { grid-template-columns: minmax(0, 1fr); row-gap: 32px; }
	.od-claim__text, .od-claim__links { grid-column: 1; }
	.od-claim__text { order: 1; max-width: 26em; }
	.od-claim__links { order: 2; }
}
@media (min-width: 700px) and (max-width: 999px) {
	.od-piece:nth-child(2) { margin-right: 24%; }
	.od-piece:nth-child(1) { margin-left: 52%; margin-top: -18%; }
	.od-piece:nth-child(3) { margin-right: 36%; }
	.od-piece:nth-child(4) { margin-left: 20%; }
}

@media (prefers-reduced-motion: reduce) {
	.od-piece, .od-selected__head, .od-piece__frame, .od-piece__frame img, .od-piece__cap::before, .od-piece__name, .od-claim__go, .od-claim__go::before, .od-strip__link, .od-strip__logo, .od-offer__name a { transition: none; }
	.od-piece.is-back .od-piece__client, .od-piece.is-back .od-piece__name, .od-piece.is-back .od-piece__meta, .od-piece.is-back .od-piece__cap::before { animation: none; }
}
/* Print: the statement in black on the sheet, the list in full with every sentence, each client once. */
@media print {
	.od-claim, html.od-claim-live .od-claim--rise { background: none; color: #000; }
	.od-claim__ground, html.od-claim-live .od-claim--rise .od-claim__ground, html.od-claim-live .od-claim--rise::after { display: none !important; }
	html.od-claim-live .od-claim__label, html.od-claim-live .od-claim__text, html.od-claim-live .od-claim__links { opacity: 1 !important; translate: none !important; }
	html.od-claim-live .od-claim__wi { transform: none !important; }
	.od-pieces-live .od-piece.is-wait .od-piece__frame img { clip-path: none !important; scale: none !important; }
	.od-pieces-live .od-piece.is-wait .od-piece__cap, html.od-piece-out .od-selected__head, html.od-piece-out .od-piece { opacity: 1 !important; translate: none !important; scale: none !important; }
	.od-offer__bar { display: none !important; }
	html.od-offer-live .od-offer__text { opacity: 1 !important; clip-path: none !important; translate: none !important; }
	.od-strip.od-strip-on { overflow: visible; margin: 0; padding: 0; -webkit-mask-image: none; mask-image: none; }
	.od-strip-on .od-strip__track { flex-wrap: wrap; width: auto; transform: none !important; }
	.od-strip-on .od-strip__item[aria-hidden="true"] { display: none; }
	.od-offer__item .od-offer__name a { background: none !important; color: #000 !important; }
	.od-offer__item .od-offer__name a::before { color: var(--od-brand) !important; }
	.od-offer__names { display: block; margin: 0; }
	.od-offer__name { font-size: 20px; line-height: 1.4; }
	.od-offer__text { position: static; visibility: visible !important; width: auto; max-width: none; padding: 0 0 8px; font-size: 12px; font-weight: 400; }
}
@media (forced-colors: active) {
	.od-offer__item.is-lit .od-offer__name a { outline: 2px solid; }
}
