/* ==========================================================================
   Meme Theme 灯箱（Lightbox）
   结构：template-parts/lightbox.php（原生 <dialog>，全站只有一份，由 footer.php 输出）
   色板：global.css 的 --meme-lb-* 变量（深色浮层专用）
   本文件只管布局与视觉，不含开合、焦点、历史等行为逻辑。

   1. 容器与遮罩
   2. 关闭按钮
   3. 主图舞台
   4. 底部控制栏
   5. 关联图格子
   6. 操作按钮
   7. 信息面板
   8. 断点与偏好设置
   ========================================================================== */

/* 1. 容器与遮罩 */

/*
 * display 只在 [open] 时接管：
 * 无条件写 display: flex 会把 UA 的 dialog:not([open]) { display: none } 一起盖掉，
 * 灯箱会一直显示在页面上。这是 <dialog> 最常见的坑，不要合并这两条规则。
 */
.meme-lightbox {
	position: fixed;
	inset: 0;
	width: 100vw;
	height: 100vh;
	max-width: none;   /* Chrome UA 给 dialog 设了 max-width，不覆盖会留白边 */
	max-height: none;
	margin: 0;
	padding: 0;
	border: 0;
	background: var(--meme-lb-bg);
	color: var(--meme-lb-text);
	overflow: hidden;
}

.meme-lightbox[open] {
	display: flex;
	flex-direction: column;
}

.meme-lightbox::backdrop {
	background: var(--meme-lb-bg);
}

/*
 * 灯箱打开时锁住页面滚动（遮罩挡住了点击，但滚轮仍能滚到底下的瀑布流）。
 * 用 :has() 挂在页面根上，不需要 JS 额外维护 body 类名。
 */
body:has(> .meme-lightbox[open]) {
	overflow: hidden;
}

/* 2. 关闭按钮 */

.lightbox-close {
	position: absolute;
	top: 14px;
	right: 18px;
	z-index: 3;
	width: 40px;
	height: 40px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	/* 圆形图标按钮：50% 是刻意做的正圆，不是「散值圆角」，不受 6px 规范约束 */
	border-radius: 50%;
	background: transparent;
	color: var(--meme-lb-text);
	cursor: pointer;
	transition: background-color 0.15s ease, opacity 0.15s ease;
}

.lightbox-close:hover {
	background: var(--meme-lb-surface);
}

.lightbox-close svg {
	display: block;
}

/* 3. 主图舞台 */

.lightbox-stage {
	flex: 1 1 auto;
	min-height: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	/* 上方让出关闭按钮，左右预留给将来的上一张 / 下一张箭头 */
	padding: 64px 72px 24px;
	overflow: hidden;
}

.lightbox-main {
	display: block;
	max-width: 90vw;
	max-height: 80vh;
	width: auto;
	height: auto;
	object-fit: contain;
	border-radius: var(--meme-border-radius);
}

/* 4. 底部控制栏 */

.lightbox-toolbar {
	position: relative; /* 信息面板的定位基准 */
	flex: 0 0 auto;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--meme-gap);
	/*
	 * 不换行：关联图一多，换行会把「信息 / 下载」两个按钮挤到第二行，
	 * 按钮位置随图数量漂移，手指每次都要重新找。
	 * 正确的压缩方式是让 .lightbox-related 收缩 + 横向滚动（见下一条）。
	 */
	min-height: 64px;
	padding: 12px 16px;
	background: var(--meme-lb-surface);
	border-top: 1px solid var(--meme-lb-border);
}

/* 5. 关联图格子 */

