/**
 * KISS YouTube Gallery — the plugin sheet. Structure only.
 *
 * The plugin owns geometry: grid, columns, gaps, aspect ratios, the featured/list
 * split, the play affordance, focus rings, transitions, reduced motion. The theme
 * owns skin: typeface, weight, tracking, case, colour, heading scale, body size and
 * line-height. Nothing in this file sets typography or a
 * literal colour on a text node — every text node inherits, so a real <h3> picks up
 * the Kit's H3 style with no plugin CSS at all.
 *
 * Every value is a custom property declared on the root at (0,1,0), resolving
 * through a three-step chain: our own variable → the Elementor Kit's global → inherit
 * / currentColor. With Elementor Pro, Elementor free or no Elementor at all, the
 * gallery adopts the site.
 *
 * Cascade, weakest to strongest:
 *   1. theme (e.g. Hello Elementor)
 *   2. this sheet                             .kiss-youtube                              (0,1,0)
 *   3. Elementor Kit / Theme Style            .elementor-kit-N h3 …                      (0,1,1)
 *   4. global plugin setting + widget/shortcode  .kiss-youtube:where(#kiss-yt-…)          (0,1,0, later)
 *   5. site CSS                               .elementor-widget-kiss_youtube .kiss-youtube (0,2,0)
 *   6. Elementor Style-tab controls           .elementor-element-<id> .kiss-youtube        (0,2,0, later)
 *
 * Nothing here is flagged important. Where a rule below uses a modifier, pseudo-element or
 * combinator, it only ever reads variables — so a site re-points the variable on the
 * root and the higher-specificity rule follows. The two exceptions that set direct
 * values above (0,1,0) are the <button> resets, which have to beat a Kit's
 * `.elementor-kit-N button` rule or the play button renders as a giant pill.
 */

/* --------------------------------------------------------------------------
   Root + tokens
   -------------------------------------------------------------------------- */

.kiss-youtube {
	/* Palette — our var → the Kit global → inherit from the theme */
	--kiss-yt-title-color: var(--e-global-color-text, currentColor);
	--kiss-yt-meta-color: var(--e-global-color-text, currentColor);
	--kiss-yt-accent: var(--e-global-color-accent, currentColor);
	--kiss-yt-surface: var(--e-global-color-primary, transparent);
	--kiss-yt-title-font: var(--e-global-typography-primary-font-family, inherit);
	--kiss-yt-meta-font: var(--e-global-typography-text-font-family, inherit);

	/* Play affordance: a disc with the triangle knocked out, drawn in CSS */
	--kiss-yt-play-size: 92px;
	--kiss-yt-play-size-row: 32px;
	--kiss-yt-play-size-card: 56px;
	--kiss-yt-play-fill: var(--kiss-yt-accent);
	--kiss-yt-play-icon: transparent;
	--kiss-yt-play-hover: var(--kiss-yt-play-fill);
	--kiss-yt-play-hover-scale: 1.06;

	/* Text */
	--kiss-yt-meta-size: 0.875em;
	--kiss-yt-meta-opacity: 0.8;
	--kiss-yt-meta-gap: 0.75em;
	--kiss-yt-row-title-size: 1em;
	--kiss-yt-title-lines: none;
	--kiss-yt-row-title-lines: 2;
	--kiss-yt-desc-lines: 3; /* 0 = no clamp: an invalid line-clamp value computes to none. */
	--kiss-yt-desc-mode: clamp; /* clamp | more | scroll — per breakpoint from the settings block; read by the script. */
	--kiss-yt-scroll-margin: 0px;
	--kiss-yt-touch-peek: 12%; /* Touch scroller: how much of the next card shows at the edge. */



	/* Filter bar (tags / hashtags). Off unless filters are configured. The row and
	   the text-tab tokens mirror CoverFlow's filter row (--kiss-tab-*). */
	--kiss-yt-filter-justify: center;
	--kiss-yt-filter-gap-x: 2em;
	--kiss-yt-filter-gap-y: 0.5em;
	--kiss-yt-filter-mb: var(--kiss-yt-gap);
	--kiss-yt-filter-size: 1em;
	--kiss-yt-filter-color: var(--kiss-yt-meta-color);           /* idle */
	--kiss-yt-filter-idle-opacity: 0.8;
	--kiss-yt-filter-active-color: var(--kiss-yt-accent);
	--kiss-yt-filter-rule-color: currentColor;                    /* text tabs: the rule under the active one */
	--kiss-yt-filter-rule-h: 2px;
	--kiss-yt-filter-rule-offset: -4px;
	--kiss-yt-filter-bg: transparent;                             /* chips */
	--kiss-yt-filter-border: currentColor;
	--kiss-yt-filter-active-bg: transparent;
	--kiss-yt-filter-active-border: var(--kiss-yt-accent);
	--kiss-yt-filter-pad: 0.4em 1em;
	--kiss-yt-filter-radius: 999px; /* Extra room above whatever the script scrolls into view; fixed and sticky headers are measured. */

	/* Geometry */
	--kiss-yt-gap: 20px;
	--kiss-yt-split: 62.2%;
	--kiss-yt-ratio: 16 / 9;
	--kiss-yt-radius: 0px;
	--kiss-yt-cols: 3;
	--kiss-yt-col-min: 280px;
	--kiss-yt-body-gap: 16px;
	--kiss-yt-text-gap: 8px;
	--kiss-yt-label-gap: 14px;
	--kiss-yt-label-space: 2.5em;
	--kiss-yt-row-thumb: 50.2%;
	--kiss-yt-row-gap: 20px;
	--kiss-yt-row-pad: 19px;

	/* Divider between up-next rows */
	--kiss-yt-divider: 1px;
	--kiss-yt-divider-color: var(--kiss-yt-meta-color);
	--kiss-yt-divider-opacity: 0.2;

	/* Up-next list: height, scrollbar, optional bottom fade */
	--kiss-yt-list-max-h: 100%;
	--kiss-yt-scrollbar-w: 6px;
	--kiss-yt-scrollbar-track: transparent;
	--kiss-yt-scrollbar-thumb: var(--kiss-yt-accent);
	--kiss-yt-scrollbar-radius: 3px;
	--kiss-yt-list-fade: 0px;

	/* Scroll hint ("Scroll for more") overlaid at the bottom of the list */
	--kiss-yt-hint-color: var(--kiss-yt-accent);
	--kiss-yt-hint-bg: transparent;
	--kiss-yt-hint-size: 0.8125em;
	--kiss-yt-hint-band: 44px;
	--kiss-yt-hint-pad: 0;
	--kiss-yt-hint-fade: 40px;

	/* Duration badge — an overlay on a photo, not theme text, so it carries its own
	   contrast pair. The only two literal colours in this sheet; both are tokens. */
	--kiss-yt-badge-bg: rgba(0, 0, 0, 0.72);
	--kiss-yt-badge-color: #ffffff;

	/* Focus */
	--kiss-yt-focus: var(--kiss-yt-accent);
	--kiss-yt-focus-w: 2px;

	position: relative;
	display: block;
	width: 100%;
}

