@charset "utf-8";

/* ==========================================================================
   CamTalk - the travelling counter layer and the closing white scene.

   Loads on the main page only, next to css/camtalk-scroll3d.css, and after
   it: the counter keeps every surface, proportion and dimension defined
   there, and only the two rules it needs to travel are overridden here.
   Desktop only - the project breakpoint is 1000px.
   ========================================================================== */

/* ==========================================================================
   The counter layer
   ========================================================================== */

.ctc {
	display: none;
}

/* Shared by both profiles - the counter layer and the closing scene are the
   same objects on a phone. Width-dependent values are overridden in the
   mobile block at the end. */
@media screen {

	/* One fixed, click-through layer for the whole page. It sits above the
	   page content and below the site's own drop-down menu (z-index 10) and
	   the AI assistant, so it never covers a control or takes a click. */
	.ctc {
		display: block;
		position: fixed;
		inset: 0;
		z-index: 9;
		pointer-events: none;
		visibility: hidden;
	}

	.ctc.is-visible {
		visibility: visible;
	}

	/* Carries --ctc-dock-gap as a real length for the script to read. */
	.ctc__gap {
		position: absolute;
		left: 0;
		bottom: 0;
		width: 1px;
		height: var(--ctc-dock-gap, 28px);
		opacity: 0;
		pointer-events: none;
	}

	/* The counter itself. Positioned from the top left and moved by one
	   translate, which is what makes its whole journey - right-hand home,
	   bottom centre, closing scene - a single continuous path. Scale is
	   never touched, so every width measurement in the display stays
	   honest and the object keeps its compact size the whole way down. */
	.ctc .ct3d__side--right {
		position: absolute;
		left: 0;
		top: 0;
		opacity: 0;
		will-change: transform, opacity;
		/* grounds the object on the light sections; invisible on the dark
		   ones. Not a plate and not a glow - just contact shadow. */
		filter: drop-shadow(0 6px 15px rgba(24, 8, 20, 0.20));
	}

	/* ----------------------------------------------------------------------
	   The call above the counter.

	   Out of flow on purpose: the counter's own box, its locked width and
	   every measurement the flap display makes are left exactly as they were.
	   Every dimension is derived from --ct3d-cell, the one variable the
	   counter itself scales by, so the caption tracks the counter's size at
	   any viewport instead of being sized twice.
	   ---------------------------------------------------------------------- */

	.ctc__caption {
		position: absolute;
		left: 50%;
		bottom: calc(100% + var(--ct3d-cell) * 0.34);
		transform: translateX(-50%);
		width: max-content;
		max-width: 148%;
		text-align: center;
		line-height: 1.16;
		letter-spacing: -0.018em;
		opacity: var(--ctc-caption-a, 1);
		pointer-events: none;
		/* light by default - the counter spends its first phases on the dark
		   stage; the light sections flip it with .is-on-dark below */
		color: #f4eef3;
		transition: color 0.35s ease, text-shadow 0.35s ease;
		/* A tight contour of the opposite polarity under a soft one. The
		   counter's digits sit in a housing and read on anything; bare words
		   do not, and the sections below it include photographs. This holds
		   the line over them without putting a panel behind it. */
		text-shadow:
			0 1px 1.5px rgba(0, 0, 0, 0.92),
			0 -1px 1.5px rgba(0, 0, 0, 0.55),
			0 3px 14px rgba(0, 0, 0, 0.70);
	}

	.ctc__caption-intro,
	.ctc__caption-main {
		display: block;
		white-space: nowrap;
	}

	.ctc__caption-intro {
		font-size: calc(var(--ct3d-cell) * 0.60);
		font-weight: 700;
		opacity: 0.88;
	}

	.ctc__caption-main {
		font-size: calc(var(--ct3d-cell) * 0.95);
		font-weight: 800;
		margin-top: calc(var(--ct3d-cell) * 0.06);
	}

	/* the brand red, lifted just enough to hold its own on the dark stage */
	.ctc__caption-main b {
		font-weight: 800;
		color: #ff4a72;
		transition: color 0.35s ease;
	}

	/* English sets wider, so it gives a little back to stay inside the
	   counter's width at both desktop sizes */
	body.lang-en .ctc__caption-intro {
		font-size: calc(var(--ct3d-cell) * 0.52);
	}

	body.lang-en .ctc__caption-main {
		font-size: calc(var(--ct3d-cell) * 0.76);
	}

	/* --- and the same block over a light section --- */

	.ctc:not(.is-on-dark) .ctc__caption {
		color: #23232a;
		text-shadow:
			0 1px 1.5px rgba(255, 255, 255, 0.95),
			0 -1px 1.5px rgba(255, 255, 255, 0.80),
			0 3px 14px rgba(255, 255, 255, 0.85);
	}

	.ctc:not(.is-on-dark) .ctc__caption-main b {
		color: #cc0c0c;
	}

	/* The unit is a light glyph with no housing behind it, so on the white
	   sections it needs an edge of its own or it disappears. A tight dark
	   contour does that and is invisible against the dark stage above, so
	   the approved look there is unchanged. */
	.ctc .ct3d__meter-unit {
		text-shadow:
			0 0 1px rgba(96, 0, 38, 0.95),
			0 1px 0 rgba(96, 0, 38, 0.85),
			-1px 0 0 rgba(96, 0, 38, 0.55),
			1px 0 0 rgba(96, 0, 38, 0.55),
			0 0 6px rgba(255, 90, 150, 0.40),
			0 2px 5px rgba(0, 0, 0, 0.70);
	}
}