.lightbox-related {
	display: flex;
	align-items: center;
	gap: 8px;
	flex: 1 1 auto;
	min-width: 0;
	overflow-x: auto;
	overflow-y: hidden;
	padding: 2px; /* 给选中态的边框留出空间，避免被 overflow 裁掉 */
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.lightbox-related::-webkit-scrollbar {
	display: none;
}

/*
 * 格子由 JS 注入，元素可以是 <button> 或 <a>，统一用这个类名。
 * 用固定宽高 + object-fit: cover，保证不同比例的缩略图格子大小一致。
 */
.lightbox-related-item {
	flex: 0 0 auto;
	width: 60px;
	height: 60px;
	display: block;
	padding: 0;
	border: 2px solid transparent;
	border-radius: var(--meme-border-radius);
	background: var(--meme-lb-bg);
	overflow: hidden;
	cursor: pointer;
	opacity: 0.6;
	transition: opacity 0.15s ease, border-color 0.15s ease;
}

.lightbox-related-item img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.lightbox-related-item:hover,
.lightbox-related-item:focus-visible {
	opacity: 1;
}

/* 选中态：白色描边。aria-current 与 .is-active 两种写法都认，JS 用哪个都行 */
.lightbox-related-item.is-active,
.lightbox-related-item[aria-current="true"] {
	opacity: 1;
	border-color: var(--meme-lb-text);
}

/* 6. 操作按钮 */

.lightbox-actions {
	display: flex;
	align-items: center;
	gap: 10px;
	flex: 0 0 auto;
	margin-left: auto;
}

.lightbox-info-btn,
.lightbox-download {
	width: 40px;
	height: 40px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	/* 圆形图标按钮：与关闭按钮一样是刻意做正圆 */
	border-radius: 50%;
	background: var(--meme-lb-btn);
	color: var(--meme-lb-text);
	cursor: pointer;
	text-decoration: none;
	transition: background-color 0.15s ease, transform 0.15s ease;
}

.lightbox-info-btn:hover,
.lightbox-download:hover {
	background: var(--meme-lb-btn-hover);
	color: var(--meme-lb-text);
}

.lightbox-info-btn:active,
.lightbox-download:active {
	transform: translateY(1px);
}

.lightbox-info-btn svg,
.lightbox-download svg {
	display: block;
}

/* 信息面板打开时按钮给个「已按下」的视觉 */
.lightbox-info-btn[aria-expanded="true"] {
	background: var(--meme-lb-btn-hover);
}

/* 7. 信息面板 */

/*
 * 贴在控制栏上方：控制栏是 position: relative，面板用 bottom: 100%，
 * 因此控制栏换行变高时面板自动跟随，不需要 JS 计算高度。
 * 关闭态 translateY(100%) 会滑到控制栏背后（控制栏 z-index 2 > 面板 1），视觉上收进底部。
 */
.lightbox-info-panel {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 100%;
	z-index: 1;
	max-height: 40vh;
	overflow-y: auto;
	padding: 16px 20px;
	background: var(--meme-lb-surface);
	border-top: 1px solid var(--meme-lb-border);
	transform: translateY(100%);
	opacity: 0;
	pointer-events: none;
	transition: transform 0.3s ease, opacity 0.3s ease;
}

.lightbox-info-panel.is-open {
	transform: translateY(0);
	opacity: 1;
	pointer-events: auto;
}

.lightbox-title {
	margin: 0 0 10px;
	font-size: 16px;
	font-weight: 600;
	line-height: 1.4;
	color: var(--meme-lb-text);
}

.lightbox-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 24px;
	margin: 0 0 10px;
}

.lightbox-meta-item {
	display: flex;
	align-items: baseline;
	gap: 8px;
}

.lightbox-meta-item dt {
	color: var(--meme-lb-text-muted);
	font-size: 13px;
}

.lightbox-meta-item dd {
	margin: 0;
	font-size: 13px;
}

.lightbox-source-row {
	display: flex;
	align-items: baseline;
	gap: 8px;
	margin: 0;
	font-size: 13px;
}

/* 没有来源时整行收起：空 <a> 没有文字，留着会显示一条无意义的下划线 */
.lightbox-source-row:has(.lightbox-source:empty) {
	display: none;
}

.lightbox-source-label {
	color: var(--meme-lb-text-muted);
}