.kiss-youtube *,
.kiss-youtube *::before,
.kiss-youtube *::after {
	box-sizing: border-box;
}

/* Column defaults per band. The per-instance settings block and site CSS re-point
   these at the same breakpoints. */
@media (max-width: 1024px) {
	.kiss-youtube {
		--kiss-yt-cols: 2;
	}
}

@media (max-width: 767px) {
	.kiss-youtube {
		--kiss-yt-cols: 1;
	}
}

/* --------------------------------------------------------------------------
   Item — the same structure in every layout, so the showcase can move a node
   between the featured slot and the list by changing one modifier class.
   -------------------------------------------------------------------------- */

.kiss-yt-item {
	position: relative;
	display: block;
	margin: 0;
	min-width: 0;
}

.kiss-yt-item[hidden] {
	display: none;
}

/* Variant tokens. Set here, read by the parts below through inheritance. */
.kiss-yt-item--featured {
	--kiss-yt-play-size-local: var(--kiss-yt-play-size);
}

.kiss-yt-item--card {
	--kiss-yt-play-size-local: var(--kiss-yt-play-size-card);
	break-inside: avoid;
	margin-bottom: var(--kiss-yt-card-mb, 0);
}

.kiss-yt-item--row {
	--kiss-yt-play-size-local: var(--kiss-yt-play-size-row);
	--kiss-yt-title-lines: var(--kiss-yt-row-title-lines);
	--kiss-yt-desc-display: none;
	--kiss-yt-body-gap-local: 0px;
	display: grid;
	grid-template-columns: var(--kiss-yt-row-thumb) minmax(0, 1fr);
	gap: var(--kiss-yt-row-gap);
	align-items: start;
	padding-block: var(--kiss-yt-row-pad);
	cursor: pointer;
}

/* The first row sits level with the top of the player, with no divider above it. */
.kiss-yt-item--row:where(:first-child) {
	padding-top: 0;
}

.kiss-yt-item--row::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: var(--kiss-yt-divider);
	background: var(--kiss-yt-divider-color);
	opacity: var(--kiss-yt-divider-opacity);
}

.kiss-yt-item--row:where(:first-child)::before {
	display: none;
}

/* --------------------------------------------------------------------------
   Media box — explicit aspect ratio on every thumbnail box: zero CLS.
   -------------------------------------------------------------------------- */

.kiss-yt-media {
	position: relative;
	display: block;
	width: 100%;
	aspect-ratio: var(--kiss-yt-item-ratio, var(--kiss-yt-ratio));
	overflow: hidden;
	border-radius: var(--kiss-yt-radius);
	background: var(--kiss-yt-surface);
}

@supports not (aspect-ratio: 16 / 9) {
	.kiss-yt-media {
		height: 0;
		padding-bottom: calc(100% / (var(--kiss-yt-item-ratio, var(--kiss-yt-ratio))));
	}
}

.kiss-yt-poster,
.kiss-yt-player {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	border: 0;
}

.kiss-yt-poster {
	display: var(--kiss-yt-facade-display, block);
	object-fit: cover;
	object-position: center;
}

/* While a player is in the box the poster, play button and badge are removed from
   layout, not merely painted under the iframe — a theme or Kit rule on `iframe` or
   `img` (position, z-index, max-width) must never leave a visitor hearing a video
   behind its own thumbnail. Scoped at (0,2,1) so the iframe's geometry beats any
   single-class theme rule as well. */
