/* ---------------------------------------------------------------------------
   Case-study boards

   Loaded on single portfolio pages by inc/case-studies.php.

   Sized by container query, not viewport. A board sits inside a builder module
   that is half the grid on a desktop page and full width on a phone, so the
   space it actually has bears no fixed relation to the window — at 1024px the
   module is around 510px wide and wants one column, while the same viewport in
   a full-width module wants two. Querying the board's own width gets this right
   without hard-coding which module it was dropped into.

   container-type is inline-size, never size: the boards sit among modules whose
   height comes from padding ratios, and size containment would collapse those
   to nothing. Single column is the default, so a browser without container
   query support gets the stacked layout rather than a broken one.
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   The two title sizes

   Every title on a project page sets at one of these. Viewport units rather
   than container units so a title inside a board and a title in a plain text
   module land on the same number — cqi resolves against the nearest container,
   and the plain modules have none, so the same clamp would have given 19.2px
   inside a board and 24px outside it at the same window width.

   1.5vw is the desktop figure the boards were already at (19.2px at 1280px),
   so the large size changes nothing on the boards and brings the rest of the
   page to them. The small size is one step down for the title of a short
   credit — Role, Timeline — rather than a section.
   --------------------------------------------------------------------------- */

body.single-portfolio {
	--cs-title-lg: clamp( 19px, 1.5vw, 24px );
	--cs-title-sm: clamp( 17px, 1.33vw, 21px );

	/* Body copy, one size at every width. On a phone the child theme already
	   floors ".copy p" at 16px; on desktop the theme sets paragraphs to 15px
	   and leaves list items alone, so the boards' lists sat at 16px beside
	   15px paragraphs. 16px everywhere is what the phone was already doing. */
	--cs-body: 16px;
}

.cs-board {
	container-type: inline-size;

	/* A grid with one item, so the inner box stretches to the board. Side by
	   side, .cs-boards stretches a pair to one height, but the board's inner
	   box only ever took its own content height — so the shorter board's
	   content sat at the head of its panel and its centring and end-aligning
	   had nothing to work against. Stretched, they do. */
	display: grid;

	/* The board's palette, as properties so a project can restate it in one
	   place. The defaults are One Medical's: dark teal with white type and a
	   white chip. Every colour a board paints reads from these. */
	--cs-board-bg: #005450;
	--cs-board-fg: #fff;
	--cs-chip-bg: #fff;
	--cs-chip-fg: #005450;

	background-color: var( --cs-board-bg );
	color: var( --cs-board-fg );
}

/* Personalizing Amazon's boards: the pale sky and slate the artwork used,
   with the chip in the slate. */
.cs-board--sky {
	--cs-board-bg: #e1effb;
	--cs-board-fg: #3e555c;
	--cs-chip-bg: #3e555c;
	--cs-chip-fg: #fff;
}

/* The "Discovering opportunity" boards: the artwork's wash, which runs from
   a light blue at the top through a deeper one at the middle and back, so
   two boards stacked meet light on light and read as one. Near-black type
   and a slate chip, both sampled. */
.cs-board--blue {
	--cs-board-bg: #aad8f3;
	--cs-board-fg: #191919;
	--cs-chip-bg: #2a373a;
	--cs-chip-fg: #fff;

	background-image: linear-gradient( to bottom, #aad8f3, #74bfeb 49%, #aad7f3 );
}

/* The wireframe boards: white, as the artwork was, with the page's type
   colour and the chip in the dark teal a chip takes on a white module. */
.cs-board--white {
	--cs-board-bg: #fff;
	--cs-board-fg: #191919;
	--cs-chip-bg: #002927;
	--cs-chip-fg: #fff;
}

/* The wireframe flow: the artwork's light grey. */
.cs-board--grey {
	--cs-board-bg: #f4f4f4;
	--cs-board-fg: #323232;
	--cs-chip-bg: #002927;
	--cs-chip-fg: #fff;
}

.cs-board__inner {
	display: grid;
	gap: 32px;
	align-items: center;

	/* 6.5% horizontal, which is what lines the board's copy up with the body
	   copy above and below it.

	   The module used to supply that inset and this was 0. It cannot any more:
	   the panel is full-bleed, so the copy wrapper's width limit and side
	   margins were lifted to let the colour reach both edges, and the text went
	   with them. What the other sections actually inset by is the module's own
	   11.27px of padding plus 22.98px of margin on the copy wrapper — 34px on a
	   375px screen. The module padding still applies here, so the board only
	   has to make up the difference, and 22.98px of a 353px panel is 6.5%.

	   A percentage rather than 23px so it tracks the theme's own measure, which
	   is itself proportional. Only the stacked case: the container query below
	   replaces this padding outright once a board has room for two columns. */
	padding: 34px 6.5% 40px;
}

/* 520px, measured rather than guessed: inside a half-grid module the board is
   557px wide at a 1280px window and around 440px at 1024px. A 560px threshold
   sat just above the first of those, so a 1280px desktop got the stacked
   layout; 520px puts the split where the board actually has room for it and
   still leaves 1024px stacked, where two columns would be too tight.

   The copy column, stacked, is the thing worth reading first — so the figure
   follows it in the markup and the wide layout reorders instead. */
@container ( min-width: 520px ) {

	.cs-board__inner {
		grid-template-columns: 1fr 1fr;
		gap: clamp( 28px, 5cqi, 56px );
		padding: clamp( 36px, 6cqi, 72px );
	}

	.cs-board--media-first .cs-board__media {
		order: -1;
	}

}

/* ---------------------------------------------------------------------------
   Type

   Everything is in rem or a clamp with a floor at or above 16px. The whole
   point of the rebuild is that this copy stops being 8px artwork on a phone,
   so nothing here is allowed to scale below reading size.
   --------------------------------------------------------------------------- */

/* A chip, on the same terms as the skill chips on the About page: fully
   rounded at 999px, 13.5px, 7px by 15px. Matching those rather than inventing a
   second chip treatment means the site has one idea of what a chip is.

   Selected through .cs-board and the element name to outweigh the child theme's
   own "body .module div.copy p", which forces 16px on phones so body copy stays
   legible. That rule is inside a phone media query, so without this the chip
   would have set at 13.5px on desktop and 16px on a phone — larger on the
   smaller screen. The badge is a <p> only because the builder's editor writes
   paragraphs; it is not body copy and should not inherit the floor meant for
   it. */
.cs-board .cs-board__text p.cs-step,
#content-wrapper .copy p.cs-chip {
	display: inline-block;
	margin: 0 0 16px;
	padding: 7px 15px;
	border-radius: 999px;
	background-color: var( --cs-chip-bg, #fff );
	color: var( --cs-chip-fg, #005450 );
	font-weight: 700;
	font-size: 13.5px;
	line-height: 1.35;
}

/* The same chip on a white module, in the dark teal the old "Step 2" badge
   artwork was drawn in (#002927, sampled from it) so it reads as the label it
   replaces rather than a new element. Selected through #content-wrapper for the
   same reason as the board chip: the phone-only 16px floor on ".copy p" would
   otherwise take it. */
#content-wrapper .copy p.cs-chip {
	background-color: #002927;
	color: #fff;
}

/* Every heading on a board sets at one size — the board titles included. They
   were a step larger, which read as a hierarchy the boards do not have: each is
   a short label over its own short block, not a section containing the others.

   font-family: inherit because the theme sets Playfair on h1-h6 by element
   name, and the boards declared no family at all, so that rule won by default.
   These are sans in the artwork and should match the body they sit with;
   inheriting avoids naming a stack that would then have to be kept in step with
   the theme's. */
.cs-board__heading {
	margin: 0 0 10px;
	font-family: inherit;
	color: var( --cs-board-fg );
	font-weight: 700;
	font-size: var( --cs-title-lg );
	line-height: 1.25;
}

/* A line under a board title that names what follows — "Existing UX &
   Research Insights" under "Research" — at the small title size, so the two
   read as title and subtitle rather than two titles. */
.cs-board__subheading {
	margin: 0 0 22px;
	font-family: inherit;
	color: var( --cs-board-fg );
	font-weight: 700;
	font-size: var( --cs-title-sm );
	line-height: 1.3;
}

.cs-board__heading + .cs-board__subheading {
	margin-top: 18px;
}

.cs-board__text p:not( .cs-step ) {
	margin: 0 0 26px;
	color: var( --cs-board-fg );
	font-size: var( --cs-body );
	line-height: 1.55;
}

.cs-board__text p:not( .cs-step ):last-child {
	margin-bottom: 0;
}

/* ---------------------------------------------------------------------------
   Icon lists

   The icons carried meaning in the artwork, so they are kept — as Font Awesome
   duotone, matching the icon language introduced in the main menu. They are
   decorative here though: every one sits beside a label that already says the
   same thing, so they are aria-hidden in the markup and the list reads cleanly
   without them.

   Grid rather than flex so the labels align to one another when a question
   wraps to two lines, instead of each label indenting to its own icon.
   --------------------------------------------------------------------------- */

.cs-icon-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.cs-icon-list li {
	display: grid;
	grid-template-columns: 1.5em 1fr;
	gap: .7em;
	align-items: start;
	margin: 0 0 18px;
	color: var( --cs-board-fg );
	font-size: var( --cs-body );
	line-height: 1.4;
}

.cs-icon-list li:last-child {
	margin-bottom: 0;
}

.cs-icon-list svg,
.cs-icon-list i {
	/* Both dimensions, not just width. Font Awesome's own rule sets height to
	   1em, so a 1.5em-wide box just letterboxed the glyph back down to 1em and
	   the icons came out markedly smaller than the artwork's. */
	width: 1.5em;
	height: 1.5em;

	/* Nudged down so the glyph centres on the first line of its label rather
	   than on the cap height. */
	margin-top: .04em;
	--fa-secondary-opacity: .5;
}

/* ---------------------------------------------------------------------------
   Numbered findings

   A list of findings keyed to markers drawn on a screenshot: a ring with the
   number, a bold title beside it, the finding under both. The ring is the
   board's text colour outlined, not filled, matching the markers on the
   phone so the eye pairs them. Grid so the titles and bodies align to one
   another whatever the ring's width.
   --------------------------------------------------------------------------- */

.cs-findings {
	margin: 0;
	padding: 0;
	list-style: none;
}

.cs-finding {
	display: grid;
	grid-template-columns: 2em 1fr;
	column-gap: .6em;
	align-items: center;
	margin: 0 0 24px;
	color: var( --cs-board-fg );
	font-size: var( --cs-body );
	line-height: 1.55;
}

.cs-finding:last-child {
	margin-bottom: 0;
}

.cs-finding__n {
	display: grid;
	place-items: center;
	box-sizing: border-box;
	width: 2em;
	height: 2em;
	border: 2px solid currentColor;
	border-radius: 999px;
	font-size: .875em;
	font-weight: 700;
	line-height: 1;
}

.cs-finding__title {
	font-size: 1.0625em;
	font-weight: 700;
	line-height: 1.3;
}

.cs-finding__body {
	grid-column: 2;
	margin-top: 4px;
}

/* ---------------------------------------------------------------------------
   A board that stacks: copy over a row of examples

   The "Discovering opportunity" boards put their text across the top and two
   phone mockups under it, rather than beside it. One column at every width,
   so the container query's two columns are stood down; the examples make
   their own row.
   --------------------------------------------------------------------------- */

.cs-board__inner--stack {
	grid-template-columns: 1fr;
	grid-template-rows: auto 1fr;
	gap: 28px;

	/* Side by side the two boards are stretched to one height, and their
	   text blocks are not the same height — a callout on one, a chip and a
	   line of copy on the other. The examples sit at the foot of their
	   board, so the two rows of phones line up across the pair whatever the
	   text above them does; the copy is a one-row auto track above. */
	align-items: end;
}

/* A lighter panel inside a board, for the themes the examples share. The
   fill is the artwork's, a step lighter than the wash it sits on. */
.cs-board__callout {
	box-sizing: border-box;
	padding: 22px 26px 24px;
	border-radius: 18px;
	background-color: #aedbf6;
}

.cs-board__callout .cs-board__heading {
	margin-bottom: 14px;
}

/* The icons in the themes panel: the type colour, as the artwork drew
   them, with the duotone's secondary layer lighter than the list default
   so the grey reads as a tint rather than a second weight of black. The
   award glyph draws its ribbon above the top of its own viewBox — its
   paths start at y -32 in a 0-512 box — and the kit clips the svg to that
   box, so the ribbon lost its top; letting the svg overflow shows it. */
.cs-board__callout .cs-icon-list svg,
.cs-board__callout .cs-icon-list i {
	overflow: visible;
	--fa-secondary-opacity: .3;
}

/* An icon list laid across rather than down, where the board has room. */
@container ( min-width: 520px ) {
	.cs-icon-list--row {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: 28px;
	}

	.cs-icon-list--row li {
		margin-bottom: 0;
	}
}

/* Two examples across at every width, as the artwork had them: the phones
   are pictures, not text to read, and the captions under them are live. */
.cs-examples {
	display: grid;
	/* minmax(0, 1fr), not 1fr: a bare 1fr floors each column at its
	   min-content, and a long word in one caption was buying that column
	   20px from the other, so the two phones set at different sizes. */
	grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1fr );
	gap: 20px 16px;
	margin: 0;
	padding: 0;
	list-style: none;
}