.lightbox-source {
	color: var(--meme-lb-text);
	text-decoration: none;
	border-bottom: 1px solid var(--meme-lb-border);
	overflow-wrap: anywhere;
}

.lightbox-source:hover {
	color: var(--meme-lb-text);
	border-bottom-color: var(--meme-lb-text);
}

/* 8. 断点与偏好设置 */

@media (max-width: 768px) {
	.lightbox-close {
		top: 8px;
		right: 10px;
		width: 36px;
		height: 36px;
	}

	.lightbox-stage {
		padding: 52px 12px 12px;
	}

	.lightbox-main {
		max-width: 100%;
		max-height: 72vh;
	}

	.lightbox-toolbar {
		gap: 12px;
		padding: 10px 12px;
	}

	/* 手机端缩小关联图，一行能放更多格子；放不下时靠横向滚动，不换行 */
	.lightbox-related-item {
		width: 48px;
		height: 48px;
	}

	.lightbox-actions {
		gap: 8px;
	}

	.lightbox-info-btn,
	.lightbox-download {
		width: 36px;
		height: 36px;
	}

	.lightbox-info-btn svg,
	.lightbox-download svg {
		width: 18px;
		height: 18px;
	}

	.lightbox-info-panel {
		max-height: 50vh;
		padding: 14px 16px;
	}

	.lightbox-title {
		font-size: 15px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.lightbox-info-panel,
	.lightbox-related-item,
	.lightbox-close,
	.lightbox-info-btn,
	.lightbox-download {
		transition: none;
	}
}

/* 9. JS 用到的状态属性
   --------------------------------------------------------------------------
   .lightbox-related 与 .lightbox-source-row 都写了 display，会盖掉浏览器默认的
   [hidden] { display: none }，所以 JS 切换 hidden 时必须有一条规定兜底，
   否则「没有关联图 / 没有来源」时仍会留一块空白。
   -------------------------------------------------------------------------- */
.lightbox-related[hidden],
.lightbox-source-row[hidden],
.lightbox-download[hidden] {
	display: none;
}

/*
 * 下载按钮的「准备中」态。
 * 它是 40px 的纯图标圆钮，塞一行文字会把圆撑破，所以等待感用变暗 + 禁点表达，
 * 文字提示交给 JS 改写的 aria-label / title（读屏与鼠标悬停都能看到 "Preparing…"）。
 * 禁点也让连点无法重复发起请求，后端限流之外再加一道。
 */
.lightbox-download.is-busy {
	opacity: 0.55;
	pointer-events: none;
	cursor: default;
}

/* 格子由 JS 生成为 <button>，清掉原生按钮的字体与外观，只留图片本身 */
.lightbox-related-item {
	font: inherit;
	color: inherit;
	-webkit-appearance: none;
	appearance: none;
}

/*
 * dialog 只是焦点容器（JS 打开时把焦点放它身上，tabindex="-1"），本身不可交互，
 * 全屏描边反而像边框错位。内部按钮的焦点环不受影响。
 */
.meme-lightbox:focus-visible {
	outline: none;
}

/* ==========================================================================
   10. 画廊细节
   --------------------------------------------------------------------------
   10.1 控制栏高度恒定 + 缩略图居中      10.4 手机端横向滚动渐隐
   10.2 格子始终正方形                   10.5 打开动效
   10.3 桌面端上一张 / 下一张
   ========================================================================== */

/* 10.1 控制栏：高度恒定，缩略图居中 */

/*
 * 控制栏高度必须与「有没有关联图」无关。
 * 旧规则只给了 min-height: 64px：没有关联图时内容只有两个 40px 按钮，
 * 控制栏 65px；有图时被 60px 格子撑到 89px。同一次浏览里前后点开两张，
 * 主图区域就差 24px，画面会往上蹿一下。这里把下界钉在「有图」的高度：
 * 12(上下内边距) + 64(格子行 60 + 自身 2px 内边距) + 12 + 1(上边框)。
 */
.lightbox-toolbar {
	min-height: 89px;
}

@media (min-width: 769px) {
	/*
	 * 缩略图 + 按钮当成一个整体居中。
	 *
	 * 旧做法是「缩略图条相对整屏居中 + 按钮绝对定位贴右」，两者互不相干：
	 * 只有一张关联图时，一个 60px 的格子在屏幕正中，两个按钮孤零零地在最右边，
	 * 中间空出几百像素的荒地，看着像两块不同的东西。
	 *
	 * 现在回到正常文档流：工具栏自身 justify-content: center，
	 * 缩略图条按内容取宽（flex-basis: auto，不再 flex: 1 撑满整行），
	 * 按钮紧跟其后，整组一起落到屏幕中线。关联图越多，整组越宽，仍然居中。
	 */
	.lightbox-toolbar {
		justify-content: center;
		padding-left: 16px;
		padding-right: 16px;
	}

	/*
	 * flex: 0 1 auto 的三个值都不能省：
	 * - 0 不放大：只有一张图时缩略图条就是 60px 宽，不会撑满整行把按钮推回最右边；
	 * - 1 可收缩：十几张图时让给它的是「按钮组之外剩下的宽度」，超出部分自己横向滚；
	 * - auto 以内容宽度为基准，再配合 min-width: 0 才允许收缩到比内容更窄。
	 *
	 * safe 是关键字：内容溢出时退回左对齐。
	 * 只写 center 的话，超出部分会被挡在滚动区起点之外（左端永远滚不出来），
	 * 这是 flex + overflow 组合的经典坑。
	 */
	.lightbox-related {
		flex: 0 1 auto;
		justify-content: safe center;
	}

	/* 按钮回到文档流，紧跟缩略图条；margin-left: auto 是基础规则里的，这里要清掉 */
	.lightbox-actions {
		position: static;
		margin-left: 0;
		transform: none;
	}
}

/* 10.2 格子始终正方形 */

/*
 * 尺寸早已写死 60/48，但比例没锁：横图很宽、竖图很高时，flex 项的最小内容尺寸
 * 会被图片的固有比例牵着走，格子偶尔被撑成 60×52 这种长方形。
 * aspect-ratio 把比例钉死，overflow: hidden + object-fit: cover 负责裁掉溢出部分，
 * 于是「不管原图什么比例，格子边界都不动，画面填满不露底色」。
 */
.lightbox-related-item {
	aspect-ratio: 1 / 1;
	overflow: hidden;
}

.lightbox-related-item img {
	object-fit: cover;
	object-position: center;
}

/* 10.3 桌面端上一张 / 下一张 */

/* 舞台成为按钮的定位基准：按钮挂在舞台右侧中点，而不是整屏中点 */
.lightbox-stage {
	position: relative;
}

/*
 * 主图上限从 90vw 改成 100%：舞台左右本来就留了 72px，让箭头住在里面。
 * 90vw 在 769~1440px 之间是大于「舞台内容宽」的（例如 769px 下 90vw=692，
 * 而内容只有 625），图片会溢出内边距、正好压在两个箭头上。
 * 100% 的参照是舞台内容盒，天然不会越界，宽屏下图片仍按原尺寸显示。
 */
.lightbox-main {
	max-width: 100%;
}

.lightbox-nav {
	position: absolute;
	top: 50%;
	z-index: 3;
	width: 48px;
	height: 48px;
	/* 默认不显示：手机端靠横向滑动与方向键，屏幕上再压两个圆钮只会挡图 */
	display: none;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	/* 圆形图标按钮：与关闭按钮同一套做法，刻意做正圆 */
	border-radius: 50%;
	background: var(--meme-lb-btn);
	color: var(--meme-lb-text);
	cursor: pointer;
	transform: translateY(-50%);
	transition: background-color 0.18s ease, transform 0.18s ease;
}

.lightbox-prev {
	left: 16px;
}

.lightbox-next {
	right: 16px;
}

.lightbox-nav:hover {
	background: var(--meme-lb-btn-hover);
}

.lightbox-nav:active {
	transform: translateY(-50%) scale(0.94);
}

.lightbox-nav svg {
	display: block;
}

/*
 * 只有一张图时 JS 会加 hidden。
 * 属性选择器的权重（0,2,0）高于下面媒体查询里的 .lightbox-nav（0,1,0），
 * 所以桌面端的 display: inline-flex 盖不掉这条，顺序怎么排都安全。
 */
.lightbox-nav[hidden] {
	display: none;
}

@media (min-width: 769px) {
	.lightbox-nav {
		display: inline-flex;
	}
}

/* 10.4 手机端：横向滚动 + 末端渐隐 */

@media (max-width: 768px) {
	/* 手机端格子 48 + 上下 2px 内边距 = 52，控制栏 = 10 + 52 + 10 + 1 */
	.lightbox-toolbar {
		min-height: 73px;
	}

	.lightbox-related {
		--meme-lb-fade: 28px;
		scroll-behavior: smooth;
		/* 滑到头时别把横向手势交给浏览器的「返回上一页」 */
		overscroll-behavior-x: contain;
		/* 默认（中间位置）：两端都渐隐，提示「左右都还有」 */
		-webkit-mask-image: linear-gradient(
			to right,
			transparent 0,
			#000 var(--meme-lb-fade),
			#000 calc(100% - var(--meme-lb-fade)),
			transparent 100%
		);
		mask-image: linear-gradient(
			to right,
			transparent 0,
			#000 var(--meme-lb-fade),
			#000 calc(100% - var(--meme-lb-fade)),
			transparent 100%
		);
	}

	/* 已经顶到最左：左端不用再提示，只留右端那截渐隐 */
	.lightbox-related.is-at-start {
		-webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - var(--meme-lb-fade)), transparent 100%);
		mask-image: linear-gradient(to right, #000 0, #000 calc(100% - var(--meme-lb-fade)), transparent 100%);
	}

	/* 已经顶到最右：只留左端 */
	.lightbox-related.is-at-end {
		-webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--meme-lb-fade), #000 100%);
		mask-image: linear-gradient(to right, transparent 0, #000 var(--meme-lb-fade), #000 100%);
	}

	/* 格子在屏幕内放得下（没有溢出）：不需要任何渐隐，否则两端会凭空发灰 */
	.lightbox-related.is-at-start.is-at-end {
		-webkit-mask-image: none;
		mask-image: none;
	}
}