.kiss-yt-media--playing {
	--kiss-yt-facade-display: none;
}

.kiss-youtube iframe.kiss-yt-player {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	margin: 0;
	padding: 0;
	border: 0;
}

/* Facade button. Fills the media box; the disc is drawn by the span inside.
 *
 * Scoped to the widget so it is (0,2,1): a bare `.kiss-yt-play` is (0,1,0) and loses to
 * a Kit's `.elementor-kit-N button { padding … border-radius … background … }`, which
 * would turn the poster into a giant pill. Keep the reset list exhaustive — anything
 * omitted leaks in. Everything visual lives on `.kiss-yt-play-disc`, driven by tokens. */
.kiss-youtube button.kiss-yt-play {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: grid;
	place-items: center;
	width: 100%;
	height: 100%;
	min-width: 0;
	min-height: 0;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	appearance: none;
	-webkit-appearance: none;
	background: none;
	box-shadow: none;
	color: inherit;
	font: inherit;
	line-height: inherit;
	text-align: inherit;
	cursor: pointer;
}

.kiss-youtube button.kiss-yt-play[hidden] {
	display: none;
}

/* The disc: an accent-filled circle with the triangle knocked out (fill-rule evenodd
   in the mask) so the poster shows through. Set --kiss-yt-play-icon to a colour to
   paint the triangle instead. */
.kiss-yt-play-disc {
	position: relative;
	display: block;
	width: var(--kiss-yt-play-size-local, var(--kiss-yt-play-size));
	aspect-ratio: 1 / 1;
	transition: transform 0.2s ease;
}

.kiss-yt-play-disc::before {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--kiss-yt-play-fill);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath fill-rule='evenodd' d='M50 0a50 50 0 1 0 0 100A50 50 0 1 0 50 0zM40 29l34 21-34 21z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath fill-rule='evenodd' d='M50 0a50 50 0 1 0 0 100A50 50 0 1 0 50 0zM40 29l34 21-34 21z'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
	transition: background-color 0.2s ease;
}

.kiss-yt-play-disc::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--kiss-yt-play-icon);
	clip-path: polygon(40% 29%, 74% 50%, 40% 71%);
}

.kiss-yt-play:hover .kiss-yt-play-disc,
.kiss-yt-play:focus-visible .kiss-yt-play-disc {
	--kiss-yt-play-fill: var(--kiss-yt-play-hover);
	transform: scale(var(--kiss-yt-play-hover-scale));
}

.kiss-yt-duration {
	display: var(--kiss-yt-facade-display, block);
	position: absolute;
	right: 8px;
	bottom: 8px;
	z-index: 1;
	padding: 2px 6px;
	border-radius: 3px;
	background: var(--kiss-yt-badge-bg);
	color: var(--kiss-yt-badge-color);
	font-size: var(--kiss-yt-badge-size, 0.75em);
	line-height: 1.4;
	pointer-events: none;
}

/* --------------------------------------------------------------------------
   Text — inherits everything. Only spacing, clamping and the token colour.
   -------------------------------------------------------------------------- */

.kiss-yt-body {
	display: flex;
	flex-direction: column;
	gap: var(--kiss-yt-text-gap);
	margin-top: var(--kiss-yt-body-gap-local, var(--kiss-yt-body-gap));
	min-width: 0;
}

.kiss-yt-title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--kiss-yt-title-lines);
	overflow: hidden;
	overflow-wrap: break-word;
	margin: 0;
	padding: 0;
	color: var(--kiss-yt-title-color);
}

/* Up-next titles read the row size token. On an Elementor site the Kit's own heading
   rule (0,1,1) outranks this; re-point it from a two-class rule or the Style tab. */
.kiss-yt-title--row {
	font-size: var(--kiss-yt-row-title-size);
}

.kiss-yt-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25em var(--kiss-yt-meta-gap);
	align-items: baseline;
	margin: 0;
	padding: 0;
	color: var(--kiss-yt-meta-color);
	opacity: var(--kiss-yt-meta-opacity);
	font-size: var(--kiss-yt-meta-size);
}

.kiss-yt-link {
	color: inherit;
}

/* The description and its two affordances. The wrap takes the show/hide token (rows
   hide it); the text is line-clamped by default. The script switches the wrap to
   --open (Read more) or --scroll, only when the text really overflows. */
.kiss-yt-desc-wrap {
	display: var(--kiss-yt-desc-display, block);
	position: relative;
	margin: 0;
	scroll-margin-top: var(--kiss-yt-scroll-margin);
}

.kiss-yt-desc {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: var(--kiss-yt-desc-lines);
	overflow: hidden;
	margin: 0;
}

.kiss-yt-desc-wrap--open .kiss-yt-desc {
	display: block;
	-webkit-line-clamp: none;
}

/* Scroll mode: a box lines × line-height tall (measured by the script), the list's
   fade and scrollbar, and the hint in its own band beneath so it never sits on text.
   The band stays reserved at the end of the text, so nothing below ever moves. */
.kiss-yt-desc-wrap--scroll {
	padding-bottom: var(--kiss-yt-hint-band);
	--kiss-yt-desc-fade: var(--kiss-yt-hint-fade);
}