@container ( min-width: 520px ) {
	.cs-examples {
		gap: 24px 32px;
	}
}

.cs-example__media {
	margin: 0 0 12px;
}

.cs-example__media img {
	display: block;
	width: 100%;
	height: auto;
}

/* The caption pairs the ring with its line the way the findings do; the
   body-copy rule leaves it alone by name so it can sit a step under 16px
   where two share a phone's width. */
.cs-board .cs-board__inner--stack p.cs-example__caption {
	display: grid;
	grid-template-columns: 2em 1fr;
	column-gap: .5em;
	align-items: start;
	margin: 0;
	color: var( --cs-board-fg );
	font-size: 15px;
	line-height: 1.4;
}

.cs-example__caption .cs-finding__n {
	font-size: .8em;
	margin-top: .1em;
}

@container ( min-width: 520px ) {
	.cs-board .cs-board__inner--stack p.cs-example__caption {
		font-size: var( --cs-body );
	}
}

/* A wireframe with its name over it — "Homepage", "Search results" — in
   the grey the artwork labelled them in, left-aligned to the frame. Both
   classes, to outweigh the media rule's centring, which is declared later. */
.cs-board__media.cs-wire {
	text-align: left;
}

.cs-wire__label {
	margin: 0 0 10px;
	color: #6a6a6a;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
}

/* Each wireframe is cropped with its marker and shadow, so the frame's own
   left edge sits some way into the image — a different way for each. The
   figure carries that as --wire-inset, measured from the crop as a share
   of its width, and the label starts there: on the frame, not the image. */
.cs-wire__label {
	padding-left: var( --wire-inset, 0 );
}

/* Narrow, the wireframe is held to 320px and centred by the media rules;
   the label follows it to the same width so the two stay aligned. */
.cs-wire__label {
	max-width: 320px;
	margin-left: auto;
	margin-right: auto;
}

@container ( min-width: 520px ) {
	.cs-wire__label {
		max-width: none;
	}
}

/* The product goals: the findings ring with a letter in it and one line
   beside it, in the body weight — a goal is a phrase, not a heading. */
.cs-findings--goals .cs-finding {
	align-items: center;
	margin-bottom: 16px;
}

.cs-findings--goals .cs-finding__title {
	font-size: var( --cs-body );
	font-weight: 400;
	line-height: 1.4;
}

/* The key to the landing-page markers: the three lines across, where the
   board has room, so they read as a legend rather than a list. */
@container ( min-width: 520px ) {
	.cs-findings--key {
		display: grid;
		grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
		column-gap: 16px;
	}

	.cs-findings--key .cs-finding {
		margin-bottom: 0;
	}
}

/* The landing-layouts board sits beside the grey journey panel on desktop,
   and the two modules share a top. The panel is a painted box, so its edge
   is where it starts; the board is white on white, so what reads as its
   start is the cap line of its title — which the 43px padding and the
   line box's own leading put 49px under the panel's edge. No padding
   over the title here, and the title pulled up by the 6px between its line
   box and its cap line, so the two tops meet. */
@media only screen and ( min-width: 961px ) {
	.cs-board--landing .cs-board__inner {
		padding-top: 0;
	}

	.cs-board--landing .cs-board__text > .cs-board__heading:first-child {
		margin-top: -6px;
	}
}