/* 10.5 打开 / 关闭动效 */

/*
 * 用 animation 而不是 transition：<dialog> 打开时是从 display:none 切到 flex，
 * transition 在「首次渲染」这一帧没有起点可插值，实测不会动。
 * animation 一定会跑，兼容性也更好。
 *
 * 打开：0.3s 整块淡入，主图与控制栏各错半拍轻微落位。
 * 之前是 0.24s + 从 0.96 缩放 / 24px 上移，时间和幅度都偏「急」，
 * 观感上还是「啪」地一下；现在放慢到 0.3s、幅度收到 0.985 与 12px，
 * 只在潜意识里感觉得到「拉开了一层」，不抢注意力。
 *
 * 关闭：.is-closing 由 JS 加上（lightbox.js 的 closeWithFade），
 * 播完 0.22s 淡出才真正 dialog.close()。
 */
@media (prefers-reduced-motion: no-preference) {
	/* 整块淡入。只动 opacity：全屏容器做缩放会在四周留出一圈边 */
	.meme-lightbox[open] {
		animation: meme-lb-fade-in 0.3s ease-out both;
	}

	.meme-lightbox[open]::backdrop {
		animation: meme-lb-fade-in 0.3s ease-out both;
	}

	/* 主图轻微放大落位，比整块一起缩放更像「拉开一层」 */
	.meme-lightbox[open] .lightbox-stage {
		animation: meme-lb-zoom-in 0.36s cubic-bezier(0.2, 0.7, 0.2, 1) both;
	}

	/* 控制栏自下而上收起，和主图错开半拍，观感上分两层 */
	.meme-lightbox[open] .lightbox-toolbar {
		animation: meme-lb-rise-in 0.36s cubic-bezier(0.2, 0.7, 0.2, 1) both;
	}

	/*
	 * 关闭：整块 + 遮罩一起淡出。
	 * 必须连 ::backdrop 一起动，否则 dialog 淡到透明了、背后还压着一块不透明黑，
	 * 页面要等 close() 之后才「啪」地露出来，等于没做关闭动效。
	 */
	.meme-lightbox[open].is-closing {
		animation: meme-lb-fade-out 0.22s ease-in both;
		/* 淡出期间别再响应用户点击，避免反复触发关闭流程 */
		pointer-events: none;
	}

	.meme-lightbox[open].is-closing::backdrop {
		animation: meme-lb-fade-out 0.22s ease-in both;
	}
}