.kiss-yt-desc-wrap--scroll .kiss-yt-desc {
	display: block;
	-webkit-line-clamp: none;
	max-height: var(--kiss-yt-desc-max-h);
	overflow-y: auto;
	overflow-x: hidden;
	overscroll-behavior: contain;
	scrollbar-gutter: stable;
	-webkit-mask-image: linear-gradient(to bottom, currentColor calc(100% - var(--kiss-yt-desc-fade, 0px)), transparent 100%);
	mask-image: linear-gradient(to bottom, currentColor calc(100% - var(--kiss-yt-desc-fade, 0px)), transparent 100%);
}

.kiss-yt-desc--end {
	--kiss-yt-desc-fade: 0px;
}

/* Read more. A <button>, so the same exhaustive reset as the hint; static, beneath
   the text, sharing the hint's tokens so the two read as one control. */
.kiss-youtube button.kiss-yt-desc-more {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	width: auto;
	min-width: 0;
	min-height: 0;
	height: auto;
	margin: 0.5em 0 0;
	padding: var(--kiss-yt-hint-pad);
	border: 0;
	border-radius: 0;
	appearance: none;
	-webkit-appearance: none;
	background: var(--kiss-yt-hint-bg);
	box-shadow: none;
	color: var(--kiss-yt-hint-color);
	font: inherit;
	font-size: var(--kiss-yt-hint-size);
	line-height: 1.2;
	text-align: left;
	cursor: pointer;
}

.kiss-youtube button.kiss-yt-desc-more[hidden] {
	display: none;
}

.kiss-yt-desc-more .kiss-yt-hint-chevron,
.kiss-yt-more--text .kiss-yt-hint-chevron {
	animation: none;
	transition: transform 0.2s ease;
}

.kiss-yt-desc-wrap--open .kiss-yt-desc-more .kiss-yt-hint-chevron {
	transform: rotate(225deg) translate(-15%, -15%);
}

.kiss-yt-desc-more:focus-visible {
	outline: var(--kiss-yt-focus-w) solid var(--kiss-yt-focus);
	outline-offset: 2px;
}

.kiss-yt-desc > p {
	margin: 0 0 0.5em;
}

.kiss-yt-label {
	margin: 0 0 var(--kiss-yt-label-gap);
	padding: 0;
	color: var(--kiss-yt-meta-color);
}

/* On desktop the label hangs above the list so the first row sits level with the
   player top, as in the design; --kiss-yt-label-space reserves room for it above
   the stage (set it to 0 where the section's own spacing already leaves room). */
.kiss-youtube--showcase {
	--kiss-yt-label-position: absolute;
	--kiss-yt-stage-pt: var(--kiss-yt-label-space);
}

.kiss-yt-label {
	position: var(--kiss-yt-label-position, static);
	bottom: 100%;
	left: 0;
	right: 0;
}

/* --------------------------------------------------------------------------
   Showcase — featured player + up-next list. 62.2% / 20px / 36.5% at 1448 wide.
   -------------------------------------------------------------------------- */

.kiss-yt-stage {
	display: grid;
	grid-template-columns: minmax(0, var(--kiss-yt-split)) minmax(0, 1fr);
	gap: var(--kiss-yt-gap);
	align-items: start;
	padding-top: var(--kiss-yt-stage-pt, 0px);
}

.kiss-yt-featured {
	min-width: 0;
	scroll-margin-top: var(--kiss-yt-scroll-margin);
}

/* The aside stretches to the featured column's height and contributes none of its
   own: the list is absolutely positioned inside a flexible wrapper, so the two
   columns stay level and the list scrolls within that height. */
.kiss-yt-aside {
	position: relative;
	display: flex;
	flex-direction: column;
	align-self: stretch;
	min-width: 0;
	min-height: 0;
}

/* The wrap carries the height cap, so the list (inset 0), the fade and the hint all
   share one bottom edge. */
.kiss-yt-list-wrap {
	position: relative;
	flex: 1 1 auto;
	min-height: 0;
	max-height: var(--kiss-yt-list-max-h);
}

/* The list stops above the hint's band, so the hint never sits on a row. */
.kiss-yt-list {
	position: absolute;
	inset: 0;
	bottom: var(--kiss-yt-hint-band-local, 0px);
	overflow-y: auto;
	overflow-x: hidden;
	overscroll-behavior: contain;
	scrollbar-gutter: stable;
	-webkit-mask-image: linear-gradient(to bottom, currentColor calc(100% - var(--kiss-yt-list-fade)), transparent 100%);
	mask-image: linear-gradient(to bottom, currentColor calc(100% - var(--kiss-yt-list-fade)), transparent 100%);
}

/* No more to scroll — nothing to hint at. */
.kiss-yt-list--end {
	--kiss-yt-list-fade: 0px;
}

/* A visible-rows cap (data-kiss-yt-rows) is measured by the script from the real row
   pitch and handed back as a token on the list; with no script, the list stays level
   with the player. */
.kiss-youtube--rows .kiss-yt-list-wrap {
	max-height: var(--kiss-yt-rows-max-h, var(--kiss-yt-list-max-h));
}

/* With the hint on, the rows fade out beneath it by default so the text sits on the
   section background. Same weight as the root rule and later, so it wins the default;
   a site's two-class rule still beats both. */