/* A stacked board whose only content is the example row — the search
   wireframes — spans both rows and sits at the head of the board, so its
   labels and frames top-align with the Homepage wireframe in the board
   beside it, which is taller and so already at the head of its own. */
.cs-board__inner--stack > .cs-examples:only-child {
	grid-row: 1 / -1;
	align-self: start;
}

/* The search wireframes: one under the other where the board is narrow, each
   held to the 320px the homepage wireframe above them sets, so a phone reads
   the three as one stack of same-sized frames rather than one frame over two
   half-width ones. The row gap is 44px: the homepage board's 40px foot plus
   the 4px head the stacked-boards rule below leaves the search board, so the
   three frames run down the panel evenly spaced. Two across, as the artwork
   had them, once the board has room. */
.cs-examples--wires {
	grid-template-columns: minmax( 0, 1fr );
	gap: 44px;
}

.cs-examples--wires .cs-example__media {
	margin-bottom: 0;
}

.cs-examples--wires .cs-example__media img {
	max-width: 320px;
	margin: 0 auto;
}

@container ( min-width: 520px ) {
	.cs-examples--wires {
		grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1fr );
		gap: 24px 32px;
	}

	.cs-examples--wires .cs-example__media img {
		max-width: 100%;
	}
}

/* ---------------------------------------------------------------------------
   The journey as wireframes

   Five wireframes with tap points, and arrows from each tap to the next
   screen. Wide, the five stand in a row and the arrows are an SVG laid over
   the row. The SVG's coordinate space is 100 units across, and the row is
   built to match it: five columns of 16 units with 5-unit gaps, images at
   their own aspect (2.044), and a foot of 9 units under them for the arrows
   to run along — so every unit is 1% of the row's width and the paths land
   on their tap points whatever the row's size. The labels over the frames
   are lifted out of the flow for the same reason: their height is type,
   not a fraction of the width, so the row reserves a fixed 32px for them
   and the SVG starts under that.

   Narrow, the frames run down the page in order, each 64 units of its
   step's width with a lane beside it and a foot of 20 under it, and each
   frame that has a next one carries its own SVG in that space — from the
   tap point out into the lane, down past the foot, back to the frame's
   centre and down towards the next. The row's SVG is not shown.
   --------------------------------------------------------------------------- */

.cs-flowboard .cs-board__text {
	margin-bottom: 0;
}

.cs-flowboard__stage {
	position: relative;
}

.cs-flowboard__steps {
	margin: 0;
	padding: 0;
	list-style: none;
}

.cs-flowboard__step {
	margin: 0;
}

.cs-flowboard__step .cs-wire {
	margin: 0;
}

.cs-flowboard__frame {
	position: relative;
	padding-bottom: 20%;
}

.cs-flowboard__step img {
	display: block;
	width: 64%;
	height: auto;
}

/* The crop carries 10px of ground around the frame on its 409px canvas, so
   the frame's own edge sits that far inside the image; the label over it
   starts there too — 10 / 409 of the image's 64% — rather than at the
   image edge, where it looked a step to the left of the phone. */
.cs-flowboard__step .cs-wire__label {
	margin-left: 1.56%;
}

.cs-flowboard__arrow {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: auto;
	overflow: visible;
	pointer-events: none;
}

.cs-flowboard__arrows {
	display: none;
}

.cs-flowboard__arrow path,
.cs-flowboard__arrows path {
	vector-effect: non-scaling-stroke;
}

@container ( min-width: 760px ) {

	.cs-flowboard__steps {
		display: grid;
		grid-template-columns: repeat( 5, minmax( 0, 1fr ) );
		column-gap: 5%;
		padding-top: 32px;
		padding-bottom: 9%;
	}

	.cs-flowboard__step {
		position: relative;
	}

	.cs-flowboard__frame {
		padding-bottom: 0;
	}

	.cs-flowboard__step img {
		width: 100%;
	}

	.cs-flowboard__arrow {
		display: none;
	}

	/* The same 10 / 409 in from the image edge, now that the image is the
	   whole column. */
	.cs-flowboard__step .cs-wire__label {
		position: absolute;
		bottom: 100%;
		left: 2.44%;
		right: 0;
		max-width: none;
		margin: 0 0 10px;
		white-space: nowrap;
	}

	.cs-flowboard__arrows {
		display: block;
		position: absolute;
		top: 32px;
		left: 0;
		width: 100%;
		height: auto;
		overflow: visible;
		pointer-events: none;
	}

}

/* ---------------------------------------------------------------------------
   Screenshots

   The crops keep the board's own background, which is the same #005450 the
   panel is painted, so the phone reads as sitting on the panel with no seam
   and no cut-out edge to go wrong at an odd width.
   --------------------------------------------------------------------------- */

.cs-board__media {
	margin: 0;
	text-align: center;
}

.cs-board__media img {
	display: block;
	width: 100%;
	max-width: 320px;
	height: auto;
	margin: 0 auto;
}

@container ( min-width: 520px ) {
	.cs-board__media img {
		max-width: 100%;
	}
}

/* ---------------------------------------------------------------------------
   A pair of boards as one panel

   Two boards that read as a pair used to be two builder modules. The builder
   positions modules independently, so stacked they sat 41px apart with the
   section's white between two panels of the same colour — and that gap belonged
   to neither module, so neither could close it.

   As one module the panel is continuous by construction, and the space between
   the two is set here instead of by the builder.

   A media query rather than a container query: this wrapper spans the full grid,
   so its width is the window's, and 961px is the theme's own threshold —
   lobo/js/main.js swaps to the compact menu below it. Side by side the two
   boards already met edge to edge, which is why the columns have no gap.
   --------------------------------------------------------------------------- */

/* The theme narrows the copy column of any full-width text module to 50% and
   centres it — sensible for a wide column of prose, wrong for a panel that is
   meant to reach both edges, which left the pair 640px wide in a 1280px module.
   Scoped by :has() so it lifts the limit only where a board panel is actually
   present and every other full-width text module keeps its reading measure. */
#content-wrapper .text-module .copy:has( .cs-boards ),
#content-wrapper .text-module .copy:has( .cs-figure ),
#content-wrapper .text-module .copy:has( .cs-timeline ),
#content-wrapper .text-module .copy:has( .cs-grid ) {
	width: 100%;
	margin-left: 0;
	margin-right: 0;
}

.cs-boards {
	display: grid;
	background-color: #005450;
}

/* The panel behind a pair of sky boards is sky too, so the stacked gap
   between them is the same colour as the boards. */
.cs-boards:has( .cs-board--sky ) {
	background-color: #e1effb;
}

.cs-boards:has( .cs-board--blue ) {
	background-color: #aad8f3;
}

.cs-boards:has( .cs-board--white ) {
	background-color: #fff;
}

.cs-boards:has( .cs-board--grey ) {
	background-color: #f4f4f4;
}

/* Under 480px the theme pads every text module 3% a side, and the module
   behind a panel is painted one flat colour by the builder. Behind a flat
   panel that is invisible; behind the blue wash it showed as an 11px strip
   of the pale either side of the gradient. The panel reaches the module
   edge instead — 3 / 94 of its containing block, as the hotspots stage
   does — so every panel meets the screen edge on a phone. */
@media only screen and ( max-width: 479px ) {
	.cs-boards {
		margin-left: -3.1915%;
		margin-right: -3.1915%;
	}

	/* With the module's padding bled through, the board's 6.5% no longer
	   has the module's 3% under it, so it makes that up itself: 6.5% of
	   the copy column plus the 3% of the module, as fractions of the full
	   width, is 9% — 34px at 375px, where the body copy sits. */
	.cs-boards .cs-board__inner {
		padding-left: 9%;
		padding-right: 9%;
	}
}

/* Side by side: one equal column per board, however many there are — a
   panel holding a single board fills the module rather than half of it. */
@media only screen and ( min-width: 961px ) {

	.cs-boards {
		grid-auto-flow: column;
		grid-auto-columns: minmax( 0, 1fr );
	}

}

/* Stacked, the first board's 40px foot met the second's 34px head for 74px of
   dead teal between two blocks of text. Trimming the head of every board after
   the first brings that to 44px, which still separates them without the panel
   reading as two things that failed to meet. Only applies while stacked; the
   columns sit side by side above the breakpoint and each keeps its own padding. */
