@charset "utf-8";

/* ==========================================================================
   CamTalk / vod.php - 매력영상, the phone.

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

   WHAT THE PAGE IS, top to bottom: a full-screen hero that is one picture
   with the words on it; a row of category chips; the recommended video; the
   trending grid; the just-added grid; the shared footer. The player is a
   dialog that is empty until something is played.

   THE SYSTEM. One gutter, one gap, one radius, one red. The gutter is 16px
   at 360, 18px at 390 and 20px at 430 - the brief's own range - and every
   section uses it. Posters are 16:9 because the sources are 16:9.

   STABILITY.
     * The hero's picture is an <img> INSIDE the hero. No
       `background-attachment: fixed`, no scroll-driven transform, no scale
       per scroll event.
     * The hero's height is `100svh`: the SMALL viewport unit is the height
       WITH the address bar showing, so it does not change when the bar
       slides away. `min-height`, not `height`, so a short screen or a longer
       translation grows the hero rather than clipping the copy.
     * Every picture has width and height attributes and a box with a fixed
       ratio, so a late poster cannot move the card under it.
     * 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
       anywhere below would otherwise paint over the bar on the way past.
     * The reveal is opacity plus an 8px lift, one-shot, and only on cards
       that were already below the fold when the script ran.
   ========================================================================== */

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

	.ctv-page {
		--cv-gutter: clamp(16px, 4.7vw, 20px);
		--cv-gap: clamp(10px, 2.9vw, 12px);
		--cv-radius: 12px;

		--cv-bg: #ffffff;
		--cv-bg-2: #f6f6f8;
		--cv-ink: #14141a;
		--cv-ink-2: #3c3c45;
		--cv-muted: #8d8d97;
		--cv-line: #ebebef;
		--cv-red: #e8253f;
		--cv-red-deep: #cf1b33;
		--cv-night: #0b0d16;

		--cv-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. */
	.ctv, .ctv *, .ctv *::before, .ctv *::after { box-sizing: border-box; }

	/* The wide window's page. Same markup, same strings, simply not laid out
	   here. */
	.ctv-page .ct-vod-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. */
	.ctv-page .ctv[hidden] { display: block; }

	.ctv { background: var(--cv-bg); color: var(--cv-ink); }
	.ctv img { display: block; max-width: 100%; }
	.ctv a { text-decoration: none; }
	.ctv ul { list-style: none; }
	.ctv em { font-style: normal; }
	/* `:where()` scores zero, so this resets the UA's button skin and still
	   loses to every single class below it - including `font`, which is a
	   shorthand and would otherwise reset each chip's size. */
	:where(.ctv) button { background: none; font: inherit; cursor: pointer; }

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

	/* `.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. */
	.ctv-page .gnb:not(.gnb_invert) { border-bottom-color: transparent; }

	.ctv-sr {
		position: absolute; width: 1px; height: 1px; margin: -1px;
		padding: 0; overflow: hidden; clip: rect(0 0 0 0);
		clip-path: inset(50%); white-space: nowrap; border: 0;
	}

	/* ======================================================================
	   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 top of the picture is dark, so the bar keeps the white
	   type it has by default and this file writes nothing about it.
	   ====================================================================== */

	.ctv-hero {
		position: relative;
		z-index: 0;
		isolation: isolate;
		display: flex;
		flex-direction: column;
		justify-content: flex-end;
		min-height: 100vh;
		min-height: 100svh;
		overflow: hidden;
		background: #0a0c16;
	}

	/* THE HERO CLIP, and the poster under it.

	   One element. Its `poster` is the still this hero used to be, so the
	   box is never empty and never white: that still is what the preload in
	   inc/top.php already fetches, what a reduced-motion reader keeps, and
	   what a refused autoplay falls back to. The script hands the element a
	   source only when the clip is genuinely wanted, so there is no second
	   request and nothing to undo.

	   The clip 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 - the same crop the still took. Nothing is stretched and
	   nothing is zoomed past what filling the screen needs. No border, no
	   radius, no gutter and no transform: the box IS the section, and it
	   scrolls because the section does. */
	.ctv-hero__video {
		position: absolute;
		inset: 0;
		z-index: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		object-position: 50% 50%;
		/* Decorative and muted. It must not eat the taps meant for the
		   button over it, and it must not be reachable by the keyboard. */
		pointer-events: none;
		/* The section is this colour too, so a frame that has not decoded
		   yet shows the hero's own dark rather than the UA's black. */
		background: #0a0c16;
	}

	/* 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. It reaches 88% at the very bottom and
	   is gone by 62% of the height, so it never reaches the middle third of
	   the frame - which is where both the still and the clip keep their
	   faces - and the room, the phones and the grid all stay readable as
	   picture. 88% and not the still's 82%: this clip cuts to a white room
	   three times, and white under white type wants the extra six points.
	   The head ramp is short and light and exists so the bar's white type
	   holds over the top of the frame. */
	.ctv-hero__shade {
		position: absolute;
		inset: 0;
		z-index: 1;
		pointer-events: none;
		background:
			/* THE HEAD BAND, and why it no longer ends on an edge.

			   While this hero was a still, the band stopped dead at 13.55% - the
			   hard step where the translucent panel drawn into that photograph
			   began. Ending on a step that was already in the picture turned two
			   soft boundaries into one crisp one.

			   The clip has no such step, so a band that still stopped at 13.55%
			   would be drawing its OWN horizontal line across a moving picture -
			   and this clip is bright white behind the bar in most of its scenes,
			   which is exactly where such a line would be most visible. So the
			   band fades out instead: the same weight where the bar and the
			   breadcrumb sit, gone by a quarter of the way down, quoted at five
			   stops so the ramp does not show an edge of its own. It is still
			   local to the head, and it still never reaches the middle third,
			   which is where this clip keeps its faces. */
			linear-gradient(
				to bottom,
				rgba(6, 8, 16, 0.56) 0%,
				rgba(6, 8, 16, 0.52) 34%,
				rgba(6, 8, 16, 0.40) 58%,
				rgba(6, 8, 16, 0.20) 80%,
				rgba(6, 8, 16, 0) 100%
			) top / 100% 25% no-repeat,
			linear-gradient(
				to top,
				rgba(6, 8, 16, 0.88) 0%,
				rgba(6, 8, 16, 0.84) 8%,
				rgba(6, 8, 16, 0.74) 17%,
				rgba(6, 8, 16, 0.58) 27%,
				rgba(6, 8, 16, 0.40) 37%,
				rgba(6, 8, 16, 0.22) 47%,
				rgba(6, 8, 16, 0.08) 56%,
				rgba(6, 8, 16, 0) 62%
			);
	}

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

	/* The breadcrumb belongs at the head of the hero, under the bar, as the
	   reference has it - so it is pulled to the top of the body box while the
	   rest of the stack stays at the foot. */
	.ctv-crumb {
		margin-bottom: auto;
		padding-bottom: clamp(30px, 12vw, 70px);
		font-size: 12.5px;
		font-weight: 600;
		letter-spacing: 0.01em;
		color: rgba(255, 255, 255, 0.76);
	}
	.ctv-crumb b { color: #fff; font-weight: 700; }
	.ctv-crumb span { margin: 0 5px; opacity: 0.6; }

	/* The heavy weight of the project's own Paperozi, white, set tight - the
	   character the second reference shows. */
	.ctv-hero__title {
		font-size: clamp(48px, 14.5vw, 58px);
		font-weight: 800;
		line-height: 1.04;
		letter-spacing: -0.03em;
		word-break: keep-all;
	}

	.ctv-hero__sub {
		margin-top: clamp(12px, 3.4vw, 16px);
		font-size: clamp(17px, 4.9vw, 20px);
		font-weight: 600;
		line-height: 1.48;
		letter-spacing: -0.015em;
		color: rgba(255, 255, 255, 0.96);
		word-break: keep-all;
	}

	.ctv-hero__desc {
		margin-top: clamp(10px, 2.9vw, 13px);
		font-size: clamp(13px, 3.7vw, 15px);
		font-weight: 400;
		line-height: 1.68;
		color: rgba(255, 255, 255, 0.72);
		word-break: keep-all;
	}

	html[lang="en"] .ctv-hero__title,
	html[lang="en"] .ctv-hero__sub,
	html[lang="en"] .ctv-hero__desc {
		word-break: normal;
		overflow-wrap: break-word;
	}

	.ctv-hero__cta {
		align-self: flex-start;
		display: inline-flex;
		align-items: center;
		gap: 9px;
		margin-top: clamp(20px, 5.6vw, 26px);
		min-height: 52px;
		padding: 0 22px;
		border-radius: 999px;
		background: var(--cv-red);
		color: #fff;
		font-size: clamp(14px, 4vw, 16px);
		font-weight: 700;
		letter-spacing: -0.01em;
		box-shadow: 0 10px 26px -12px rgba(232, 37, 63, 0.9);
	}
	.ctv-hero__cta svg {
		width: 17px; height: 17px; fill: none; stroke: #fff;
		stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
	}

	/* ======================================================================
	   2. THE CATEGORIES
	   ====================================================================== */

	.ctv-cats {
		position: relative;
		z-index: 0;
		isolation: isolate;
		padding: clamp(18px, 5vw, 24px) 0 clamp(4px, 1.4vw, 8px);
		background: var(--cv-bg);
	}

	/* One row. It scrolls sideways if a translation makes the four labels
	   wider than the window, rather than wrapping or pushing the PAGE
	   sideways; the negative margin lets it bleed to the screen edge while
	   the first and last chip stay on the gutter. */
	.ctv-cats__row {
		display: flex;
		gap: 8px;
		padding: 0 var(--cv-gutter);
		overflow-x: auto;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}
	.ctv-cats__row::-webkit-scrollbar { display: none; }

	.ctv-chip {
		flex: 0 0 auto;
		display: inline-flex;
		align-items: center;
		gap: 6px;
		min-height: 38px;
		padding: 0 15px;
		border-radius: 999px;
		background: #f0f0f3;
		color: var(--cv-ink-2);
		font-size: 13.5px;
		font-weight: 600;
		letter-spacing: -0.01em;
		white-space: nowrap;
	}
	.ctv-chip__icon {
		width: 16px; height: 16px; fill: none; stroke: currentColor;
		stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
	}
	.ctv-chip.is-on {
		background: var(--cv-red);
		color: #fff;
		box-shadow: 0 8px 20px -12px rgba(232, 37, 63, 0.95);
	}
	/* The reference's first chip has a solid flame; the rest are outlines. */
	.ctv-chip.is-on .ctv-chip__icon { fill: currentColor; stroke: none; }

	/* ======================================================================
	   3. SECTIONS AND HEADINGS
	   ====================================================================== */

	.ctv-section {
		position: relative;
		z-index: 0;
		isolation: isolate;
		padding: clamp(24px, 6.6vw, 30px) var(--cv-gutter) clamp(6px, 1.7vw, 10px);
		background: var(--cv-bg);
	}
	.ctv-section[hidden] { display: none; }
	.ctv-section:last-of-type { padding-bottom: clamp(38px, 10vw, 48px); }

	.ctv-head {
		display: flex;
		align-items: center;
		gap: 12px;
		margin-bottom: clamp(14px, 4vw, 18px);
	}

	/* The reference's short red rule, as a pseudo-element so it cannot be
	   mistaken for content and cannot wrap away from the words. */
	.ctv-head__title {
		position: relative;
		flex: 1 1 auto;
		min-width: 0;
		padding-left: 13px;
		font-size: clamp(21px, 6vw, 25px);
		font-weight: 800;
		line-height: 1.24;
		letter-spacing: -0.03em;
		color: var(--cv-ink);
		word-break: keep-all;
	}
	.ctv-head__title::before {
		content: "";
		position: absolute;
		left: 0;
		top: 0.16em;
		width: 4px;
		height: 0.92em;
		border-radius: 2px;
		background: var(--cv-red);
	}
	html[lang="en"] .ctv-head__title { word-break: normal; overflow-wrap: break-word; }

	.ctv-more {
		flex: 0 0 auto;
		display: inline-flex;
		align-items: center;
		gap: 5px;
		font-size: 13px;
		font-weight: 600;
		color: var(--cv-ink-2);
		white-space: nowrap;
	}
	.ctv-more[hidden] { display: none; }
	.ctv-more svg {
		width: 15px; height: 15px; fill: none; stroke: currentColor;
		stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
	}

	/* ======================================================================
	   4. POSTERS
	   ====================================================================== */

	.ctv-poster {
		position: relative;
		display: block;
		aspect-ratio: 16 / 9;
		border-radius: var(--cv-radius);
		overflow: hidden;
		background: #e7e7ea;        /* the box is reserved before the file lands */
	}
	.ctv-poster img { width: 100%; height: 100%; object-fit: cover; }
	.ctv-poster--lg { border-radius: 14px; }

	/* Only the recommended poster carries one, as the reference does: on a
	   grid of twelve, twelve rings over twelve faces is noise, and the
	   duration chip already says "this is a video". */
	.ctv-card .ctv-poster__play { display: none; }

	.ctv-poster__play {
		position: absolute;
		left: 50%;
		top: 50%;
		transform: translate(-50%, -50%);
		display: grid;
		place-items: center;
		width: 44px;
		height: 44px;
		border: 2px solid rgba(255, 255, 255, 0.92);
		border-radius: 50%;
		background: rgba(12, 12, 18, 0.30);
	}
	.ctv-poster__play svg { width: 22px; height: 22px; fill: #fff; margin-left: 1px; }
	.ctv-poster__play--lg { width: 60px; height: 60px; border-width: 2.5px; }
	.ctv-poster__play--lg svg { width: 30px; height: 30px; }

	/* Bottom right, where YouTube puts it and where the reference puts it.

	   The inset is 3px and not the 6-8px this would otherwise want, because
	   eight of these twelve thumbnails carry the channel's app-icon
	   watermark in that corner: it occupies the bottom-right 9.2% x 16.4% of
	   the frame, inset 2.2% / 3.6%, which on a 171px card is a 16px square
	   starting 3.7px in. At this size and inset the chip covers it exactly,
	   which is also what YouTube's own listing does - and what the repo's
	   305px screenshots of that listing were showing, muddily, at a quarter
	   of the resolution. */
	.ctv-poster__time {
		position: absolute;
		right: 3px;
		bottom: 3px;
		min-height: 22px;
		display: flex;
		align-items: center;
		padding: 0 7px 1px;
		border-radius: 6px;
		background: rgba(8, 8, 12, 0.94);
		color: #fff;
		font-size: 11px;
		font-weight: 700;
		line-height: 1.1;
		letter-spacing: 0.01em;
		font-variant-numeric: tabular-nums;
	}
	/* The recommended clip's thumbnail has no watermark, so its chip sits
	   where the reference draws it. */
	.ctv-poster--lg .ctv-poster__time {
		right: 10px;
		bottom: 10px;
		min-height: 26px;
		padding: 0 9px 1px;
		font-size: 12.5px;
	}

	.ctv-poster__badge {
		position: absolute;
		left: 9px;
		top: 9px;
		padding: 5px 10px 6px;
		border-radius: 8px;
		background: rgba(12, 12, 18, 0.72);
		color: #fff;
		font-size: 10.5px;
		font-weight: 800;
		line-height: 1;
		letter-spacing: 0.12em;
	}

	/* ======================================================================
	   5. THE RECOMMENDED VIDEO
	   ====================================================================== */

	.ctv-pick { display: block; color: inherit; }
	.ctv-pick__body { display: block; padding-top: clamp(13px, 3.7vw, 16px); }

	.ctv-label {
		display: block;
		font-size: 11px;
		font-weight: 800;
		letter-spacing: 0.1em;
		line-height: 1.2;
		color: var(--cv-red);
	}

	.ctv-pick__title {
		display: block;
		margin-top: 8px;
		font-size: clamp(18px, 5.1vw, 21px);
		font-weight: 700;
		line-height: 1.34;
		letter-spacing: -0.025em;
		color: var(--cv-ink);
		word-break: keep-all;
	}
	.ctv-pick__title em { color: var(--cv-red); }

	.ctv-pick__desc {
		display: block;
		margin-top: 9px;
		font-size: clamp(13px, 3.6vw, 14.5px);
		font-weight: 400;
		line-height: 1.68;
		color: var(--cv-muted);
		word-break: keep-all;
	}
	html[lang="en"] .ctv-pick__title,
	html[lang="en"] .ctv-pick__desc { word-break: normal; overflow-wrap: break-word; }

	.ctv-pick__by {
		display: flex;
		align-items: center;
		gap: 8px;
		margin-top: 13px;
		font-size: 12.5px;
		color: var(--cv-muted);
	}
	.ctv-pick__ch {
		display: inline-flex;
		align-items: center;
		padding: 4px 10px 5px;
		border: 1px solid var(--cv-line);
		border-radius: 999px;
		font-weight: 700;
		color: var(--cv-ink-2);
	}

	/* ======================================================================
	   6. THE GRIDS
	   ====================================================================== */

	.ctv-grid {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: clamp(18px, 5vw, 24px) var(--cv-gap);
	}

	/* `minmax(0, 1fr)` above and `min-width: 0` here keep a long title from
	   widening its own column. */
	.ctv-card { min-width: 0; }
	.ctv-card[hidden] { display: none; }
	.ctv-card__link { display: block; color: inherit; }

	.ctv-card__meta { display: block; margin-top: 9px; }
	/* One line, never two. "CAMTALK POPULAR VOD" is nineteen characters and
	   at the reference's tracking it broke as "CAMTALK POPUL / AR VOD" in a
	   170px column. The date used to share this row and is now its own line
	   under the title, where it cannot collide with the label at 360px. */
	.ctv-card__meta .ctv-label {
		font-size: 9.5px;
		letter-spacing: 0.04em;
		white-space: nowrap;
	}
	.ctv-date {
		display: block;
		margin-top: 6px;
		font-size: 10.5px;
		font-weight: 500;
		color: var(--cv-muted);
		font-variant-numeric: tabular-nums;
	}

	/* The titles on this page all open with the same sixteen characters, so
	   they run to three lines in a 170px column. They are NOT clamped: the
	   brief asks for the whole name, and a clamp here would leave twelve
	   cards reading "터치 & 서치 내손에 영상데이트 캠톡 …" and nothing else. */
	.ctv-card__title {
		display: block;
		margin-top: 5px;
		font-size: clamp(14px, 3.9vw, 15.5px);
		font-weight: 600;
		line-height: 1.42;
		letter-spacing: -0.02em;
		color: var(--cv-ink);
		word-break: keep-all;
		overflow-wrap: anywhere;
	}
	html[lang="en"] .ctv-card__title { word-break: normal; overflow-wrap: break-word; }

	/* ======================================================================
	   7. THE PLAYER

	   Above everything, including the assistant, whose launcher sits at
	   z-index 2147482000 in the root stacking context from inside its own
	   shadow root.
	   ====================================================================== */

	.ctv-player {
		position: fixed;
		inset: 0;
		z-index: 2147483000;
		display: flex;
		align-items: center;
		justify-content: center;
		/* A little tighter than the page's gutter: the clips are 16:9 and
		   every pixel of width is 0.56 of a pixel of picture. */
		padding: 0 12px;
	}
	.ctv-player[hidden] { display: none; }

	.ctv-player__veil {
		position: absolute;
		inset: 0;
		background: rgba(4, 5, 10, 0.94);
	}

	.ctv-player__box {
		position: relative;
		z-index: 1;
		width: 100%;
		max-width: 560px;
	}

	.ctv-player__frame {
		position: relative;
		aspect-ratio: 16 / 9;
		border-radius: 12px;
		overflow: hidden;
		background: #000;
	}
	/* The player is whatever shape the clip is - the frame is 16:9 and the
	   video letterboxes inside it, which is what YouTube's own embed does and
	   what keeps a vertical clip from being cropped. */
	.ctv-player__frame iframe {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		border: 0;
	}

	.ctv-player__close {
		position: absolute;
		right: -4px;
		bottom: calc(100% + 12px);
		display: grid;
		place-items: center;
		width: 40px;
		height: 40px;
		border-radius: 50%;
		background: rgba(255, 255, 255, 0.14);
	}
	.ctv-player__close svg {
		width: 19px; height: 19px; fill: none; stroke: #fff;
		stroke-width: 2; stroke-linecap: round;
	}

	.ctv-player__title {
		margin-top: 14px;
		font-size: 14px;
		font-weight: 600;
		line-height: 1.5;
		color: rgba(255, 255, 255, 0.92);
		word-break: keep-all;
	}
	html[lang="en"] .ctv-player__title { word-break: normal; overflow-wrap: break-word; }

	/* The background is frozen with `position: fixed` on <body> and its own
	   offset written back, so opening the player cannot scroll the page to
	   the hero and closing it returns to the exact row. */
	body.ctv-locked { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden; }

	/* ======================================================================
	   8. THE REVEAL

	   `.ctv-veil` is put on by the script and only on cards already below the
	   fold when it runs, so nothing on screen is hidden and then shown, and a
	   page whose script never arrives shows everything from the first paint.
	   One-shot: scrolling back up cannot hide anything again.
	   ====================================================================== */

	.ctv-veil {
		opacity: 0;
		transform: translate3d(0, 8px, 0);
	}
	.ctv-veil.ctv-in {
		opacity: 1;
		transform: none;
		transition: opacity 0.42s ease, transform 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
	}

	@media (prefers-reduced-motion: reduce) {
		.ctv-veil,
		.ctv-veil.ctv-in {
			opacity: 1;
			transform: none;
			transition: none;
		}
	}
}