.kiss-youtube--hint {
	--kiss-yt-list-fade: var(--kiss-yt-hint-fade);
	--kiss-yt-hint-band-local: var(--kiss-yt-hint-band);
}

/* The hint. A <button>, so it gets the same exhaustive reset as the play button; the
   text and the chevron inherit the theme. */
.kiss-youtube button.kiss-yt-hint {
	position: absolute;
	left: 0;
	right: var(--kiss-yt-scrollbar-w);
	bottom: 0;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	width: auto;
	min-width: 0;
	min-height: 0;
	height: var(--kiss-yt-hint-band);
	margin: 0;
	padding: var(--kiss-yt-hint-pad);
	border: 0;
	border-radius: 0;
	appearance: none;
	-webkit-appearance: none;
	background: var(--kiss-yt-hint-bg);
	box-shadow: none;
	color: var(--kiss-yt-hint-color);
	font: inherit;
	font-size: var(--kiss-yt-hint-size);
	line-height: 1.2;
	text-align: center;
	cursor: pointer;
}

.kiss-youtube button.kiss-yt-hint[hidden] {
	display: none;
}

.kiss-yt-hint-chevron {
	display: block;
	width: 0.55em;
	height: 0.55em;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg) translate(-15%, -15%);
	animation: kiss-yt-nudge 1.8s ease-in-out infinite;
}

@keyframes kiss-yt-nudge {
	0%, 100% { transform: rotate(45deg) translate(-15%, -15%); }
	50% { transform: rotate(45deg) translate(5%, 5%); }
}

.kiss-yt-hint:focus-visible {
	outline: var(--kiss-yt-focus-w) solid var(--kiss-yt-focus);
	outline-offset: 2px;
}

/* Scrollbar: visible and themeable, never hidden. WebKit engines take the pseudo-
   element rules; Firefox (which has no ::-webkit-scrollbar) takes the standard
   properties. Setting scrollbar-color in Chrome would switch its pseudo-element
   styling off, which is why the standard properties are fenced. */
.kiss-yt-list::-webkit-scrollbar,
.kiss-yt-desc-wrap--scroll .kiss-yt-desc::-webkit-scrollbar {
	width: var(--kiss-yt-scrollbar-w);
}

.kiss-yt-list::-webkit-scrollbar-track,
.kiss-yt-desc-wrap--scroll .kiss-yt-desc::-webkit-scrollbar-track {
	background: var(--kiss-yt-scrollbar-track);
	border-radius: var(--kiss-yt-scrollbar-radius);
}

.kiss-yt-list::-webkit-scrollbar-thumb,
.kiss-yt-desc-wrap--scroll .kiss-yt-desc::-webkit-scrollbar-thumb {
	background: var(--kiss-yt-scrollbar-thumb);
	border-radius: var(--kiss-yt-scrollbar-radius);
}

@supports not selector(::-webkit-scrollbar) {
	.kiss-yt-list,
	.kiss-yt-desc-wrap--scroll .kiss-yt-desc {
		scrollbar-width: var(--kiss-yt-scrollbar-width, thin);
		scrollbar-color: var(--kiss-yt-scrollbar-thumb) var(--kiss-yt-scrollbar-track);
	}
}

/* Below 1025 the showcase stacks: player full width, then ordinary full-width rows.
   A scroll container inside a scrolling page is miserable on a phone. */
@media (max-width: 1024px) {
	.kiss-youtube--showcase {
		--kiss-yt-label-position: static;
		--kiss-yt-stage-pt: 0px;
	}

	.kiss-yt-stage {
		grid-template-columns: minmax(0, 1fr);
	}

	.kiss-yt-aside {
		display: block;
		position: static;
	}

	.kiss-yt-list-wrap {
		position: static;
		max-height: none;
	}

	.kiss-yt-list {
		position: static;
		max-height: none;
		overflow: visible;
		-webkit-mask-image: none;
		mask-image: none;
	}

	/* The list no longer scrolls when stacked, so its hint goes; the description's
	   own hint (scroll mode chosen for touch) stays. */
	.kiss-youtube .kiss-yt-list-wrap button.kiss-yt-hint {
		display: none;
	}
}

/* --------------------------------------------------------------------------
   Shorts row beneath a long-form section (same root, same filter bar)
   -------------------------------------------------------------------------- */

.kiss-yt-shorts {
	margin: var(--kiss-yt-shorts-mt, calc(var(--kiss-yt-gap) * 2)) 0 0;
	padding: 0;
}

.kiss-yt-heading {
	margin: 0 0 var(--kiss-yt-heading-mb, var(--kiss-yt-gap));
	padding: 0;
	color: var(--kiss-yt-title-color);
}

/* <em> in a heading takes the accent, for a two-tone headline. */
.kiss-yt-heading em {
	color: var(--kiss-yt-accent);
}

/* Filter switch: the Videos / Shorts chips swap which view shows, in place. */
.kiss-youtube[data-kiss-yt-view="long"] .kiss-yt-view--shorts,
.kiss-youtube[data-kiss-yt-view="shorts"] .kiss-yt-view--long {
	display: none;
}

.kiss-youtube--switch .kiss-yt-shorts {
	margin-top: 0; /* the chip is the label; the view sits where the showcase did */
}

/* A little air between the view chips and the tag chips. */
.kiss-yt-filter--type + .kiss-yt-filter:not(.kiss-yt-filter--type) {
	margin-left: var(--kiss-yt-filter-group-gap, 1em);
}