@media only screen and ( max-width: 960px ) {

	.cs-boards > .cs-board + .cs-board .cs-board__inner {
		padding-top: 4px;
	}

}

/* ---------------------------------------------------------------------------
   Amazon + One Medical, Personalizing Amazon: the pages' own titles

   The titles typed into the builder's modules set at four different sizes —
   28px, 24px, 19px and 18.72px — with no pattern behind the differences. All of
   them come to the large size; Role and Timeline, which title a credit rather
   than a section, take the small one.

   !important, because two of them carry an inline font-size from the editor
   (Market Research and Designing the Experience at 28px) and nothing short of
   it reaches an inline value. Scoped to these posts so the override goes no
   further than the content it was written for. The boards are matched by the
   first rule too, at the same value they already have, which is harmless and
   keeps one rule saying what the size is.
   --------------------------------------------------------------------------- */

body:is( .postid-1308, .postid-1259 ) #content-wrapper .text-module .copy :is( h2, h3 ) {
	font-size: var( --cs-title-lg ) !important;
	line-height: 1.25;
}

/* Both rules are !important, so specificity alone decides between them, and
   the general rule above weighs (1,3,2). This one carries both ids so it weighs
   (2,2,2) and wins — without that the credits set at the large size too.
   13081 is One Medical's credit module, 12591 Personalizing Amazon's. */
body.postid-1308 #content-wrapper #module-13081 .copy h2,
body.postid-1259 #content-wrapper #module-12591 .copy h2 {
	font-size: var( --cs-title-sm ) !important;
}

/* A board subheading is an h3 too, and would take the large size from the
   page-title rule. Carrying .cs-board as well makes this (1,4,1) to its
   (1,3,2). */
body #content-wrapper .text-module .copy .cs-board .cs-board__subheading {
	font-size: var( --cs-title-sm ) !important;
}

/* ---------------------------------------------------------------------------
   Callout box

   The "A Team Effort" aside sat on Background2.png — a flat beige rectangle
   with rounded corners, drawn once at 1500x814 and applied as the module's
   cover background. A raster cannot grow with its text: on a phone the corners
   scaled off the edges and the last line ran out past the bottom of the beige,
   and the text was held in by 14% inline padding that had been tuned to the
   picture. This is the box the picture was standing in for. #fff2dd is the
   picture's own fill.

   The icon is the same PNG, now inside the heading it belongs to and sized
   there rather than floated with a percentage margin. Colour is stated on each
   element because the theme paints headings and paragraphs its own way; the
   aside used to keep a muted #6d6363, and now takes the #191919 the rest of
   the page's copy is set in.
   --------------------------------------------------------------------------- */

.cs-callout {
	box-sizing: border-box;
	padding: 22px 24px 26px;
	border-radius: 18px;
	background-color: #fff2dd;
	color: #191919;
}

.cs-callout h3 {
	display: flex;
	align-items: center;
	gap: .55em;
	margin: 0 0 10px;

	/* The old markup carried Lato and bold inline on a span; without those the
	   theme's Playfair-on-h1-h6 rule took the heading. Inherit, as the boards
	   do, so it matches the body it sits with. */
	font-family: inherit;
	font-weight: 700;
	color: #191919;
}

/* Font Awesome swaps the <i> for an <svg> and carries this class across, so
   the rule covers both. Square, so the glyph is not letterboxed down by the
   kit's 1em height the way the board icons first were. Sized in em against
   the heading so it moves with the two title sizes rather than being pinned. */
.cs-callout .cs-callout__icon {
	flex: none;
	width: 1.2em;
	height: 1.2em;
	--fa-secondary-opacity: .5;
}

.cs-callout p {
	margin: 0;
	color: #191919;
}

/* The "Branding the Interface" aside: a pale pea green box on a white
   ground. Same copy colour as the beige one. */
.cs-callout--green {
	background-color: #e4eed3;
}

/* Both callouts' titles take the small size, like the credits: they head an
   aside, not a section. The page-title rule above is !important at (1,3,2),
   so this carries the callout class too for (1,4,2). The icons are sized in
   em against the heading and come with it. */
body.postid-1308 #content-wrapper .text-module .copy .cs-callout h3 {
	font-size: var( --cs-title-sm ) !important;
}

/* Space over the Ideation chip on a phone. The module above it is a grid of
   screenshots that runs right to its edge, so the chip was starting flush
   against it. The chip is inline-block, whose margins do not collapse through
   its parents, so the copy block grows by the same amount and the builder's
   own height measurement takes it in — nothing at the foot of the module is
   pushed out of view. */
@media only screen and ( max-width: 767px ) {

	body.postid-1308 #content-wrapper .module:has( .cs-chip--ideation ) .copy p.cs-chip {
		margin-top: 26px;
	}

}

/* ---------------------------------------------------------------------------
   Customer journey flow

   Amazon-Customer-Flow-2.png was a grey panel with a small flow diagram, a
   paragraph and three numbered benefits, all drawn. The panel is the beige
   callout in the artwork's grey; the diagram's boxes are text again, and
   only its connectors are drawn — an inline SVG stretched to the height the
   three source boxes take, so the lines leave the boxes' centres at any
   type size. The boxes are equal-height grid rows for the same reason: the
   lines meet them at 14%, 50% and 86% of that height, which is where three
   equal boxes with a small gap have their centres.
   --------------------------------------------------------------------------- */

.cs-callout--grey {
	background-color: #f4f4f4;
	color: #191919;
}

.cs-journey {
	container-type: inline-size;
}

/* Both carry #content-wrapper: the child theme's phone floor on
   ".copy p" is (0,2,3) and would otherwise take them back to 16px. */
#content-wrapper .cs-callout p.cs-journey__label {
	margin: 0 0 16px;
	color: #323232;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.3;
}

.cs-flow {
	display: grid;
	grid-template-columns: auto minmax( 84px, 1fr ) auto;
	grid-template-rows: 1fr auto;
	column-gap: 10px;
	margin: 0 0 30px;
	color: #494949;
}

.cs-flow__sources {
	grid-column: 1;
	grid-row: 1 / 3;
	display: grid;
	grid-template-rows: repeat( 3, 1fr );
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The boxes: the artwork's grey with white bold labels. Selected with the
   list so the theme's own "ul li" margins and the page's li size rule are
   both outweighed. */
.cs-callout .cs-flow__sources li,
.cs-callout .cs-flow__target {
	display: grid;
	place-items: center;
	box-sizing: border-box;
	margin: 0;
	padding: 8px 12px;
	border-radius: 3px;
	background-color: #6e6e6e;
	color: #fff;
	font-size: 15px;
	font-weight: 700;
	line-height: 1.25;
	text-align: center;
}

.cs-callout .cs-flow__target {
	grid-column: 3;
	grid-row: 1 / 3;
	align-self: center;
	max-width: 132px;
	padding: 12px 14px;
}

.cs-flow__join {
	grid-column: 2;
	grid-row: 1 / 3;
	position: relative;
	min-height: 96px;
}

.cs-flow__lines {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	overflow: visible;
}

.cs-flow__badge {
	position: absolute;
	left: 60%;
	top: 50%;
	display: grid;
	place-items: center;
	width: 22px;
	height: 22px;
	border-radius: 999px;
	background-color: #494949;
	color: #fff;
	font-size: 14px;
	font-weight: 700;
	line-height: 1;
	transform: translate( -50%, -50% );
}

.cs-flow__arrow {
	position: absolute;
	right: 1px;
	top: 50%;
	width: 11px;
	height: 11px;
	border-top: 3px solid #494949;
	border-right: 3px solid #494949;
	transform: translateY( -50% ) rotate( 45deg );
}

/* The note sits in the join's column under the line: the join spans both
   rows, the note takes the second, and its height is what keeps the line
   above it. Later in the markup, so it paints over the lines. */
#content-wrapper .cs-callout p.cs-flow__note {
	grid-column: 2;
	grid-row: 2;
	position: relative;
	margin: 0;
	padding: 18px 0 0 46%;
	color: #494949;
	font-size: 14px;
	font-style: italic;
	line-height: 1.3;
}