@keyframes meme-lb-fade-in {
	from {
		opacity: 0;
	}

	to {
		opacity: 1;
	}
}

@keyframes meme-lb-fade-out {
	from {
		opacity: 1;
	}

	to {
		opacity: 0;
	}
}

@keyframes meme-lb-zoom-in {
	from {
		transform: scale(0.985);
	}

	to {
		transform: none;
	}
}

@keyframes meme-lb-rise-in {
	from {
		transform: translateY(12px);
	}

	to {
		transform: none;
	}
}

/* 10.6 桌面端：信息面板内容居中 */

/*
 * 控制栏里的缩略图 + 按钮已经整组居中（10.1），而信息面板是贴着屏幕左边开始排的：
 * 面板占满整行，文字全挤在 x=20 那一列。上下两块共用一条底边，中轴却错开半个屏幕，
 * 看着像两块互不相干的条。
 *
 * 面板宽度是 relative 铺满控制栏的（left: 0 / right: 0），所以「内容居中」
 * 就等于落在屏幕中线上，和下面的缩略图组对齐。只改内容，不动面板本身的宽度与背景，
 * 深色面仍然是一条贯穿的通栏，不会变成浮在中间的小卡片。
 *
 * text-align 只治块级与行内内容（标题、来源那一行里的文字），
 * 两个 flex 容器得各自用 justify-content 居中——flex 主轴对齐不吃 text-align。
 */