/* --------------------------------------------------------------------------
   Touch gestures (opt-in). Fenced to touch devices: the desktop keeps its grids
   and paging. Card rows become native horizontal snap scrollers — the browser
   decides in the first pixels whether a finger means the page or the row, so
   vertical scrolling is never caught — and every card is in the row, so Load
   more paging is moot. The featured video's swipe lives in the script; here it
   only declares that vertical pans are the browser's and horizontal ours.
   -------------------------------------------------------------------------- */

@media (hover: none) and (pointer: coarse) {
	.kiss-youtube--touch .kiss-yt-grid {
		display: flex;
		flex-wrap: nowrap;
		gap: var(--kiss-yt-gap);
		overflow-x: auto;
		overflow-y: hidden;
		overscroll-behavior-x: contain;
		scroll-snap-type: x mandatory;
		scroll-padding-inline: 0;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	.kiss-youtube--touch .kiss-yt-grid::-webkit-scrollbar {
		display: none;
	}

	/* As many cards across as the columns setting says, minus a peek of the next. */
	.kiss-youtube--touch .kiss-yt-grid > .kiss-yt-item {
		flex: 0 0 calc((100% - var(--kiss-yt-touch-peek) - (var(--kiss-yt-cols) - 1) * var(--kiss-yt-gap)) / var(--kiss-yt-cols));
		scroll-snap-align: start;
	}

	/* Paging hides nothing in a scroller; a filtered card stays hidden. */
	.kiss-youtube--touch .kiss-yt-grid > .kiss-yt-item[hidden]:not(.kiss-yt-item--filtered) {
		display: block;
	}

	.kiss-youtube--touch .kiss-yt-grid ~ .kiss-yt-more-wrap,
	.kiss-youtube--touch .kiss-yt-shorts .kiss-yt-more-wrap {
		display: none;
	}

	/* The text under the featured video: a sideways swipe there steps the poster
	   scroller (the poster itself may be under a live player); vertical stays native. */
	.kiss-youtube--touch .kiss-yt-item--featured .kiss-yt-body {
		touch-action: pan-y;
	}
}

/* The featured poster scroller (built by the script, touch devices only): every
   poster in the widget, one per screen, snapping — the same native mechanism as
   the card rows, so only the poster moves and the browser owns the gesture. It
   sits over the play button (same z, later in the DOM — a touch on the poster
   has to land inside the scroller, and the button is not inside it; each slide
   carries its own disc and a tap presses the button) and under the duration
   badge and any player (z 2). */
.kiss-youtube--touch .kiss-yt-track {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: flex;
	flex-wrap: nowrap;
	overflow-x: auto;
	overflow-y: hidden;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	background: var(--kiss-yt-surface);
}

.kiss-youtube--touch .kiss-yt-track::-webkit-scrollbar {
	display: none;
}

.kiss-youtube--touch .kiss-yt-slide {
	position: relative;
	display: grid;
	place-items: center;
	flex: 0 0 100%;
	scroll-snap-align: start;
	scroll-snap-stop: always; /* one video per flick */
}

.kiss-youtube--touch .kiss-yt-slide-disc {
	position: relative;
	z-index: 1;
	display: var(--kiss-yt-facade-display, block);
}

/* The Shorts hand-over slide's label: an overlay on a photo, on the badge's contrast pair. */
.kiss-youtube--touch .kiss-yt-slide-cap {
	position: absolute;
	left: 50%;
	bottom: 12%;
	z-index: 1;
	transform: translateX(-50%);
	padding: 0.35em 1em;
	border-radius: 999px;
	background: var(--kiss-yt-badge-bg);
	color: var(--kiss-yt-badge-color);
	font-size: var(--kiss-yt-badge-size, 0.875em);
	line-height: 1.4;
	white-space: nowrap;
}

.kiss-youtube--touch .kiss-yt-slide[hidden] {
	display: none;
}

.kiss-youtube--touch .kiss-yt-slide-img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	border: 0;
	object-fit: cover;
	object-position: center;
}

/* --------------------------------------------------------------------------
   Shorts lightbox — the whole screen for a portrait player (built by the script)
   -------------------------------------------------------------------------- */

/* The lightbox is appended to <body>, outside any .kiss-youtube root, so its tokens
   live here. An overlay on a dark scrim, so — like the duration badge — its own
   contrast pair rather than the theme's text colour. Theme it with a site rule on
   .kiss-yt-lightbox. */
.kiss-yt-lightbox {
	--kiss-yt-lightbox-bg: rgba(0, 0, 0, 0.94);
	--kiss-yt-lightbox-color: #ffffff;
	--kiss-yt-lightbox-pad: 16px;
	--kiss-yt-lightbox-z: 99999;
	--kiss-yt-lightbox-title-size: 0.875em;
	position: fixed;
	inset: 0;
	z-index: var(--kiss-yt-lightbox-z);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--kiss-yt-lightbox-pad);
	background: var(--kiss-yt-lightbox-bg);
	color: var(--kiss-yt-lightbox-color);
}

.kiss-yt-lightbox[hidden] {
	display: none;
}

html.kiss-yt-lightbox-open {
	overflow: hidden;
}