/* In a narrow column — a phone, or the panel beside a tall image module on
   a small desktop — there is no room for the note beside the join: set
   there it ran a word to a line, or under the lower curve. It drops to a
   line of its own under the whole diagram, a step smaller. */
@container ( max-width: 379px ) {
	#content-wrapper .cs-callout p.cs-flow__note {
		grid-column: 1 / -1;
		grid-row: 3;
		padding: 8px 0 0;
		font-size: 13px;
	}

	/* And the diagram tightens to fit the column: a 375px phone leaves the
	   panel 308px, and three boxes with two joins at the wide sizes ran 25px
	   past it. Smaller boxes, closer gaps, a shorter join, and the panel's
	   own padding comes in a little. */
	.cs-journey.cs-callout {
		padding-left: 18px;
		padding-right: 18px;
	}

	.cs-flow {
		grid-template-columns: auto minmax( 64px, 1fr ) auto;
		column-gap: 8px;
	}

	.cs-callout .cs-flow__sources li,
	.cs-callout .cs-flow__target {
		padding: 8px 9px;
		font-size: 14px;
	}

	.cs-callout .cs-flow__target {
		max-width: 96px;
		padding: 10px 9px;
	}
}

.cs-journey h3 {
	margin-top: 24px;
}

.cs-journey > p:not( .cs-journey__label ) {
	margin: 0 0 6px;
}

/* The benefits, two across where the panel has room. */
@container ( min-width: 460px ) {
	.cs-findings--columns {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: 20px;
	}
}

.cs-findings--columns .cs-finding {
	margin-bottom: 14px;
}

/* ---------------------------------------------------------------------------
   Customer quote

   The toaster quote was Amazon-Customer-Quote-Toaster.png: a 1500px picture
   of a rounded mint box with a quotation set inside it, which put the quote
   at about 9px on a phone. This is the box the picture was standing in for.
   The wash, the grey marks and the attribution grey are sampled from it; the
   quotation itself sets at the large title size, which is what the artwork's
   line measured against the body copy beside it.

   The marks are drawn from the font rather than the picture, absolutely
   placed at the box's corners so they hang outside the measure the way the
   artwork's did. Both are decorative — the blockquote already says what the
   text is — so they are pseudo-elements and never read out.
   --------------------------------------------------------------------------- */

.cs-quote {
	margin: 0;
}

.cs-quote__box {
	position: relative;
	box-sizing: border-box;
	margin: 0 0 18px;
	padding: 30px 40px 32px;
	border-radius: 18px;
	background-image: linear-gradient( to bottom, #e5f5f4, #caebe8 );
}

/* The theme sets every module blockquote italic through ".module blockquote",
   which outweighs a lone class; the artwork is roman. And lobo/js/main.js
   appends a 200px white quotation mark to every blockquote in a module, at
   10% opacity, hanging off its top-left. Ours are drawn below, in the
   artwork's grey, so the theme's is dropped — again with the element name
   in the selector, to outweigh the theme's own. */
.module blockquote.cs-quote__box {
	font-style: normal;
	/* And in the body face, not the Playfair the theme gives quotations:
	   the artwork set the quotation in the same Lato as the copy beside it. */
	font-family: inherit;
}

.module blockquote.cs-quote__box p {
	font-family: inherit;
}

.module blockquote.cs-quote__box .quote-tag {
	display: none;
}

.cs-quote__box::before,
.cs-quote__box::after {
	position: absolute;
	color: #93a09f;
	font-family: Georgia, "Times New Roman", serif;
	font-size: 2.6em;
	font-weight: 700;
	line-height: 1;
}

.cs-quote__box::before {
	content: "\201C";
	top: 18px;
	left: 14px;
}

.cs-quote__box::after {
	content: "\201D";
	right: 14px;
	bottom: 12px;
}

/* The quotation, a step over the body copy rather than at title size: at
   the title size it outweighed the paragraph it sits beside on desktop and
   ran long on a phone. 16px on a phone, growing to 18px on a wide screen.
   The body-copy rule above leaves this paragraph alone by name; the theme's
   15px on desktop and the child theme's 16px floor on phones both outweigh
   a plain class, hence the ids. */
body #content-wrapper .copy .cs-quote__box p {
	margin: 0;
	color: #191919;
	font-size: clamp( 16px, 1.25vw, 18px );
	line-height: 1.5;
}

.cs-quote__cite {
	margin: 0;
	color: #5c6564;
	font-style: normal;
}

.cs-quote__cite::before {
	content: "\2013\00a0";
}

/* Narrow, the marks come in with the padding so the box is not mostly air
   around a short measure. */
@media only screen and ( max-width: 599px ) {

	.cs-quote__box {
		padding: 26px 26px 28px;
	}

	.cs-quote__box::before,
	.cs-quote__box::after {
		font-size: 2.2em;
	}

	.cs-quote__box::before {
		top: 8px;
		left: 8px;
	}

	.cs-quote__box::after {
		right: 8px;
		bottom: 4px;
	}

}

/* The role line under the hero title is hidden on these projects. It is a
   per-project field, so this is scoped to the posts rather than the template. */
body:is( .postid-1308, .postid-1259 ) .hero-info .subtitle {
	display: none;
}

/* Modules are selected by what they contain — the Ideation chip, the green
   callout — not by the numbered ids the builder assigns. Those ids are just
   the module's position, and renumber every time a module is added, merged
   or removed above them; a rule keyed to #module-13087 silently moved to a
   different module the first time that happened. The chips and callouts carry
   modifier classes for exactly this. */

/* "Designing the Experience" fades from the module's #f0f1ed to white, so it
   hands off to the white ground of the Branding module beneath with no seam.
   The fade used to be Green-Background-Gradient.png, a 1500x814 picture of
   exactly this; drawn here instead it is the same two colours with no image
   to fetch. The builder writes only background-color inline when a module has
   no picture, so no !important is needed for the image. */
body.postid-1308 #content-wrapper .module:has( .cs-chip--ideation ) {
	background-image: linear-gradient( to bottom, #f0f1ed, #fff );
}

/* On desktop the Branding module sits beside Designing in the same row, at the
   same top and height, so the identical gradient on both paints as one wash
   across the row. Stacked on a phone the two are consecutive, and there the
   fade lands on Branding's white ground instead. */
@media only screen and ( min-width: 961px ) {

	body.postid-1308 #content-wrapper .module:has( .cs-callout--green ) {
		background-image: linear-gradient( to bottom, #f0f1ed, #fff );
	}

}

/* "Designing the Experience": the heading sat 26px off its copy, which read as
   a gap rather than a lead-in; 14px now. And on a wide screen the chip gets
   more room before the heading — the 16px it shares with the boards suits a
   phone column but looks cramped once the module is 640px wide. */
body.postid-1308 #content-wrapper .module:has( .cs-chip--ideation ) .copy h2 {
	/* Both margins are countering the child theme's About-page rule, which
	   targets a 2-1 module's h2 after a 2-2 module and matches this one by
	   structural accident. Its margin-bottom is !important (26px/32px), so
	   only !important at higher specificity beats it; its desktop margin-top
	   of -16.5px is not, and was quietly eating the room the chip leaves. */
	margin-top: 0;
	margin-bottom: 14px !important;
}

@media only screen and ( min-width: 768px ) {

	body.postid-1308 #content-wrapper .module:has( .cs-chip--ideation ) .copy p.cs-chip {
		margin-bottom: 26px;
	}

}

/* Every piece of body copy on the page at --cs-body. Two ids so it outweighs
   the theme's breakpoint rules on ".copy p" without needing !important; the
   chips are excluded because they are labels, not copy. */
body:is( .postid-1308, .postid-1259 ) #content-wrapper .copy :is( p, li ):not( .cs-chip ):not( .cs-step ):not( .cs-quote__box p ):not( .cs-example__caption ):not( .cs-flow * ):not( .cs-journey__label ) {
	font-size: var( --cs-body );
}

/* ---------------------------------------------------------------------------
   Figures

   A diagram rendered at its own aspect from a text module, instead of being
   cover-cropped into the builder's fixed-ratio image box. The customer flow is
   1:2.57 and the box it was in is 1:2, so cover could never show it larger
   than 78% of the width whatever the artwork did; here the module is auto-wrap
   and takes its height from the picture, and the copy-column limit is lifted
   above so it spans the module like the image module it replaces did.
   --------------------------------------------------------------------------- */