/* ==========================================================================
   The closing scene: counter -> particles -> Earth
   ========================================================================== */

.ctf {
	display: none;
}

@media screen {

	/* --- the page the scene is on ------------------------------------------
	   White for the whole of the counter, the cloud and the planet; night by
	   the time the country is alone on it. `--ctf-night` is one number
	   written by the scene over the same span the sea is dissolving in, so
	   the background, the map's own tone and the light behind it arrive
	   together and reverse together.

	   Both surfaces take it, because both are visible: the section paints the
	   strip the sticky stage is not covering, and the stage paints the rest.
	   ---------------------------------------------------------------------- */

	.ctf {
		display: block;
		position: relative;
		z-index: 0;
		--ctf-night: 0;
		/* #0b0b0f at full night - the same colour the download block below it
		   is, so the seam between the two sections has nothing to show. */
		--ctf-page: rgb(
			calc(255 - 244 * var(--ctf-night)),
			calc(255 - 244 * var(--ctf-night)),
			calc(255 - 240 * var(--ctf-night)));
		background-color: var(--ctf-page);
		isolation: isolate;
	}

	.ctf__track {
		position: relative;
		/* real height is set in px from CONFIG.scrollDistancePx in
		   js/camtalk-final.js; this is only the pre-script fallback */
		height: 100vh;
	}

	.ctf__stage {
		position: sticky;
		top: 0;
		height: 100vh;
		overflow: hidden;
		background-color: var(--ctf-page, #ffffff);
	}

	.ctf__canvas {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		display: block;
	}

	/* ----------------------------------------------------------------------
	   The light the counter travels through.

	   Between the third chapter leaving and the burst, the counter is one
	   small object alone on a full white window. These three gradients give
	   that stretch somewhere to happen - warm, wide and clearly behind the
	   digits rather than around them.

	   The whole thing is three radial gradients, no blur filter and no image:
	   a gradient that ends on `transparent` already has softer edges than a
	   blurred box, and it costs the compositor nothing to move. Everything is
	   driven from three custom properties the scene writes on the container:

	     --a   overall opacity: in after the chapter, out after the burst
	     --t   0 at the top of the track, 1 at the burst - the slow drift
	     --k   0 -> 1 approaching the burst - the core tightens, coral lifts

	   so a frame is three property writes and the transforms below do the
	   rest. Nothing here runs on a timer: stop scrolling and it stops.
	   ---------------------------------------------------------------------- */

	.ctf__glow {
		position: absolute;
		inset: 0;
		overflow: hidden;          /* the spots reach past the edges on purpose */
		pointer-events: none;
		--a: 0;
		--t: 0;
		--k: 0;
		opacity: var(--a);
	}

	.ctf__glow-spot {
		position: absolute;
		will-change: transform, opacity;
	}

	/* Pale pink, wide, high on the left. `closest-side` makes the gradient an
	   ellipse inscribed in the box and the last stop is fully transparent, so
	   there is no edge of any shape to see - only the tint running out. */
	.ctf__glow-spot--left {
		left: -24%;
		top: -16%;
		width: 76%;
		height: 116%;
		background: radial-gradient(closest-side,
			rgba(246, 184, 198, 0.78) 0%,
			rgba(252, 227, 234, 0.54) 40%,
			rgba(255, 245, 247, 0.22) 70%,
			rgba(255, 245, 247, 0) 100%);
		transform: translate3d(calc(var(--t) * 44px - 18px), calc(var(--t) * -24px), 0)
			scale(calc(1 + var(--t) * 0.06));
	}

	/* Warm coral, smaller and lower on the right - the asymmetry is the point,
	   two matching blobs would read as a pattern. It is also the one that
	   lifts as the burst comes on. */
	.ctf__glow-spot--right {
		right: -20%;
		top: 4%;
		width: 68%;
		height: 106%;
		background: radial-gradient(closest-side,
			rgba(248, 174, 155, 0.66) 0%,
			rgba(252, 219, 208, 0.46) 42%,
			rgba(255, 245, 247, 0.19) 70%,
			rgba(255, 245, 247, 0) 100%);
		opacity: calc(0.62 + var(--k) * 0.38);
		transform: translate3d(calc(14px - var(--t) * 26px), calc(var(--t) * 28px), 0)
			scale(calc(1.02 - var(--t) * 0.06));
	}

	/* The big diffuse spot behind the counter's travel: 52% of the window
	   wide, centred on the middle of the climb-and-descent rather than on the
	   counter itself, and it drifts 46px while the counter travels 218 - it
	   holds the area, it does not follow the object.

	   Its own middle is left almost white. That is what keeps the digits and
	   the caption reading: the tint builds outwards from the centre, so the
	   counter sits in the light rather than on the colour. */
	.ctf__glow-spot--core {
		left: 50%;
		top: 36%;
		width: 54%;
		height: 66%;
		background: radial-gradient(closest-side,
			rgba(255, 246, 248, 0.95) 0%,
			rgba(253, 229, 236, 0.88) 32%,
			rgba(246, 184, 198, 0.56) 62%,
			rgba(246, 184, 198, 0) 100%);
		opacity: calc(0.88 + var(--k) * 0.12);
		transform: translate(-50%, -50%)
			translate3d(0, calc(var(--t) * 46px), 0)
			scale(calc(1 - var(--k) * 0.12));
	}

	/* ----------------------------------------------------------------------
	   The light behind South Korea

	   The same construction as the layer above, one property lower in the
	   stack and one property simpler: two gradients and a single alpha, with
	   nothing on a transform. That is deliberate - this one has to be STILL.
	   It arrives with the last of the approach and then holds exactly as it
	   is for the whole of the settled ending, so anything that drifted or
	   breathed would be the only moving thing on a page that has stopped.

	   Both spots are `closest-side` ellipses whose last stop is fully
	   transparent, so what the eye gets is tint running out into the page -
	   no circle, no oval, no edge anywhere. They are low enough in the stage
	   that the band holding the line and the button stays white, and they are
	   under the canvas, so the satellite tile is drawn over them at its own
	   contrast and is not tinted by a single pixel of this.
	   ---------------------------------------------------------------------- */
	.ctf__korea {
		position: absolute;
		inset: 0;
		overflow: hidden;
		pointer-events: none;
		--kg: 0;
		opacity: var(--kg);
	}

	.ctf__korea-spot {
		position: absolute;
	}

	/* Pale pink, wide, behind the mainland and a little to its west. */
	/* A wide window is mostly empty page with a small country in the middle
	   of it, so the light belongs around the country rather than out at the
	   edges: the mainland occupies roughly 43%..57% of the width here, and
	   these two are centred at 40% and 59% of it. */
	.ctf__korea-spot--west {
		left: 16%;
		top: 24%;
		width: 48%;
		height: 72%;
		/* Retuned for the night page. A pale pink that read as light on white
		   reads as grey haze on black, so the light is saturated and given
		   its energy in the core instead - the same two spots, the same
		   boxes, the same one custom property driving them. */
		background: radial-gradient(closest-side,
			rgba(255, 58, 110, 0.42) 0%,
			rgba(230, 36, 96, 0.26) 34%,
			rgba(168, 20, 74, 0.13) 60%,
			rgba(120, 12, 56, 0.05) 82%,
			rgba(120, 12, 56, 0) 100%);
	}

	/* Warmer, smaller, low to the east - the one that carries the coral over
	   towards the button's red. Two matching spots would read as a pattern,
	   so this one is neither the same size, the same height nor the same
	   colour as the one it sits beside. */
	.ctf__korea-spot--east {
		left: 37%;
		top: 42%;
		width: 44%;
		height: 62%;
		/* A long, shallow ramp rather than a core with a falloff round it -
		   a spot whose middle is much brighter than its surround is read as
		   an object, and an object with a soft edge is still an object. Most
		   of the alpha is spent between a third and four fifths of the way
		   out, which is where a light that is simply further away lives. */
		background: radial-gradient(closest-side,
			rgba(255, 96, 86, 0.32) 0%,
			rgba(226, 54, 72, 0.22) 32%,
			rgba(150, 24, 60, 0.12) 56%,
			rgba(96, 12, 44, 0.04) 80%,
			rgba(96, 12, 44, 0) 100%);
	}

	/* ======================================================================
	   THE COUNTRY AT NIGHT

	   Everything from here belongs to the ending the brief's reference asks
	   for: a dark page, light type, a map lit from inside it and the cities
	   named on it in HTML text.
	   ====================================================================== */

	/* --- the two lines that belong to one phase each ----------------------
	   The counter's line and the globe's. Same mechanics as the closing call
	   below them: an alpha written by the scene, a rise that is a function of
	   that alpha, and `visibility` following it so neither is ever in the
	   reading order while it is invisible.
	   ---------------------------------------------------------------------- */

	.ctf__lead,
	.ctf__globe {
		position: absolute;
		left: 50%;
		z-index: 2;
		width: max-content;
		max-width: min(720px, 86vw);
		transform: translateX(-50%);
		text-align: center;
		pointer-events: none;
		visibility: hidden;
	}

	.ctf__lead.is-live,
	.ctf__globe.is-live {
		visibility: visible;
	}

	/* Anchored to the counter, not to the window.

	   The counter's housing arrives at about 0.455 of the height and its top
	   edge sits near 0.255 of it; this block's BOTTOM edge is set 28px above
	   that, so the two read as one composition instead of a small line adrift
	   near the top of the screen. `--ctf-line-bottom` is written by the scene
	   for the same reason it is on the globe's line: the counter is placed
	   from the window, so the gap has to be solved per window rather than
	   guessed once. */
	.ctf__lead {
		bottom: var(--ctf-line-bottom, 74%);
	}

	/* Placed by the scene against the planet's own top edge - see
	   SceneLine.place() and assembledTopPx() in js/camtalk-final.js. The
	   fallback is only for the frames before the first measurement. */
	.ctf__globe {
		bottom: var(--ctf-line-bottom, 74%);
	}

	.ctf__lead-title,
	.ctf__globe-title {
		margin: 0;
		font-weight: 800;
		line-height: 1.32;
		letter-spacing: -0.022em;
		word-break: keep-all;
		color: #1b1b20;
		opacity: var(--a, 0);
		transform: translateY(calc(14px * (1 - var(--a, 0))));
		will-change: opacity, transform;
	}

	/* A size up: it is the only thing on the screen besides the counter it
	   belongs to, and it was reading as a caption. */
	.ctf__lead-title {
		font-size: clamp(27px, 1.4vw + 18px, 38px);
		line-height: 1.38;
	}

	.ctf__globe-title {
		font-size: clamp(24px, 1.3vw + 17px, 34px);
		line-height: 1.38;
	}

	/* The one accent each of these two lines carries. The brand red, the same
	   token the chapters' own headings use on white (--ctc-red: #cc0c0c) -
	   these blocks are over the closing scene's white, not over the night at
	   the end of it, so the pink of the final call would read as a different
	   system rather than as the same one. */
	.ctf__lead-title b,
	.ctf__globe-title b {
		font-weight: 800;
		color: #cc0c0c;
	}

	/* --- the cities -------------------------------------------------------
	   One layer over the canvas. Every marker is moved by a transform the
	   scene writes from the projection of its real coordinates, so the layer
	   itself has no layout of its own: `inset: 0` and nothing else.
	   ---------------------------------------------------------------------- */

	.ctf__places {
		position: absolute;
		inset: 0;
		z-index: 2;
		pointer-events: none;
		opacity: var(--a, 0);
		visibility: hidden;
	}

	.ctf__places.is-live {
		visibility: visible;
	}

	.ctf__links {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		overflow: visible;
	}

	.ctf__link {
		stroke: rgba(255, 110, 150, 0.30);
		stroke-width: 1;
		fill: none;
	}

	.ctf__pins {
		position: absolute;
		inset: 0;
	}

	/* The element IS the dot: 14px square, its centre on the city, and the
	   transform the scene writes is the whole of its placement.

	   The name is taken out of the flow rather than laid beside it. It used
	   to be a flex sibling, which worked for the five markers whose name
	   reads to the right and put Gwangju's dot 31px east of Gwangju - in a
	   reversed row the dot is the LAST item, so the box's origin was the
	   name's left edge and not the dot's centre. Absolutely positioned, the
	   name cannot move the dot whichever side it is on.
	   ---------------------------------------------------------------------- */
	.ctf__pin {
		position: absolute;
		left: 0;
		top: 0;
		width: 14px;
		height: 14px;
		margin: -7px 0 0 -7px;
		opacity: 0;
	}

	.ctf__pin.is-on {
		opacity: 1;
	}

	.ctf__pin-dot {
		position: absolute;
		inset: 0;
		display: block;
		border-radius: 50%;
		background: radial-gradient(circle at 42% 38%,
			#ffd0dd 0%, #ff4b7d 42%, #e01046 74%, #a80832 100%);
		box-shadow:
			0 0 0 3px rgba(255, 60, 110, 0.22),
			0 0 14px 4px rgba(255, 60, 110, 0.45),
			0 0 30px 10px rgba(255, 40, 90, 0.20);
	}

	.ctf__pin-name {
		position: absolute;
		top: 50%;
		left: calc(100% + 7px);
		transform: translateY(-50%);
		white-space: nowrap;
	}

	.ctf__pin--left .ctf__pin-name {
		left: auto;
		right: calc(100% + 7px);
	}

	.ctf__pin-name {
		font-size: 14px;
		font-weight: 700;
		letter-spacing: -0.01em;
		color: #fff;
		text-shadow: 0 1px 6px rgba(0, 0, 0, 0.85);
	}

	/* --- the way on ------------------------------------------------------- */

	/* Placement only: everything about how the hint looks is the shared
	   `.ct-hint` component in camtalk-scroll3d.css, which this section's
	   three phases drive through the same `--a` / `.is-live` pair. */
	/* `--ctf-hint-lift` is how far the sticky stage still hangs below the
	   window, written by the scene. During the entrance the stage is not
	   pinned yet, so its own bottom edge is off screen and a hint anchored to
	   it would be too; lifted by that offset, the hint sits in the window's
	   bottom band from the first frame it is asked for. It is 0 for the whole
	   of the pinned run, which is every other phase. */
	.ctf__hint {
		position: absolute;
		left: 22px;
		bottom: calc(16px + var(--ctf-hint-lift, 0px));
		z-index: 3;
		display: flex;
	}

	.ctf__sr {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		overflow: hidden;
		clip-path: inset(50%);
	}

	/* ----------------------------------------------------------------------
	   The closing line and the call to action.

	   Anchored from the BOTTOM, on a line the script puts just above the
	   planet's visible top edge (--ctf-cta-bottom). That is what keeps the
	   composition honest: the planet's size, path and resting place are
	   untouched, and the copy is fitted into the free band that is actually
	   left above it rather than to a guessed pixel.

	   The band is narrow - at 1918x908 the fixed site header ends at 85px and
	   the planet's halo begins at 302px, so the whole block has 217px to live
	   in. Hence the tight leading and the size below; see the report.

	   Every pixel in there is spoken for, and the three gaps trade against
	   each other: title 106, header air 28, title-to-button 16, button 48,
	   button-to-halo 19. Change one and one of the others has to give.
	   ---------------------------------------------------------------------- */

	.ctf__cta {
		position: absolute;
		left: 50%;
		bottom: var(--ctf-cta-bottom, 62%);
		transform: translateX(-50%);
		z-index: 2;
		display: flex;
		flex-direction: column;
		align-items: center;
		width: max-content;
		max-width: min(880px, 86vw);
		text-align: center;
		/* Hidden means hidden: no pointer, no tab stop, nothing for a screen
		   reader. The script lifts this the moment the block starts fading in
		   and drops it again on the way back up. */
		visibility: hidden;
		pointer-events: none;
	}

	.ctf__cta.is-live {
		visibility: visible;
	}

	.ctf__cta-title,
	.ctf__cta-sub {
		/* one shared pair of custom properties per part, written by the scene */
		opacity: var(--a, 0);
		transform: translateY(calc(var(--rise, 20px) * (1 - var(--a, 0))));
		will-change: opacity, transform;
	}

	.ctf__cta-title {
		margin: 0;
		/* the site's own big-heading treatment - same family, weight and
		   tracking as .ctc-title in the chapters above; only the size and the
		   leading are tightened, because this one has a button under it */
		font-size: clamp(41px, 29.9px + 1.05vw, 58px);
		font-weight: 800;
		line-height: 1.06;
		letter-spacing: -0.025em;
		/* The page is night by the time this block opens - the darkening runs
		   over the isolation and finishes before `ctaTitleFrom` on both
		   profiles - so the block is authored for night rather than crossed
		   over into it. */
		color: #fff;
	}

	.ctf__cta-title b {
		font-weight: 800;
		color: #ff5b87;
	}

	.ctf__cta-sub {
		margin: 14px 0 0;
		font-size: clamp(15px, 0.35vw + 13px, 18px);
		font-weight: 500;
		line-height: 1.62;
		letter-spacing: -0.01em;
		word-break: keep-all;
		color: rgba(255, 255, 255, 0.70);
		/* it travels a little less than the line above it, so the two read as
		   one block arriving rather than two things sliding */
		--rise: 12px;
	}

	/* English sets wider: it gives a little back so two lines still clear the
	   header in the same band */
	body.lang-en .ctf__cta-title {
		font-size: clamp(37px, 26.9px + 0.94vw, 52px);
	}

	/* --- reduced motion / no WebGL ---------------------------------------
	   A settled composition, no travel distance, nothing spinning. */

	.ctf--static .ctf__track {
		height: auto;
	}

	.ctf--static .ctf__stage {
		position: relative;
		height: 76vh;
		min-height: 520px;
	}

	/* The settled composition, arrived at rather than animated to: the line
	   and the words under it are simply there, in the place they end up in,
	   with no rise and nothing to wait for. */
	.ctf--static .ctf__cta-title,
	.ctf--static .ctf__cta-sub {
		--rise: 0px;
	}

	@media (prefers-reduced-motion: reduce) {
		.ctf__cta-title,
		.ctf__cta-sub,
		.ctf__lead-title,
		.ctf__globe-title {
			--rise: 0px;
			transition: none;
		}
	}

	/* The line over the globe is the phone's.

	   A wide window's planet assembles at 0.320 of the height and 0.255 of it
	   in radius, which puts its top edge 124px down a 900px window - 58px
	   under a 66px header. There is no band there for two lines of a heading
	   to be in, and the wide window's composition was signed off without one.
	   The counter's line above it does fit on both, and stays on both. */
	@media screen and (min-width: 1001px) {
		.ctf__globe {
			display: none;
		}
	}

	/* --- disabled: no empty height anywhere --- */

	.ctf--off {
		display: none;
	}
}

/* ==========================================================================
   MOBILE PROFILE
   ========================================================================== */

@media screen and (max-width: 1000px) {

	/* The gap the docked counter keeps from the bottom edge. Read back by
	   js/camtalk-counter.js, so the phone's own safe area is respected
	   without the script having to know anything about notches. */
	/* The gap the docked counter keeps from the bottom edge.
	 *
	 * Wider than it looks like it needs to be, and deliberately: the AI
	 * assistant's launcher is a 64px button pinned 17px off the bottom right
	 * corner, and a centred counter 79% of the width wide runs straight into
	 * it. Clearing it vertically keeps the counter centred - which is where
	 * it belongs - and leaves the corner to the assistant. The phone's own
	 * safe area is added on top. */
	.ctc {
		--ctc-dock-gap: calc(88px + env(safe-area-inset-bottom, 0px));
	}

	/* A phone screen is narrow, so the caption gives a little back and sits
	   closer to the digits - it still has to fit inside the counter's own
	   width at 360px. */
	.ctc__caption {
		bottom: calc(100% + var(--ct3d-cell) * 0.28);
		max-width: 132%;
	}

	.ctc__caption-intro {
		font-size: calc(var(--ct3d-cell) * 0.58);
	}

	.ctc__caption-main {
		font-size: calc(var(--ct3d-cell) * 0.92);
	}

	body.lang-en .ctc__caption-intro {
		font-size: calc(var(--ct3d-cell) * 0.50);
	}

	body.lang-en .ctc__caption-main {
		font-size: calc(var(--ct3d-cell) * 0.70);
	}

	/* ----------------------------------------------------------------------
	   The light behind the counter, on a narrow frame.

	   Same three gradients, same layer, same three custom properties from the
	   scene - only the boxes change. The two side spots hang further off the
	   edges, because on 360-412px a spot that fits inside the frame reads as
	   a blob rather than as light coming from the side; and the core is much
	   wider as a share of the window, because the counter itself is nearly
	   80% of it here. `overflow: hidden` on the layer is what keeps all of
	   that off the document's scroll width.
	   ---------------------------------------------------------------------- */

	.ctf__glow-spot--left {
		left: -34%;
		top: -10%;
		width: 92%;
		height: 88%;
	}

	.ctf__glow-spot--right {
		right: -30%;
		top: 8%;
		width: 86%;
		height: 84%;
	}

	/* Centred on the middle of the counter's own climb-and-descent, which on
	   the phone profile runs from 0.215 to 0.455 of the stage height. */
	.ctf__glow-spot--core {
		top: 33%;
		width: 92%;
		height: 46%;
	}

	/* The phone centres on the country's whole extent rather than on the
	   mainland - Ulleungdo is three degrees east of everything else - so the
	   land sits left of the middle here and the light follows it across. */
	.ctf__korea-spot--west {
		left: -14%;
		top: 30%;
		width: 88%;
		height: 64%;
	}

	.ctf__korea-spot--east {
		left: 26%;
		top: 46%;
		width: 92%;
		height: 60%;
	}

	/* ----------------------------------------------------------------------
	   The closing line and the button.

	   Same block, same markup, same keys, same link. The band it lives in is
	   actually roomier than on a wide window - the phone's planet is capped
	   at 40% of the WIDTH, so it sits lower and smaller - so the type is set
	   from the width and the gaps are the comfortable ones.
	   ---------------------------------------------------------------------- */

	/* ----------------------------------------------------------------------
	   The two headings of this scene, on a phone.

	   Both were set from a viewport-width term that a narrow window barely
	   moves, so both bottomed out on their clamp floor and read as captions
	   over the objects they belong to. They are sized from the WIDTH here,
	   against their own longest line, so they fill the measure the way the
	   brief's references do and still hold two lines at 360:

	     counter   "캠톡에서 매칭되고 있어요"   13 glyphs
	     globe     "국경을 넘어, 더 많은"        11 glyphs + space

	   7.1vw is 25.6px at 360, 27.7 at 390 and 30.5 at 430 - in every case the
	   long line sets inside the measure with the side padding intact.
	   ---------------------------------------------------------------------- */

	.ctf__lead-title {
		font-size: clamp(24px, 7.1vw, 31px);
		line-height: 1.3;
		letter-spacing: -0.028em;
	}

	/* The same system as the two headings in the section above: Paperozi 800,
	   closed-up leading, the same tracking. Only the accent differs, and that
	   is the brand's red because this one is read on white. */
	.ctf__globe-title {
		font-size: clamp(26px, 7.8vw, 34px);
		line-height: 1.22;
		letter-spacing: -0.03em;
	}

	/* English sets much wider and has to hold the same two lines. */
	body.lang-en .ctf__lead-title,
	body.lang-en .ctf__globe-title {
		font-size: clamp(21px, 5.9vw, 27px);
	}

	.ctf__cta {
		max-width: calc(100vw - 32px);
	}

	/* 29px at 360, 33px at 412 - two lines, no horizontal squeezing */
	.ctf__cta-title {
		font-size: clamp(26px, 1.3px + 7.69vw, 36px);
		line-height: 1.14;
		letter-spacing: -0.022em;
	}

	/* English sets wider and has to hold two lines in the same width */
	body.lang-en .ctf__cta-title {
		font-size: clamp(21px, 3.2px + 5.77vw, 30px);
	}

	.ctf__cta-sub {
		margin-top: 12px;
		font-size: 15px;
		line-height: 1.58;
		--rise: 8px;
	}

	/* Same stable height unit as the section above, for the same reason. */
	.ctf__stage {
		height: 100vh;
		height: 100svh;
	}

	.ctf--static .ctf__stage {
		height: 74svh;
		min-height: 420px;
	}
}