.kiss-yt-lightbox-panel {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	max-width: 100%;
	max-height: 100%;
}

/* A 9:16 stage as tall as the viewport allows, never wider than it. */
.kiss-yt-lightbox-stage {
	aspect-ratio: 9 / 16;
	height: min(calc(100vh - var(--kiss-yt-lightbox-pad) * 2 - 96px), calc((100vw - var(--kiss-yt-lightbox-pad) * 2) * 16 / 9));
	height: min(calc(100dvh - var(--kiss-yt-lightbox-pad) * 2 - 96px), calc((100vw - var(--kiss-yt-lightbox-pad) * 2) * 16 / 9));
	background: #000;
}

.kiss-yt-lightbox-stage iframe {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

.kiss-yt-lightbox-title {
	margin: 0;
	max-width: 100%;
	text-align: center;
	font-size: var(--kiss-yt-lightbox-title-size);
	opacity: 0.85;
}

.kiss-yt-lightbox-nav {
	display: flex;
	gap: 24px;
}

/* The three buttons: the play button's reset, a 44px target, currentColor. */
.kiss-yt-lightbox button.kiss-yt-lightbox-close,
.kiss-yt-lightbox button.kiss-yt-lightbox-prev,
.kiss-yt-lightbox button.kiss-yt-lightbox-next {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	min-width: 0;
	min-height: 0;
	margin: 0;
	padding: 0;
	border: 1px solid currentColor;
	border-radius: 50%;
	appearance: none;
	-webkit-appearance: none;
	background: transparent;
	box-shadow: none;
	color: inherit;
	font: inherit;
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
}

.kiss-yt-lightbox button.kiss-yt-lightbox-close {
	position: absolute;
	top: 0;
	right: 0;
	transform: translate(25%, -25%);
	z-index: 1;
}

.kiss-yt-lightbox button[disabled] {
	opacity: 0.35;
	cursor: default;
}

.kiss-yt-lightbox .kiss-yt-hint-chevron {
	animation: none;
	transform: rotate(-45deg) translate(15%, -15%);
}

.kiss-yt-lightbox button.kiss-yt-lightbox-prev .kiss-yt-hint-chevron {
	transform: rotate(135deg) translate(-15%, 15%);
}

.kiss-yt-lightbox button:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   Filter bar — All + one chip per configured tag that some video carries
   -------------------------------------------------------------------------- */

.kiss-yt-filters {
	display: flex;
	flex-wrap: wrap;
	justify-content: var(--kiss-yt-filter-justify);
	gap: var(--kiss-yt-filter-gap-y) var(--kiss-yt-filter-gap-x);
	margin: 0 0 var(--kiss-yt-filter-mb);
	padding: 0;
}

.kiss-yt-filters--chips {
	--kiss-yt-filter-gap-x: 0.5em;
}

/* Text tabs and chips are <button>s with the play button's exhaustive reset. The
   "buttons" variant is deliberately absent here: it wears the Load more classes and
   the theme / Kit draws it. */
.kiss-youtube button.kiss-yt-filter--tab,
.kiss-youtube button.kiss-yt-filter--chip {
	position: relative;
	display: inline-block;
	width: auto;
	min-width: 0;
	min-height: 0;
	height: auto;
	margin: 0;
	padding: 4px 0;
	border: 0;
	border-radius: 0;
	appearance: none;
	-webkit-appearance: none;
	background: none;
	box-shadow: none;
	color: var(--kiss-yt-filter-color);
	opacity: var(--kiss-yt-filter-idle-opacity);
	font: inherit;
	font-size: var(--kiss-yt-filter-size);
	line-height: 1.2;
	text-align: center;
	cursor: pointer;
	transition: opacity 0.2s ease, color 0.2s ease;
}

.kiss-youtube button.kiss-yt-filter--tab:hover,
.kiss-youtube button.kiss-yt-filter--chip:hover {
	opacity: 0.9;
}

.kiss-youtube button.kiss-yt-filter--active {
	color: var(--kiss-yt-filter-active-color);
	opacity: 1;
}

/* A chip the script hides (nothing in the active view carries its tag) must beat the
   reset's display, as every [hidden] rule here does. */
.kiss-youtube button.kiss-yt-filter[hidden] {
	display: none;
}

/* Text tabs: a rule grows in under the active one. */
.kiss-yt-filter--tab::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: var(--kiss-yt-filter-rule-offset);
	height: var(--kiss-yt-filter-rule-h);
	background: var(--kiss-yt-filter-rule-color);
	transform: scaleX(var(--kiss-yt-filter-rule-scale, 0));
	transform-origin: left center;
	transition: transform 0.25s ease;
}

.kiss-yt-filter--tab.kiss-yt-filter--active {
	--kiss-yt-filter-rule-scale: 1;
}

/* Chips: outlined pills. */
.kiss-youtube button.kiss-yt-filter--chip {
	padding: var(--kiss-yt-filter-pad);
	border: 1px solid var(--kiss-yt-filter-border);
	border-radius: var(--kiss-yt-filter-radius);
	background: var(--kiss-yt-filter-bg);
}

.kiss-youtube button.kiss-yt-filter--chip.kiss-yt-filter--active {
	background: var(--kiss-yt-filter-active-bg);
	border-color: var(--kiss-yt-filter-active-border);
}