/* The theme gives auto-wrap modules 20px of vertical margin, which is right
   for a text column but put this module 20px below the image module beside it
   on desktop — both are positioned to the same top by the builder, and only
   one carried the margin. A figure module is standing in for an image module,
   so it takes an image module's margins: none. */
#content-wrapper .module.auto-wrap:has( .cs-figure ) {
	margin-top: 0;
	margin-bottom: 0;
}

.cs-figure {
	margin: 0;
}

.cs-figure img {
	display: block;
	width: 100%;
	height: auto;
}

/* On a wide screen the figure sits beside an image module the builder holds
   at a 1:2 box, and shown full width the 1:2.5 diagram ran 331px past it.
   78% of the column brings the figure's module to the same height as its
   neighbour — 1279px against 1280px at a 1280px window — so the pair reads
   as a row again. Centred, so the trimmed margins stay even. */
@media only screen and ( min-width: 961px ) {

	.cs-figure img {
		width: var( --cs-figure-w, 78% );
		margin: 0 auto;
	}

	/* The content-priority diagram is 1:2.79 against the flow's 1:2.52. At the
	   same width it would run 134px past its neighbour, so it takes the width
	   that gives it the flow's height: 78% x 2.52 / 2.79. */
	.cs-figure--priority {
		--cs-figure-w: 70.4%;
	}

}

/* ---------------------------------------------------------------------------
   Rows that pair a chip-led text block with a callout, on desktop

   The builder centres each module's content vertically, so where a text block
   and a callout sit side by side their top edges land wherever their heights
   happen to put them: Research and the beige box were 58px and 54px from the
   top, Ideation and the green box 41px and 54px — a 13px stagger between two
   things meant to read as a row. Top-aligning all four at one inset gives the
   two rows a shared edge, and keeps it if the copy changes length.

   !important because the alignment is inline on the cell, written by the
   builder's editor. 54px is where the callouts already sat when centred, so
   the boxes stay put and the chips come to them; measured from the module's
   top edge, which the cell shares.
   --------------------------------------------------------------------------- */

@media only screen and ( min-width: 961px ) {

	body.postid-1308 #content-wrapper :is( .module:has( .cs-chip--research ), .module:has( .cs-callout--beige ), .module:has( .cs-chip--ideation ), .module:has( .cs-callout--green ) ) .copy > div > div {
		vertical-align: top !important;
		padding-top: 54px !important;
	}

}

/* Room before the footer. The last module ended on the footer's top edge — a
   light landing-page comp straight onto black — where every other section on
   the page closes with air. Padding on the section for the same reason the
   space under the hero is there: it is content-box with a builder-set height,
   so the padding adds rather than eats, and it is white. */
body.single-portfolio #content-wrapper .content-module {
	padding-bottom: 44px;
}

/* Except where the page closes on a painted panel. One Medical closes on
   the annotated comp, whose devices run off the bottom of the artwork by
   design, so 44px of white under it showed the cut as a cut; Personalizing
   Amazon closes on the grey wireframe-flow board, and white between a grey
   panel and the dark next-project card read as a gap. Each meets the card
   directly instead: no section padding, none on the module — which the
   theme gives 3% of under 480px — and no auto-wrap margin under it. */
body.single-portfolio #content-wrapper .content-module:has( .cs-hotspots ),
body.single-portfolio #content-wrapper .content-module:has( .cs-flowboard ) {
	padding-bottom: 0;
}

#content-wrapper .content-module .text-module:has( .cs-hotspots ),
#content-wrapper .content-module .text-module:has( .cs-flowboard ) {
	padding-bottom: 0;
	margin-bottom: 0;
}

/* ---------------------------------------------------------------------------
   Reveal on scroll

   js/reveal.js adds .cs-reveal to each module's inner box and .is-in as it
   enters. Nothing here applies without the script, so no-JS shows the page.
   Reduced motion is handled in the script (it does not run), and again here
   in case a stale class survives.
   --------------------------------------------------------------------------- */

.cs-reveal {
	opacity: 0;
	transform: translateY( 12px );
	transition:
		opacity .45s cubic-bezier( .22, .61, .36, 1 ),
		transform .45s cubic-bezier( .22, .61, .36, 1 );
}

.cs-reveal.is-in {
	opacity: 1;
	transform: none;
}

@media ( prefers-reduced-motion: reduce ) {
	.cs-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
   Next project

   A full-width card after the last module: the next case study's artwork
   under the same kind of dark wash the homepage tiles use on hover, with the
   artwork creeping in on hover the way the tiles do. Sits on the 44px the
   section leaves before the footer, and meets the footer flush.
   --------------------------------------------------------------------------- */

.cs-next {
	box-sizing: border-box;
	position: relative;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 24px;
	min-height: clamp( 260px, 38vw, 420px );
	padding: clamp( 28px, 5vw, 64px );
	overflow: hidden;
	background-color: #0e1012;
	color: #fff;
	text-decoration: none;
}

.cs-next__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transform: scale( 1 );
	transition: transform .8s cubic-bezier( .22, .61, .36, 1 );
}

/* Dark wash, heaviest where the text sits. */
.cs-next::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to top,
		rgba( 0, 0, 0, .82 ) 0%,
		rgba( 0, 0, 0, .55 ) 45%,
		rgba( 0, 0, 0, .25 ) 100%
	);
}

.cs-next__body,
.cs-next__cue {
	position: relative;
	z-index: 1;
}