@media (min-width: 769px) {
	.lightbox-info-panel {
		text-align: center;
	}

	/* Size / Format 两颗是一行 flex，居中要靠主轴对齐 */
	.lightbox-meta {
		justify-content: center;
	}

	/* Source: 文案 + 链接，同样是一行 flex */
	.lightbox-source-row {
		justify-content: center;
	}
}

/* 10.7 手机端：左右滑动切图 */

/*
 * 横向手势由 JS 接管（lightbox.js 的 touchstart / touchmove / touchend）。
 * touch-action 只放行纵向与缩放：默认的 auto 会让横向拖动被浏览器当成
 * 「滑动返回上一页」，滑到一半灯箱就被系统手势带走了。
 */
@media (max-width: 768px) {
	.lightbox-stage {
		touch-action: pan-y pinch-zoom;
	}
}

/*
 * 跟手位移直接写在 .lightbox-main 的 transform 上。
 * 松手后要 0.22s 回弹 / 入场，所以平时带一条过渡；
 * 手指按住期间（舞台挂上 .is-dragging）必须把它关掉，
 * 否则每一帧都在插值，图会像被一根橡皮筋拖着，越滑越跟不上手指。
 */
.lightbox-main {
	transition: transform 0.22s ease, opacity 0.22s ease;
}

.lightbox-stage.is-dragging .lightbox-main {
	transition: none;
}

@media (prefers-reduced-motion: reduce) {
	.lightbox-main {
		transition: none;
	}
}