/* Theme buttons: the inactive ones step back. */
.kiss-yt-filter--btn[aria-pressed="false"] {
	opacity: var(--kiss-yt-filter-idle-opacity);
}

.kiss-yt-filter:focus-visible {
	outline: var(--kiss-yt-focus-w) solid var(--kiss-yt-focus);
	outline-offset: 2px;
}

/* Filtered out by the bar (separate from load-more's hidden attribute). */
.kiss-yt-item--filtered {
	display: none;
}

/* A chip that leaves nothing up next takes the label with it. */
.kiss-youtube--no-rows .kiss-yt-label {
	display: none;
}

/* --------------------------------------------------------------------------
   Grid + masonry
   -------------------------------------------------------------------------- */

.kiss-yt-grid {
	display: grid;
	grid-template-columns: var(--kiss-yt-grid-template, repeat(var(--kiss-yt-cols), minmax(0, 1fr)));
	gap: var(--kiss-yt-gap);
}

/* "Auto" columns: as many as fit at the minimum width. */
.kiss-youtube--cols-auto {
	--kiss-yt-grid-template: repeat(auto-fit, minmax(var(--kiss-yt-col-min), 1fr));
}

/* CSS columns, no JS. Orders top-to-bottom within a column; if order matters more
   than packing, use the grid. */
.kiss-yt-masonry {
	columns: var(--kiss-yt-cols);
	column-gap: var(--kiss-yt-gap);
}

.kiss-youtube--masonry {
	--kiss-yt-card-mb: var(--kiss-yt-gap);
}

/* Shorts shelf: portrait cards, so a smaller play disc, two-line titles and no
   description (a Short's is usually hashtags). Tokens only; a site rule can restore
   any of them, e.g. .kiss-youtube--shelf { --kiss-yt-desc-display: block }. */
.kiss-youtube--shelf {
	--kiss-yt-play-size-card: var(--kiss-yt-play-size-shelf, 48px);
	--kiss-yt-title-lines: var(--kiss-yt-shelf-title-lines, 2);
	--kiss-yt-desc-display: none;
	--kiss-yt-col-min: var(--kiss-yt-shelf-col-min, 160px);
}

.kiss-yt-more-wrap {
	margin: var(--kiss-yt-gap) 0 0;
	padding: 0;
	text-align: var(--kiss-yt-more-align, center);
}

.kiss-yt-more-wrap[hidden] {
	display: none;
}

/* Load more as a text link: the play button's reset, the scroll hint's tokens, so
   the hint, Read more, text filter tabs and this read as one family. */
.kiss-youtube button.kiss-yt-more--text {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	width: auto;
	min-width: 0;
	min-height: 0;
	height: auto;
	margin: 0;
	padding: var(--kiss-yt-hint-pad);
	border: 0;
	border-radius: 0;
	appearance: none;
	-webkit-appearance: none;
	background: var(--kiss-yt-hint-bg);
	box-shadow: none;
	color: var(--kiss-yt-hint-color);
	font: inherit;
	font-size: var(--kiss-yt-hint-size);
	line-height: 1.2;
	text-align: center;
	cursor: pointer;
}

/* --------------------------------------------------------------------------
   Buttons — "Plugin" button style. Kit style adds Elementor's own classes and
   takes no CSS from here; Unstyled takes none at all.
   -------------------------------------------------------------------------- */

.kiss-youtube a.kiss-yt-button,
.kiss-youtube button.kiss-yt-button {
	display: inline-block;
	margin: 0;
	padding: var(--kiss-yt-btn-pad, 0.6em 1.2em);
	border: var(--kiss-yt-btn-border, 1px solid currentColor);
	border-radius: var(--kiss-yt-btn-radius, 4px);
	appearance: none;
	-webkit-appearance: none;
	background: var(--kiss-yt-btn-bg, transparent);
	box-shadow: none;
	color: var(--kiss-yt-btn-color, inherit);
	font: inherit;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
}

/* --------------------------------------------------------------------------
   States
   -------------------------------------------------------------------------- */

.kiss-yt-play:focus-visible,
.kiss-yt-list:focus-visible,
.kiss-yt-more:focus-visible,
.kiss-yt-link:focus-visible {
	outline: var(--kiss-yt-focus-w) solid var(--kiss-yt-focus);
	outline-offset: 2px;
}

.kiss-yt-play:focus-visible {
	outline-offset: calc(-1 * var(--kiss-yt-focus-w));
}

/* Visible only inside the Elementor editor, when there is nothing to show yet. */
.kiss-yt-empty {
	padding: 40px;
	border: 1px dashed currentColor;
	border-radius: 10px;
	opacity: 0.7;
	text-align: center;
}

@media (prefers-reduced-motion: reduce) {
	.kiss-yt-play-disc,
	.kiss-yt-play-disc::before,
	.kiss-yt-filter--tab,
	.kiss-yt-filter--tab::after,
	.kiss-yt-filter--chip {
		transition: none;
	}

	.kiss-yt-play:hover .kiss-yt-play-disc,
	.kiss-yt-play:focus-visible .kiss-yt-play-disc {
		transform: none;
	}

	.kiss-yt-list {
		scroll-behavior: auto;
	}

	.kiss-yt-hint-chevron {
		animation: none;
	}
}