.cs-next__body {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.cs-next__label {
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	opacity: .75;
}

.cs-next__title {
	font-family: 'Playfair Display', serif;
	font-weight: 700;
	font-size: clamp( 26px, 3.4vw, 44px );
	line-height: 1.1;
}

.cs-next__role {
	font-size: 14px;
	letter-spacing: .06em;
	text-transform: uppercase;
	opacity: .8;
}

.cs-next__cue {
	flex: none;
	display: grid;
	place-items: center;
	width: 52px;
	height: 52px;
	border: 1px solid rgba( 255, 255, 255, .55 );
	border-radius: 999px;
	font-size: 20px;
	transition:
		background-color .3s ease,
		border-color .3s ease,
		transform .3s cubic-bezier( .22, .61, .36, 1 );
}

.cs-next__cue svg,
.cs-next__cue i {
	width: 1.1em;
	height: 1.1em;
	--fa-secondary-opacity: .5;
}

.no-touch .cs-next:hover .cs-next__img {
	transform: scale( 1.05 );
	transition-duration: 4s;
}

.no-touch .cs-next:hover .cs-next__cue {
	background-color: #fff;
	border-color: #fff;
	color: #0e1012;
	transform: translateX( 4px );
}

@media ( prefers-reduced-motion: reduce ) {
	.cs-next__img,
	.cs-next__cue {
		transition: none;
	}

	.no-touch .cs-next:hover .cs-next__img {
		transform: none;
	}
}

/* ---------------------------------------------------------------------------
   Phase bar

   Built by js/phases.js from the chips on the page. Fixed, not sticky:
   #content-wrapper is overflow:hidden, which stops any sticky descendant from
   ever sticking to the viewport. It slides in once the first phase reaches
   the top of the screen and out again past the last.

   The current phase is drawn as the page's own chip — the dark teal pill the
   Research and Ideation labels use — so the bar and the content share one
   vocabulary. The others are plain labels.
   --------------------------------------------------------------------------- */

.cs-phases {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 10500;
	display: flex;
	justify-content: center;
	height: 46px;
	background-color: rgba( 255, 255, 255, .9 );
	-webkit-backdrop-filter: blur( 10px );
	backdrop-filter: blur( 10px );
	border-bottom: 1px solid rgba( 0, 0, 0, .08 );
	transform: translateY( -100% );
	transition:
		transform .32s cubic-bezier( .22, .61, .36, 1 ),
		top .32s cubic-bezier( .22, .61, .36, 1 );
}

.cs-phases.is-visible {
	transform: none;
}

.cs-phases ol {
	display: flex;
	align-items: center;
	gap: 4px;
	margin: 0;
	padding: 0 12px;
	list-style: none;
}

.cs-phases a {
	display: inline-block;
	padding: 6px 13px;
	border-radius: 999px;
	color: #555;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	text-decoration: none;
	transition:
		background-color .25s ease,
		color .25s ease;
}

.cs-phases a:hover {
	color: #002927;
}

.cs-phases a[aria-current] {
	background-color: #002927;
	color: #fff;
}

/* On desktop the site header is fixed and returns on scroll-up. While it is
   showing, the bar sits under it, moving on the header's own timing; when it
   slides away the bar comes back to the top. 116px and .32s are the header's
   figures from style.css. */
@media only screen and ( min-width: 1024px ) {

	body.header-stuck:not( .header-hidden ) .cs-phases {
		top: 116px;
	}

}

@media ( prefers-reduced-motion: reduce ) {
	.cs-phases,
	.cs-phases a {
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
   Annotated hotspots

   Numbered markers on the final comp, each with a note that ties the detail
   back to the decision an earlier section set up. Markers sit at percentage
   coordinates (--x, --y) so they hold at any width.

   Narrow, the notes are a numbered list under the image — legible on a phone,
   where the comp itself is not — and a tap on a marker brings its note up.
   Wide, the same notes float beside their markers; js/hotspots.js reads which
   mode applies from the notes' computed position, so the breakpoint lives
   here only.
   --------------------------------------------------------------------------- */

/* The figure inherits .cs-figure's lifted copy column, which put its title
   and hint flush against the module edge: 11px in on a phone against the
   34px the body copy sits at, and 0 on desktop against 47px. The same inset
   the research grid carries — 6.5% narrow to make up the copy wrapper's lost
   margin, 3.25% of the full-width module from the desktop breakpoint, which
   is the 6.5% the half-width modules either side inset their copy by. On the
   text only: the comp itself bleeds, below. */
.cs-hotspots__title,
.cs-hotspots__hint {
	padding-left: 6.5%;
	padding-right: 6.5%;
}

@media only screen and ( min-width: 961px ) {
	.cs-hotspots__title,
	.cs-hotspots__hint {
		padding-left: 3.25%;
		padding-right: 3.25%;
	}
}

.cs-hotspots__title {
	margin: 0 0 6px;
	font-family: inherit;
	font-size: var( --cs-title-lg );
	font-weight: 700;
	line-height: 1.25;
	color: #191919;
}

.cs-hotspots__hint {
	margin: 0 0 18px;
	color: #6d6363;
	font-size: 14px !important;
}

/* The canvas holds the image and its markers; the stage holds the canvas and
   the notes. Markers position against the canvas. Wide, the notes overlay the
   stage, and because they are then out of flow the stage is exactly the
   canvas's size — so both use the same coordinate frame, the image's. Narrow,
   the notes simply follow the canvas in flow.

   The comp is not framed. Its artwork runs off its own bottom edge — both
   devices are cut — and its background is a wash from #fefefe at the top to
   #f9f1e6 at the bottom, so rounded corners and a cream rectangle on the
   white module read as a picture in a box. Instead the stage spans the
   module edge to edge, the image's top blends into the white it sits on,
   and the stage is painted the comp's bottom colour so whatever is under
   the image — the notes, narrow — continues the wash rather than cutting
   it off. The comp never scales past 100% so nothing crops; the markers'
   percentages are of the canvas and hold at any width. */
.cs-hotspots__stage,
.cs-hotspots__canvas {
	position: relative;
}

.cs-hotspots__stage {
	background-color: #f9f1e6;
}

.cs-hotspots__stage img {
	display: block;
	width: 100%;
	height: auto;
}

/* Under 480px the theme pads every text module 3% on each side, which is the
   only thing between the stage and the screen edge. The stage's containing
   block is the 94% inside that padding, so 3 / 94 of its width reaches it. */
@media only screen and ( max-width: 479px ) {
	.cs-hotspots__stage {
		margin-left: -3.1915%;
		margin-right: -3.1915%;
	}
}

/* --- Markers --- */

.cs-hotspot {
	position: absolute;
	left: var( --x );
	top: var( --y );
	z-index: 2;
	width: 44px;
	height: 44px;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	transform: translate( -50%, -50% );
	cursor: pointer;
}

.cs-hotspot__dot {
	display: grid;
	place-items: center;
	width: 28px;
	height: 28px;
	margin: 8px;
	border-radius: 999px;
	background-color: #002927;
	color: #fff;
	font-family: Lato, sans-serif;
	font-size: 13px;
	font-weight: 700;
	line-height: 1;
	box-shadow:
		0 0 0 3px #fff,
		0 2px 8px rgba( 0, 0, 0, .3 );
	transition: transform .25s cubic-bezier( .22, .61, .36, 1 );
}

/* A slow ring that breathes out from each marker, so they read as things to
   press rather than numbers printed on the picture. */
.cs-hotspot::before {
	content: "";
	position: absolute;
	inset: 8px;
	border-radius: 999px;
	border: 2px solid #002927;
	opacity: 0;
	animation: cs-hotspot-ring 2.8s ease-out infinite;
}

@keyframes cs-hotspot-ring {
	0%   { transform: scale( 1 );   opacity: .55; }
	70%  { transform: scale( 1.9 ); opacity: 0; }
	100% { transform: scale( 1.9 ); opacity: 0; }
}

.cs-hotspot:hover .cs-hotspot__dot,
.cs-hotspot:focus-visible .cs-hotspot__dot,
.cs-hotspot.is-open .cs-hotspot__dot {
	transform: scale( 1.15 );
}

.cs-hotspot.is-open::before {
	animation: none;
}

.cs-hotspot:focus-visible {
	outline: none;
}

.cs-hotspot:focus-visible .cs-hotspot__dot {
	box-shadow:
		0 0 0 3px #fff,
		0 0 0 6px #002927;
}

/* --- Notes, stacked (default) --- */

.cs-hotspots__notes {
	display: grid;
	gap: 12px;
	margin: 22px 0 0;
	padding: 0;
	list-style: none;
}

/* Narrow, the notes sit on the cream under the comp; they take the page's
   inset themselves now the figure has none, and close the panel with air
   before the section ends. Wide, they float and none of this applies. */
@media only screen and ( max-width: 960px ) {
	.cs-hotspots__notes {
		padding: 0 6.5% 32px;
	}
}

/* Under 480px the stage has bled through the module's 3% padding, so the
   notes make it up as well: 6.5% of the copy column plus the 3% of the
   module, as fractions of the wider stage, is 9% — 34px at 375px, where
   the body copy sits. */
@media only screen and ( max-width: 479px ) {
	.cs-hotspots__notes {
		padding-left: 9%;
		padding-right: 9%;
	}
}

.cs-hotspot-note {
	display: grid;
	grid-template-columns: 28px 1fr;
	column-gap: 12px;
	padding: 14px 16px 16px;
	border-radius: 12px;
	background-color: #f0f1ed;
	color: #191919;
	transition: box-shadow .4s ease;
}

.cs-hotspot-note__n {
	grid-row: 1 / 3;
	display: grid;
	place-items: center;
	width: 28px;
	height: 28px;
	border-radius: 999px;
	background-color: #002927;
	color: #fff;
	font-size: 13px;
	font-weight: 700;
}

.cs-hotspot-note__title {
	display: block;
	margin-bottom: 4px;
	font-size: 16px;
	line-height: 1.3;
}

.cs-hotspot-note__body {
	display: block;
	font-size: 15px;
	line-height: 1.5;
	color: #444;
}

.cs-hotspot-note.is-flash {
	box-shadow: 0 0 0 3px #002927;
}

/* Stacked on the cream, the notes are plain: no card fill, no card padding,
   just the numbered rows with more air between them than the cards had. The
   tap flash was a ring on the card's edge; on a bare row it stands off the
   text instead, as an outline with an offset, so it does not hug the type. */
@media only screen and ( max-width: 960px ) {

	.cs-hotspots__notes {
		gap: 22px;
	}

	.cs-hotspot-note {
		padding: 0;
		background-color: transparent;
	}

	.cs-hotspot-note.is-flash {
		box-shadow: none;
		outline: 3px solid #002927;
		outline-offset: 10px;
	}

}

/* --- Notes, floating (wide) --- */

@media only screen and ( min-width: 961px ) {

	.cs-hotspots__notes {
		position: absolute;
		inset: 0;
		display: block;
		margin: 0;
		pointer-events: none;
	}

	.cs-hotspot-note {
		position: absolute;
		left: calc( var( --x ) + 24px );
		top: var( --y );
		z-index: 3;
		width: 280px;
		transform: translateY( -50% );
		background-color: #fff;
		box-shadow:
			0 1px 2px rgba( 0, 0, 0, .12 ),
			0 12px 32px rgba( 0, 0, 0, .18 );
		opacity: 0;
		visibility: hidden;
		pointer-events: auto;
		transition:
			opacity .22s ease,
			visibility 0s linear .22s;
	}

	.cs-hotspot-note.is-open {
		opacity: 1;
		visibility: visible;
		transition-delay: 0s;
	}

	.cs-hotspot-note.is-left {
		left: auto;
		right: calc( 100% - var( --x ) + 24px );
	}

	.cs-hotspot-note.is-above {
		top: auto;
		bottom: calc( 100% - var( --y ) );
		transform: none;
	}

	.cs-hotspot-note.is-flash {
		box-shadow:
			0 1px 2px rgba( 0, 0, 0, .12 ),
			0 12px 32px rgba( 0, 0, 0, .18 );
	}

}

@media ( prefers-reduced-motion: reduce ) {
	.cs-hotspot::before {
		animation: none;
	}

	.cs-hotspot__dot,
	.cs-hotspot-note {
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
   Iteration timeline

   Four paragraphs of process, as four numbered steps down a line, each with
   the artefact it produced. The step's lesson is the one line to read if
   nothing else is; the original paragraph follows it.

   The copy-column limit is lifted above so the timeline can run wider than a
   50% column, and it caps itself at a reading measure. Narrow, the thumbnail
   sits above the text; from 640px it moves beside it.
   --------------------------------------------------------------------------- */

.cs-timeline {
	max-width: 900px;
	margin: 0 auto;

	/* 6.5% horizontal while narrow, for the same reason the boards carry it:
	   lifting the copy column also lifts the inset it supplied, and 6.5% of
	   the panel plus the module's own 11px is the 34px the page's body copy
	   sits at. Above the breakpoint the max-width does the centring. */
	padding: 8px 6.5% 0;
}

@media only screen and ( min-width: 961px ) {
	.cs-timeline {
		padding-left: 0;
		padding-right: 0;
	}
}

.cs-timeline__title {
	margin: 0 0 28px;
	font-family: inherit;
	font-size: var( --cs-title-lg ) !important;
	font-weight: 700;
	line-height: 1.25;
	color: #191919;
}

.cs-timeline__steps {
	position: relative;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The line the steps hang from, running through the centre of the numbers. */
.cs-timeline__steps::before {
	content: "";
	position: absolute;
	top: 16px;
	bottom: 16px;
	left: 15px;
	width: 2px;
	background-color: #dfe4e0;
}

.cs-timeline__step {
	position: relative;
	display: grid;
	grid-template-columns: 32px 1fr;
	column-gap: 18px;
	row-gap: 14px;
	margin: 0 0 36px;
}

.cs-timeline__step:last-child {
	margin-bottom: 0;
}

.cs-timeline__n {
	grid-row: 1 / 3;
	display: grid;
	place-items: center;
	width: 32px;
	height: 32px;
	border-radius: 999px;
	background-color: #002927;
	color: #fff;
	font-size: 14px;
	font-weight: 700;
	box-shadow: 0 0 0 4px #fff;
}

.cs-timeline__media {
	grid-column: 2;
	margin: 0;
	border-radius: 10px;
	overflow: hidden;
	border: 1px solid rgba( 0, 0, 0, .08 );
	background-color: #f0f1ed;
}

.cs-timeline__media img {
	display: block;
	width: 100%;
	height: auto;
}

.cs-timeline__text {
	grid-column: 2;
}

/* Weighted past the page-title rule, which sets every h2/h3 in a text module
   to the large size with !important at (1,3,2); this is (1,4,1). A step is a
   sub-heading inside the section, so it takes the small size. */
#content-wrapper .text-module .copy .cs-timeline h3.cs-timeline__heading {
	margin: 0 0 4px;
	font-family: inherit;
	font-size: var( --cs-title-sm ) !important;
	font-weight: 700;
	line-height: 1.25;
	color: #191919;
}

.cs-timeline__lesson {
	margin: 0 0 10px !important;
	color: #005450;
	font-size: 14px !important;
	font-weight: 700;
	letter-spacing: .02em;
}

.cs-timeline__body {
	margin: 0 !important;
	color: #2b2b2b;
}

@media only screen and ( min-width: 640px ) {

	.cs-timeline__step {
		grid-template-columns: 32px 220px 1fr;
		column-gap: 24px;
		align-items: start;
	}

	.cs-timeline__n {
		grid-row: 1;
	}

	.cs-timeline__media {
		grid-column: 2;
		grid-row: 1;
	}

	.cs-timeline__text {
		grid-column: 3;
		grid-row: 1;
	}

}

/* ---------------------------------------------------------------------------
   Research grid

   The four competitor mockups from the two market-research boards, as a grid
   of figures. The boards were pictures of a grid: two 1500px PNGs, each with
   two phones and a caption drawn in at a size that came out around 9px on a
   phone. The mockups are cut from them; the captions are text again, with the
   icons the artwork used, and each carries a one-line takeaway.

   Two columns while narrow, four from the desktop breakpoint, where the two
   old boards sat side by side and made four across anyway.
   --------------------------------------------------------------------------- */

.cs-grid {
	padding: 8px 6.5% 4px;
}

/* Desktop: the half-width text modules either side of this one set their copy
   at 87% of the module, centred, so the page's body copy sits 6.5% of a
   half-module in from the window edge — 47px at 1440. Zero here left the grid
   flush against the edge while the paragraphs above and below it were not.
   This module spans the full width, so the same inset is 3.25% of it. */
@media only screen and ( min-width: 961px ) {
	.cs-grid {
		padding-left: 3.25%;
		padding-right: 3.25%;
	}
}

.cs-grid__title {
	margin: 0 0 20px;
	font-family: inherit;
	font-size: var( --cs-title-lg ) !important;
	font-weight: 700;
	line-height: 1.25;
	color: #191919;
}

.cs-grid__items {
	display: grid;
	grid-template-columns: 1fr;
	gap: 22px;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Narrow: each cell lies sideways, mockup left and caption right. Two cells
   across a 375px phone left each caption about 110px once the icon and
   padding took theirs, and 15px bold text wrapped four deep. Sideways, the
   caption gets roughly twice that. From 600px the cells stand up, two across;
   from the desktop breakpoint, four. */
@media only screen and ( max-width: 599px ) {

	.cs-grid__item figure {
		display: grid;
		grid-template-columns: 52% 1fr;
		column-gap: 14px;
		align-items: start;
	}

	.cs-grid__item figcaption {
		padding: 4px 0 0;
	}

	.cs-grid__source {
		margin-top: 0;
	}

}

@media only screen and ( min-width: 600px ) {
	.cs-grid__items {
		grid-template-columns: repeat( 2, 1fr );
		gap: 28px 20px;
	}
}

@media only screen and ( min-width: 961px ) {
	.cs-grid__items {
		grid-template-columns: repeat( 4, 1fr );
		gap: 32px 28px;
	}
}

.cs-grid__item figure {
	margin: 0;
}

.cs-grid__item img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 10px;
	background-color: #fff;
}

/* The caption block is inset from the image's edges so it reads as a label
   under the picture rather than a column the same width as it. */
.cs-grid__item figcaption {
	padding: 0 12px;
}

.cs-grid__source {
	display: block;
	margin: 14px 0 5px;
	color: #6d6363;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
}

.cs-grid__caption {
	display: grid;
	grid-template-columns: 1.1em 1fr;
	gap: .45em;
	align-items: start;
	margin: 0 0 5px;
	color: #191919;
	font-size: 14px;
	font-weight: 700;
	line-height: 1.3;
}

/* Grey, not the accent: the icon is a glyph for the caption, and in teal it
   competed with the caption instead of serving it. #6d6363 is the muted grey
   the asides use. */
.cs-grid__caption svg,
.cs-grid__caption i {
	width: 1.1em;
	height: 1.1em;
	margin-top: .05em;
	color: #6d6363;
	--fa-secondary-opacity: .5;
}

.cs-grid__takeaway {
	margin: 0 !important;
	color: #444;
	font-size: 13.5px !important;
	line-height: 1.45;
}
