@charset "utf-8";

/* ==========================================================================
   CamTalk / service/camtalker.php - 캠톡커, the phone.

   SCOPE. Every rule in this file is inside
   `@media only screen and (max-width: 1000px)`, the project's own breakpoint,
   and every selector under it is nested in `.ctm-page`, a class only this
   page puts on <body>. There is no `min-width` block at all: the wide window
   renders pages.service_camtalker exactly as it did, and this file says
   nothing about it.

   WHAT THE PAGE IS, top to bottom: a full-screen photograph with the words on
   it; three characteristics in a lane, one at a time; one phone standing in
   its own light; four steps down a rail; the shared footer. The wide page has
   two more sections after those and keeps them; the phone stopped drawing
   them on 2026-09-22 and their rules came out of this file with them.

   THE SYSTEM. One gutter, one radius, one red, three type sizes.
     gutter   16px at 360, 18px at 390, 20px at 430 - clamped, never a
              media query of its own
     radius   18px on cards
     red      #e8253f, the site's own
     rhythm   every section is 76-88px of air, top and bottom, so the page
              reads as one measure rather than four different ones

   STABILITY.
     * The hero's photograph is an <img> INSIDE its section. No
       `background-attachment: fixed`, no scroll-driven transform, no scale
       per scroll event, no snap. Ordinary scrolling, both directions.
     * The lane moves on `transform` and `opacity` only - the two properties
       the compositor can animate without laying the page out again - and its
       track is as tall as its tallest card at all times, so advancing a card
       cannot change the height of anything.
     * The hero is `min-height: 100svh` - the SMALL viewport unit is the
       height WITH the address bar showing, so the hero does not resize when
       the bar slides away. `min-height`, not `height`, so a short screen or
       a longer translation grows it rather than clipping the copy.
     * Every picture carries width and height attributes and sits in a box
       with a fixed ratio, so nothing that arrives late can move what is
       under it. There is no layout shift to measure.
     * Every section carries `z-index: 0; isolation: isolate` beside its
       `position: relative`. `.gnb` is z-index 1 in the ROOT stacking context
       and `.gnb_fixed` adds no z-index of its own, so a positioned child
       further down the page would otherwise paint over the bar on the way
       past.
     * The reveal is opacity plus an 8px lift, one-shot, and it is armed only
       on what was below the fold when the script ran - so a fast scroll can
       never leave anything invisible. Under `prefers-reduced-motion` the
       whole thing is never armed and every section is simply visible.
   ========================================================================== */

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

	.ctm-page {
		--cm-gutter: clamp(16px, 4.7vw, 20px);
		--cm-air: clamp(76px, 20vw, 88px);
		--cm-radius: 18px;

		--cm-bg: #ffffff;
		--cm-tint: #fdf5f6;          /* the reference's blush, at 3% */
		--cm-blush: #fff3f6;         /* ACTIVITY and the closing band, one field */
		--cm-ink: #17171d;
		--cm-ink-2: #43434d;
		--cm-muted: #8b8b95;
		--cm-red: #e8253f;

		--cm-header: 65px;           /* .gnb's own height on the phone */
	}

	/* This project sets no global `box-sizing`. Declared here on this page's
	   own elements only: site-wide it would move every existing block. */
	.ctm, .ctm *, .ctm *::before, .ctm *::after { box-sizing: border-box; }

	/* The wide window's page. Same markup, same strings, simply not laid out
	   here - and js/camtalk-camtalker-mobile.js has already emptied it, so
	   this rule is hiding a box that holds nothing. */
	.ctm-page .ct-camtalker-desktop { display: none; }

	/* `hidden` is on <main> in the HTML so a wide window never shows the
	   phone's markup, not even for the frame before this file arrives. Below
	   the breakpoint this rule decides, not the attribute. */
	.ctm-page .ctm[hidden] { display: block; }

	/* Column flex and not plain block flow, for one reason: the newline and
	   the tab between two sections in the source are a text node, and in
	   block flow that text node gets an anonymous line box 8px tall. Six
	   sections, six ghost gaps, 48px of page nobody wrote. A flex container
	   drops whitespace-only children outright.

	   THERE IS NO `overflow-x: hidden` HERE, and there must never be one.
	   It was added as a belt-and-braces guard and it stopped the page
	   scrolling on a real phone.

	   Why: when one axis of `overflow` is not `visible`, the other axis
	   cannot stay `visible` either - it computes to `auto`. So `overflow-x:
	   hidden` silently made this element a VERTICAL scroll container, and
	   sub-pixel section heights left it with about 8px of scrollable range.
	   On a desktop wheel that costs one notch and then chains to the page.
	   On a touch screen it does not chain: a gesture LATCHES to the first
	   scroller it moves, so a finger swiping the page moved this box its 8px
	   and then held still for the rest of the swipe - and the next swipe
	   latched again. The page could not be scrolled by hand at all.

	   Nothing is lost by removing it. Every box that actually has something
	   to clip clips it itself: the lane's window holds its two off-screen
	   slides, and the hero and the closing card each hold their own artwork.
	   `document.scrollWidth === clientWidth` is checked at 360, 390 and 430. */
	.ctm {
		display: flex;
		flex-direction: column;
		background: var(--cm-bg);
		color: var(--cm-ink);
	}
	.ctm img { display: block; max-width: 100%; }
	.ctm a { text-decoration: none; }
	.ctm ul, .ctm ol { list-style: none; margin: 0; padding: 0; }
	/* `:where()` scores ZERO, and that is the whole point of it being here.
	   Written plainly this reset is `.ctm p` at (0,1,1), which outranks every
	   single-class rule in this file at (0,1,0) - so `margin-top` on
	   `.ctm-lede`, `.ctm-act__desc`, `.ctm-step__desc`, `.ctm-hero__desc` and
	   `.ctm-cta__desc` all computed to zero and those gaps were quietly never
	   drawn. Wrapped, it still clears the UA's margins and loses to every one
	   of them. */
	:where(.ctm) :where(h1, h2, h3, p) { margin: 0; }

	/* Outline only. A `border-radius` in a focus rule is the ELEMENT's radius,
	   not the outline's, and would reshape whatever is focused. */
	.ctm a:focus-visible { outline: 3px solid var(--cm-red); outline-offset: 3px; }

	/* `.gnb` carries `border-bottom: 1px solid rgba(255,255,255,.3)` for the
	   pages whose hero is a flat colour. Over a photograph it is a hairline
	   ruled across the picture 65px down. It comes back the moment
	   js/common.js turns the bar white past 150px, which is where a divider
	   belongs. */
	.ctm-page .gnb:not(.gnb_invert) { border-bottom-color: transparent; }

	/* ======================================================================
	   SHARED PARTS
	   ====================================================================== */

	.ctm-sec {
		position: relative;
		z-index: 0;
		isolation: isolate;
		padding: var(--cm-air) var(--cm-gutter);
		background: var(--cm-bg);
	}
	.ctm-sec--tint { background: var(--cm-tint); }
	.ctm-sec--blush { background: var(--cm-blush); }

	/* THE SEAMS. Every section used to bring its own full measure of air to
	   both edges, so each join paid for it twice: 178px from the lane's dots
	   to the next heading, 140px under the phone, 86px under the last step.
	   The rhythm is now set per join, as ONE total split across the two
	   sides of it, and it is quoted as what the reader sees:

	     dots -> WHAT A CAMTALKER DOES     ~46px  (12 + 22 + the 11.5px of
	                                               the dot's own tap target)
	     phone -> CAMTALKER FLOW           ~46px  (10 + 22 + the 14px of
	                                               transparent foot the phone
	                                               artwork carries)
	     last step -> the closing heading  ~36px  (28 + 8)
	     hero -> CAMTALKER ACTIVITY        ~32px  (the section's own top)

	   Written against the structure rather than new classes, so the markup
	   is untouched: ACTIVITY is the section after the hero, FLOW the one
	   after the phone. */
	.ctm-hero + .ctm-sec { padding-top: 32px; padding-bottom: 12px; }
	.ctm-does + .ctm-sec { padding-top: 22px; padding-bottom: 28px; }

	.ctm-head { margin-bottom: clamp(26px, 7vw, 32px); }
	.ctm-head--center { text-align: center; }

	/* The reference's small red line over every heading. `letter-spacing` on
	   the last glyph pushes a centred line half a space left, so the tracking
	   is paid back with a matching indent rather than left to drift. */
	.ctm-eyebrow {
		font-size: 12px;
		font-weight: 700;
		letter-spacing: 0.16em;
		text-indent: 0.16em;
		color: var(--cm-red);
	}
	.ctm-eyebrow--light { color: #ff8b9c; }

	.ctm-title {
		margin-top: 12px;
		font-size: clamp(27px, 7.6vw, 32px);
		font-weight: 800;
		line-height: 1.3;
		letter-spacing: -0.03em;
		color: var(--cm-ink);
		/* Korean breaks between any two syllables unless it is told not to.
		   `keep-all` keeps a word whole and moves the whole word down. */
		word-break: keep-all;
	}

	.ctm-lede {
		margin-top: 16px;
		font-size: clamp(14px, 3.9vw, 15px);
		line-height: 1.75;
		letter-spacing: -0.015em;
		color: var(--cm-ink-2);
		word-break: keep-all;
	}
	/* This breakpoint runs to 1000px, and on a tablet a centred paragraph
	   that keeps the whole measure is one long line with ragged ends rather
	   than a centred block. 30em holds it to about the proportion the
	   section reference has. On a phone it is wider than the gutters leave,
	   so it changes nothing there and nothing has to be said twice. */
	.ctm-head--center .ctm-lede {
		max-width: 30em;
		margin-left: auto;
		margin-right: auto;
	}

	/* The hero's button, and now the only one on the phone. Its glow is two
	   rings and an inner wash - no filter and no blurred pseudo-element, so
	   nothing has to be re-rasterised while the page moves. */
	.ctm-btn {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		gap: 10px;
		min-height: 54px;
		padding: 0 26px;
		border-radius: 999px;
		font-size: clamp(15px, 4.1vw, 16px);
		font-weight: 700;
		letter-spacing: -0.01em;
	}
	.ctm-btn--red {
		background: var(--cm-red);
		color: #fff;
		box-shadow:
			0 0 0 1px rgba(232, 37, 63, 0.24),
			0 10px 26px rgba(232, 37, 63, 0.30);
	}
	.ctm-btn__arrow svg {
		display: block;
		width: 18px;
		height: 18px;
		fill: none;
		stroke: currentColor;
		stroke-width: 2;
		stroke-linecap: round;
		stroke-linejoin: round;
	}

	/* ======================================================================
	   1. THE HERO

	   Header and hero are the first screen TOGETHER: the hero starts at y=0,
	   `.gnb` is `position: absolute` over it, and the copy is padded clear of
	   the bar. The bar's height is never added to the hero's, so 100svh is
	   the whole first screen and not one bar more.
	   ====================================================================== */

	.ctm-hero {
		position: relative;
		z-index: 0;
		isolation: isolate;
		display: flex;
		flex-direction: column;
		min-height: 100vh;
		min-height: 100svh;
		overflow: hidden;
		background: #05060a;
	}

	.ctm-hero__img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		/* The frame is 9 : 16 and the hero is taller than that in proportion
		   on every phone, so `cover` scales it by HEIGHT and takes about 9%
		   off each side. 62% and not 50%: the figure sits right of centre
		   and the left third of the frame is an unlit wall, so the crop is
		   spent there rather than on her. Nothing of the face, which sits at
		   28-42% of the height, is lost at 360, 390 or 430.

		   The frame changed on 2026-09-22 and this value did not have to:
		   the picture that replaced it puts its subject in the same half. */
		object-position: 62% 50%;
	}

	/* Two ramps on one element, each quoted at several stops - a linear ramp
	   over a photograph shows its own edge, a faint horizontal line where the
	   eye expects none.

	   The foot ramp carries the copy: 0.90 at the very bottom, gone by 58% of
	   the height. The face ends at 30%, so it is never touched, and the
	   spotlight, the dress and the phone in her hand all stay readable AS
	   PICTURE. The head band is short and light and exists for the bar and
	   the breadcrumb. */
	.ctm-hero__shade {
		position: absolute;
		inset: 0;
		z-index: 1;
		pointer-events: none;
		background:
			linear-gradient(
				to bottom,
				rgba(4, 5, 10, 0.50) 0%,
				rgba(4, 5, 10, 0.40) 46%,
				rgba(4, 5, 10, 0.18) 76%,
				rgba(4, 5, 10, 0) 100%
			) top / 100% 22% no-repeat,
			linear-gradient(
				to top,
				rgba(4, 5, 10, 0.90) 0%,
				rgba(4, 5, 10, 0.87) 7%,
				rgba(4, 5, 10, 0.80) 15%,
				rgba(4, 5, 10, 0.68) 24%,
				rgba(4, 5, 10, 0.52) 33%,
				rgba(4, 5, 10, 0.34) 42%,
				rgba(4, 5, 10, 0.17) 50%,
				rgba(4, 5, 10, 0.05) 55%,
				rgba(4, 5, 10, 0) 58%
			);
	}

	/* Fills the hero so that `margin-bottom: auto` on the breadcrumb can put
	   it under the bar while the copy stays at the foot. */
	.ctm-hero__body {
		position: relative;
		z-index: 2;
		flex: 1 1 auto;
		display: flex;
		flex-direction: column;
		padding: calc(var(--cm-header) + 14px) var(--cm-gutter)
			calc(clamp(30px, 8vw, 40px) + env(safe-area-inset-bottom));
		color: #fff;
	}

	/* The `auto` margin splits the hero into a head group and a foot group:
	   the breadcrumb under the bar, the copy at the foot. It spent 2026-09-22
	   on the note that hung under the breadcrumb; the note came off on
	   2026-09-23 and the margin came back here, so it leaves no gap. */
	.ctm-crumb {
		margin-bottom: auto;
		font-size: 12.5px;
		font-weight: 600;
		letter-spacing: 0.01em;
		color: rgba(255, 255, 255, 0.72);
	}
	.ctm-crumb b { color: #fff; font-weight: 700; }
	.ctm-crumb span { margin: 0 5px; opacity: 0.6; }

	.ctm-hero__title {
		margin-top: 14px;
		font-size: clamp(32px, 9.1vw, 38px);
		font-weight: 800;
		line-height: 1.24;
		letter-spacing: -0.035em;
		color: #fff;
		word-break: keep-all;
	}

	.ctm-hero__desc {
		margin-top: clamp(14px, 4vw, 18px);
		font-size: clamp(13.5px, 3.7vw, 14.5px);
		line-height: 1.72;
		letter-spacing: -0.015em;
		color: rgba(255, 255, 255, 0.80);
		word-break: keep-all;
	}

	.ctm-hero__copy .ctm-btn {
		margin-top: clamp(22px, 6vw, 28px);
		/* The assistant's launcher is FIXED at the foot right - 56px wide,
		   12px in - and this button is the only thing on the page that sits
		   at the foot of the screen beside it. 66px is that launcher plus
		   its own margin, subtracted from the measure, so the two cannot
		   meet at any width. At 360 that is what decides; at 430 the 300px
		   cap does, and the button is nowhere near it. */
		width: min(300px, calc(100% - 66px));
	}

	/* ======================================================================
	   2. CAMTALKER ACTIVITY
	   ====================================================================== */

	/* THE LANE.

	   The window clips, the track slides, and the track is a flex row of
	   three cards each exactly as wide as the window. That is the whole
	   mechanism: one `translate3d` on one element per change, no per-card
	   positioning, no measuring, nothing read back from layout while it
	   moves.

	   `overflow: hidden` here is what keeps the two off-screen cards off the
	   PAGE. They are laid out at +100% and +200% of this box, which is 100%
	   of the content width, so without the clip the document would be three
	   screens wide and the whole page would scroll sideways.

	   `touch-action: pan-y` is the other half of the swipe: it tells the
	   browser to keep handling vertical scrolling itself and hand the
	   horizontal axis to the script. Without it a downward flick started on a
	   card is swallowed.

	   THE PADDING AT THE FOOT IS FOR THE SHADOW, and it is not decoration.
	   `overflow` clips to the PADDING box, and the card is exactly as wide
	   and as tall as this box was - so the card's shadow was being sliced
	   into a rectangle, and the rounded bottom corners were showing that
	   rectangle's square grey corner through them. 24px is room for the
	   shadow to end on its own; the matching negative margin gives the lane
	   back exactly what the padding took, so the dots do not move and no
	   height changes anywhere.

	   Sideways there is no padding and none is needed: the shadow is quoted
	   with a negative spread that keeps it inside the card's own width, so
	   there is nothing at the left or right edge left to clip. */
	.ctm-acts__view {
		overflow: hidden;
		touch-action: pan-y;
		padding-bottom: 24px;
		margin-bottom: -24px;
	}

	.ctm-acts__track {
		display: flex;
		/* Equal height, always: the tallest card sets it and the other two
		   stretch to match, so advancing never changes the section's height
		   and nothing below it moves. */
		align-items: stretch;
		will-change: transform;
	}
	/* `.is-animated` is put on by the script AFTER the first position is set,
	   so the lane cannot animate in from nowhere on load, and is taken off
	   again while a finger is down so the card tracks the finger exactly. */
	.ctm-acts__track.is-animated {
		transition: transform 0.52s cubic-bezier(0.22, 0.61, 0.36, 1);
	}

	/* `flex: 0 0 100%` and not `width: 100%`: a flex item with a width can
	   still be shrunk by its siblings, and three of them in one row would
	   each end up a third of the lane. */
	.ctm-acts__track > .ctm-act {
		flex: 0 0 100%;
		max-width: 100%;
		/* The short fade that rides on the slide. The card leaving dims as it
		   goes and the one arriving comes up - the movement reads as one card
		   replacing another rather than a strip being dragged past. */
		opacity: 0.35;
		transition: opacity 0.45s ease;
	}

	/* THE ONE SHOWING carries the only shadow in this section.

	   ONE short layer, rose and not grey: a grey shadow on a blush field is
	   a dirty halo. It must also never reach the SIDES, because the card is
	   exactly as wide as the window and the window clips - the old shadow
	   (32px blur, -16px spread) did reach them, and its clipped ends drew a
	   square grey band under the card. Here the spread (-18px) is larger
	   than the blur (22px) can recover sideways, so at the card's side edges
	   there is nothing left to cut; below, it fades out within the window's
	   24px of foot padding. */
	.ctm-acts__track > .ctm-act.is-on {
		opacity: 1;
		box-shadow:
			inset 0 1px 0 rgba(255, 255, 255, 0.9),
			0 14px 22px -18px rgba(214, 38, 72, 0.34);
	}

	/* Before the script runs - and if it never does - the lane is three cards
	   the reader can swipe by hand, so none of them may be dimmed. */
	.ctm-acts:not(.is-live) .ctm-acts__track > .ctm-act {
		opacity: 1;
	}
	.ctm-acts:not(.is-live) .ctm-acts__view { overflow-x: auto; }

	.ctm-dots {
		display: flex;
		justify-content: center;
		gap: 8px;
		margin-top: clamp(18px, 4.8vw, 22px);
	}
	.ctm-dots:empty { display: none; }
	/* 30px of touch target around a 7px mark: the dot people see is the
	   ::after, the button they can actually hit is the padding around it.

	   The mark is ALWAYS 20px wide and the dot is cut out of it with
	   `clip-path`. It used to animate `width` 7px -> 20px, which is a layout
	   property, so every advance of the lane - every two seconds, while the
	   reader scrolls past it - ran layout. The clip draws the same 7px circle
	   and the same 20px pill and costs paint only. */
	.ctm-dots button {
		display: block;
		width: 30px;
		height: 30px;
		padding: 0;
		border: 0;
		background: none;
		cursor: pointer;
		-webkit-tap-highlight-color: transparent;
	}
	.ctm-dots button::after {
		content: "";
		display: block;
		width: 20px;
		height: 7px;
		margin: 0 auto;
		border-radius: 999px;
		background: rgba(23, 23, 29, 0.18);
		-webkit-clip-path: inset(0 6.5px round 3.5px);
		clip-path: inset(0 6.5px round 3.5px);
		transition: background-color 0.3s ease, clip-path 0.3s ease, -webkit-clip-path 0.3s ease;
	}
	.ctm-dots button[aria-current="true"]::after {
		-webkit-clip-path: inset(0 0 round 3.5px);
		clip-path: inset(0 0 round 3.5px);
		background: var(--cm-red);
	}
	.ctm-dots button:focus-visible {
		outline: 3px solid var(--cm-red);
		outline-offset: -4px;
		border-radius: 999px;
	}

	/* THE CARD. A rose-to-white panel on the blush field: the top is the
	   more saturated end, so the icon and the heading sit in colour and the
	   paragraph on near-white. One translucent rose hairline gives it its
	   edge, and the shadow belongs only to the card that is showing - see
	   `.is-on` under the lane above.

	   Its height is the TALLEST card's: the track stretches all three to it,
	   in either language, so an advance never changes the section's height.
	   Nothing here animates but the lane's own transform and opacity. */
	.ctm-act {
		display: flex;
		flex-direction: column;
		align-items: center;
		padding: clamp(24px, 6.4vw, 28px) clamp(20px, 5.4vw, 24px) clamp(26px, 7vw, 30px);
		border: 1px solid rgba(232, 37, 63, 0.10);
		border-radius: 22px;
		background:
			radial-gradient(120% 62% at 50% 0%, rgba(255, 206, 219, 0.50) 0%, rgba(255, 206, 219, 0) 72%),
			linear-gradient(180deg, #ffe9ef 0%, #fff6f8 46%, #ffffff 100%);
		text-align: center;
	}

	/* THE ICON. Three drawings, not three photographs, and drawn for this page
	   rather than taken off a sheet.

	   ONE HOUSE STYLE, and it is the same three things in each:
	     * a contact shadow under the mark - a radial-gradient ellipse, NOT a
	       `filter`. The lane these sit in slides, and a filter on a moving
	       layer is re-rasterised every frame of it;
	     * one same-hue coral ramp, #ff8090 through #f4415a to #e2153a, and no
	       second hue anywhere;
	     * inner light as white at low alpha, clipped to the mark, always from
	       the same corner.
	   No stroke on any filled shape, so there is no hard outline in any of
	   them, and no perspective, so none of them is pretending to be an object.

	   The box is square and so is the viewBox, so the drawing scales with the
	   card and never distorts.

	   THE BASE is this box, and it is the ONLY base: a soft round light, lit
	   from the same top-left corner as the marks. The heart used to carry a
	   disc of its own inside its SVG and the other two carried none; that
	   disc was taken out of the markup, so no icon sits on two. Each SVG's
	   viewBox is framed to its mark, so the three read the same size on the
	   base - the heart is wide, the shield is tall. */
	.ctm-act__media {
		display: block;
		width: clamp(80px, 21.5vw, 88px);
		height: clamp(80px, 21.5vw, 88px);
		border-radius: 50%;
		background: radial-gradient(circle at 34% 26%, #ffffff 0%, #fff4f6 46%, #ffe0e8 100%);
		box-shadow:
			inset 0 0 0 1px rgba(255, 255, 255, 0.95),
			0 8px 16px -10px rgba(214, 38, 72, 0.32);
	}
	.ctm-act__icon {
		display: block;
		width: 100%;
		height: 100%;
		overflow: visible;
	}

	.ctm-act__body { margin-top: clamp(16px, 4.4vw, 20px); }

	.ctm-act__title {
		font-size: clamp(21px, 5.9vw, 24px);
		font-weight: 800;
		line-height: 1.34;
		letter-spacing: -0.035em;
		color: var(--cm-ink);
		word-break: keep-all;
	}
	/* A warm dark and not the page's grey: on a rose panel a neutral grey
	   reads as faded. */
	.ctm-act__desc {
		margin-top: 10px;
		font-size: clamp(14px, 3.85vw, 15px);
		line-height: 1.66;
		letter-spacing: -0.015em;
		color: #5c4a51;
		word-break: keep-all;
	}

	/* ======================================================================
	   3. WHAT A CAMTALKER DOES

	   THE SECTION IS THE VISUAL. There is no card here and no panel: no
	   border, no radius, no white box, no side gutter around the artwork,
	   nothing that could read as a placeholder. The light runs from edge to
	   edge, the words stand in it, and the phone rises out of the same light.

	   That is only possible because the supplied artwork is a cut-out with a
	   real alpha channel - it has no background of its own, so the section
	   can be its background, and the two are one picture rather than a
	   picture inside a frame.

	   The field is built from four layers and nothing else - no filter, no
	   backdrop-filter, no shadow, no blurred pseudo-element, so there is
	   nothing the compositor has to re-rasterise while the page moves:

	     1. a warm rose bloom low and centred, where the phone stands;
	     2. a wide, very faint blush wash above it, so the copy is not sitting
	        on flat paper;
	     3. one soft red ambient at the foot, the brand's own, at 10%;
	     4. a vertical ramp that STARTS on the tint of the section above and
	        ENDS on the tint of the section below, so this one joins both
	        without a seam at either end.
	   ====================================================================== */

	/* AS TALL AS WHAT IS IN IT: the copy, then the phone, and nothing
	   distributed between or around them. About 700px at 390 in either
	   language, so it still reads as one screen.

	   Until 2026-09-23 it was held to `min-height: 100svh` and the phone was
	   centred in whatever the copy left, which put ~50px of slack above the
	   device and ~60px below it; and its head padding carried the bar's 65px
	   on top of its air, as though the section were pinned under a fixed
	   header - it never is, it scrolls. Both are gone. There is NO viewport
	   unit here at all now, so there is nothing for the address bar to
	   resize: never `dvh` (it changes mid-scroll on a real phone and was the
	   "accordion"), and no `svh` left either, because nothing needs one. */
	.ctm-does {
		position: relative;
		z-index: 0;
		isolation: isolate;
		/* NO `overflow: hidden`. It had one, to clip a bloom that hung 6%
		   below the section, and that left the box with 51px it was hiding
		   from itself. A hidden overflow is not user-scrollable so it never
		   latched a finger the way `.ctm` did, but a full-screen section that
		   is quietly clipping part of itself is one resize away from hiding
		   something that matters. The bloom was moved inside instead, and now
		   there is nothing here to clip. */
		display: flex;
		flex-direction: column;
		/* The head joins the lane's dots, the foot joins FLOW - see THE SEAMS. */
		padding: 22px 0 10px;
		background:
			radial-gradient(76% 34% at 50% 74%, rgba(255, 176, 198, 0.55) 0%, rgba(255, 176, 198, 0) 70%),
			radial-gradient(120% 44% at 50% 22%, rgba(255, 224, 232, 0.85) 0%, rgba(255, 224, 232, 0) 74%),
			radial-gradient(90% 26% at 50% 100%, rgba(232, 37, 63, 0.10) 0%, rgba(232, 37, 63, 0) 72%),
			linear-gradient(to bottom, var(--cm-tint) 0%, #fff7f9 18%, #ffeff3 62%, var(--cm-tint) 100%);
	}

	/* The bloom that ties the type to the artwork. It is a plain radial on
	   its own layer so it can sit BEHIND the copy and still reach up from
	   behind the phone - one light, not a halo drawn around each. */
	.ctm-does__glow {
		position: absolute;
		z-index: 0;
		left: 0;
		right: 0;
		/* Flush with the foot, not 6% past it: the section no longer clips,
		   so anything hanging below would be real overflow on the page. The
		   bloom is shaped by its gradient rather than by where the box ends,
		   so sitting it on the floor costs nothing. */
		bottom: 0;
		height: 66%;
		pointer-events: none;
		/* The bloom is wider than the screen, but it is the GRADIENT that is
		   oversized, not the box - 150% of the box, centred. A box 150% wide
		   would do the same thing visually and then hang off the right of the
		   page, where `overflow: hidden` catches it but every later audit
		   still has to work out why an element is 488px wide on a 390px
		   screen. */
		background: radial-gradient(
			150% 116% at 50% 104%,
			rgba(255, 138, 168, 0.40) 0%,
			rgba(255, 138, 168, 0.18) 44%,
			rgba(255, 138, 168, 0) 78%
		);
	}

	.ctm-does__copy {
		position: relative;
		z-index: 1;
		flex: 0 0 auto;
		padding: 0 var(--cm-gutter);
		text-align: center;
	}
	/* Held in a touch tighter than the page's own lede, because on this
	   screen every line of it is a line the phone does not get. The size is
	   untouched - it is the leading and the measure that give. */
	.ctm-does__copy .ctm-lede {
		margin-top: clamp(10px, 2.8vw, 14px);
		max-width: 27em;
		margin-left: auto;
		margin-right: auto;
		line-height: 1.62;
	}
	.ctm-does__copy .ctm-title { margin-top: clamp(8px, 2.4vw, 12px); }

	/* THE STAGE is the row the phone stands in, and it is an ordinary block
	   in the column - `position: relative` only so it sits over the section's
	   own bloom, `z-index: 1` and no higher. Nothing here is absolutely
	   positioned against the section, nothing is transformed, nothing is
	   scaled and no margin is negative. It is exactly as tall as the phone:
	   no flexible row, no slack to centre in. */
	.ctm-does__stage {
		position: relative;
		z-index: 1;
		flex: 0 0 auto;
		display: flex;
		justify-content: center;
		margin-top: clamp(10px, 3vw, 18px);
	}

	/* THE PHONE IS SIZED BY ITS WIDTH, not by the screen it is left with.

	   It used to be `width: 100%` with `object-fit: contain` doing the fitting,
	   which drew it 304px wide at 390 - large enough to read as a backdrop
	   rather than as a device. The clamp puts it at about 246px at 390 and
	   268px at 430: plainly the biggest thing in the section, and plainly a
	   phone.

	   Its height follows from that width and the 880 x 1564 in the markup,
	   so the box is reserved before the lazy image arrives and nothing
	   below it moves when it does. Nothing bounds it by height any more: the
	   stage is sized BY the phone, not the other way round. */
	.ctm-does__phone {
		display: block;
		width: clamp(228px, 63vw, 268px);
		max-width: 100%;
		height: auto;
	}

	/* ======================================================================
	   4. CAMTALKER FLOW
	   ====================================================================== */

	.ctm-flow { display: grid; gap: clamp(12px, 3.2vw, 16px); }

	.ctm-step {
		position: relative;
		display: grid;
		grid-template-columns: 34px 62px 1fr;
		align-items: start;
		gap: clamp(12px, 3.4vw, 16px);
		padding: clamp(18px, 4.8vw, 22px) clamp(16px, 4.4vw, 20px);
		border-radius: var(--cm-radius);
		background: #fff;
		box-shadow:
			0 1px 0 rgba(23, 23, 29, 0.04),
			0 8px 24px rgba(84, 30, 40, 0.06);
	}

	/* The rail is what the reference's chevrons carried: these are in order
	   and one leads to the next. It is drawn on the rail cell rather than
	   between the cards, so it cannot fall out of step with the gap. */
	.ctm-step__rail {
		position: relative;
		display: block;
		width: 34px;
		align-self: stretch;
	}
	.ctm-step__num {
		position: relative;
		z-index: 1;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 34px;
		height: 34px;
		border-radius: 999px;
		background: var(--cm-red);
		color: #fff;
		font-size: 13px;
		font-weight: 800;
		letter-spacing: 0.01em;
	}
	.ctm-step__rail::after {
		content: "";
		position: absolute;
		left: 50%;
		top: 34px;
		width: 2px;
		/* Down through the card's own bottom padding and across the gap to
		   the next one. */
		height: calc(100% - 34px + clamp(30px, 8vw, 38px));
		margin-left: -1px;
		border-radius: 1px;
		background: linear-gradient(
			to bottom,
			rgba(232, 37, 63, 0.28) 0%,
			rgba(232, 37, 63, 0.10) 100%
		);
	}
	.ctm-step--last .ctm-step__rail::after { display: none; }

	.ctm-step__icon {
		display: block;
		width: 62px;
		height: 62px;
	}
	.ctm-step__icon img { width: 100%; height: 100%; object-fit: contain; }

	.ctm-step__title {
		font-size: clamp(17px, 4.7vw, 19px);
		font-weight: 700;
		line-height: 1.34;
		letter-spacing: -0.03em;
		color: var(--cm-ink);
		word-break: keep-all;
	}
	.ctm-step__desc {
		margin-top: 8px;
		font-size: clamp(13px, 3.6vw, 14px);
		line-height: 1.68;
		letter-spacing: -0.015em;
		color: var(--cm-muted);
		word-break: keep-all;
	}

	/* ======================================================================
	   5. THE CLOSING BAND

	   NOT a card. Until 2026-09-23 this was a rounded pink panel inside a
	   white section; now the SECTION is the colour - the same solid blush as
	   CAMTALKER ACTIVITY, edge to edge, with no box, radius, border, shadow
	   or gradient, running down to the footer's own edge. The copy keeps a
	   24px gutter and the left alignment it had. Nothing here has a fixed
	   height - the band is as tall as what is in it, in either language.

	   The top padding is small on purpose: the section above ends on its own
	   full air, so a second full measure here would be a hole.
	   ====================================================================== */

	.ctm-cta {
		position: relative;
		z-index: 0;
		isolation: isolate;
		padding: clamp(8px, 2vw, 12px) 24px
			calc(clamp(48px, 13vw, 56px) + env(safe-area-inset-bottom));
		background: var(--cm-blush);
	}

	/* A positioning box for the heart and nothing else. */
	.ctm-cta__box { position: relative; }

	/* The closing heart, at 28-30px: a coral gradient outline over a light
	   gradient fill, one white highlight in the left lobe and a pink halo
	   under all of it - everything that shapes it is inside the SVG. It is
	   decorative and `aria-hidden` in the markup, so it carries no label. It
	   sits level with the heading's first line, at the gutter. */
	.ctm-cta__heart {
		position: absolute;
		top: 0;
		right: 0;
		width: clamp(28px, 7.4vw, 30px);
		height: clamp(28px, 7.4vw, 30px);
	}

	.ctm-cta__title {
		/* Held clear of the heart, so a longer line breaks before it reaches
		   it rather than running under it. */
		padding-right: clamp(46px, 13vw, 56px);
		font-size: clamp(21px, 5.9vw, 24px);
		font-weight: 800;
		line-height: 1.42;
		letter-spacing: -0.035em;
		color: var(--cm-ink);
		word-break: keep-all;
	}
	/* The reference sets two words of the heading in the brand red. They are
	   `<em>` in the string so the emphasis travels with the translation
	   instead of being a span this file has to count characters for. */
	.ctm-cta__title em {
		font-style: normal;
		color: var(--cm-red);
	}

	.ctm-cta__desc {
		margin-top: clamp(12px, 3.4vw, 16px);
		font-size: clamp(13px, 3.6vw, 14px);
		line-height: 1.68;
		letter-spacing: -0.015em;
		color: #8a6570;
		word-break: keep-all;
	}

	/* Full width of the content -
	   so the button is the widest thing on the screen and impossible to miss.
	   The assistant's launcher is fixed at the foot RIGHT and this section's
	   own bottom padding keeps the button above it; the two are checked at
	   360, 390 and 430. */
	.ctm-cta__btn {
		display: flex;
		width: 100%;
		margin-top: clamp(20px, 5.4vw, 24px);
		min-height: 58px;
		/* Softer than the hero's: that one stands on a dark photograph, this
		   one on blush, where the same glow reads as a smudge. */
		box-shadow:
			0 0 0 1px rgba(232, 37, 63, 0.20),
			0 8px 18px -6px rgba(232, 37, 63, 0.34);
	}

	/* ======================================================================
	   THE REVEAL

	   Opacity and an 8px lift, one-shot. `is-armed` is put on by the script
	   and ONLY on what was below the fold when it ran, so nothing that was
	   already on screen is taken away and put back, and a page whose script
	   fails shows everything. Under `prefers-reduced-motion` the script never
	   arms anything, so this block never applies to a single element.
	   ====================================================================== */

	.ctm [data-ctm-reveal].is-armed {
		opacity: 0;
		transform: translateY(8px);
		transition: opacity 0.5s ease, transform 0.5s ease;
	}
	.ctm [data-ctm-reveal].is-armed.is-in {
		opacity: 1;
		transform: none;
	}

	@media (prefers-reduced-motion: reduce) {
		.ctm [data-ctm-reveal].is-armed {
			opacity: 1;
			transform: none;
			transition: none;
		}
		/* The lane still WORKS - the script leaves the swipe and the dots
		   armed and only stops the timer - but it arrives at the next card
		   instead of travelling to it, and no card is dimmed on the way. */
		.ctm-acts__track.is-animated { transition: none; }
		.ctm-acts__track > .ctm-act { opacity: 1; transition: none; }
	}
}
