/* ---- 影像视图：左列影像清单，右列 BILIBILI 播放器 ---- */
.video-scroll{
  position:relative;flex:1 1 0;min-height:0;
  /* 纵向之外也接横向：两栏排不下时由这一层滚，页眉页脚照旧定宽 */
  overflow:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:rgba(224,224,224,.2) transparent;
}
.video-scroll:focus-visible{outline:1px solid rgba(224,224,224,.28);outline-offset:-1px}
.video-scroll::-webkit-scrollbar{width:8px}
.video-scroll::-webkit-scrollbar-track{background:transparent}
.video-scroll::-webkit-scrollbar-thumb{background:rgba(224,224,224,.16);border-radius:4px}
.video-scroll::-webkit-scrollbar-thumb:hover{background:rgba(224,224,224,.28)}

/* 播放器高度随当前这一条的简介高矮变化：注册成可过渡的长度，换片时整块滑过去而不是跳过去 */
@property --frame-h{syntax:"<length>";inherits:false;initial-value:600px}

.video{
  --body-gap:clamp(24px,2.4vw,48px);
  /* 右列只有播放器与它下面的简介，简介之外的高度全部归播放器：播放器多高，宽度就按 16:9 定下来；
     简介实际多高由脚本按当前这一条量出来写到 --info-h 上，下面的 188 只是脚本未跑时的兜底 */
  --info-h:188px;
  --frame-h:max(240px,calc(100dvh - var(--head-foot) - 32px - 28px - 22px - var(--info-h)));
  /* 播放器按 16:9 定宽。照片模式下 --frame-w 会被脚本改写成这一张照片的宽度，
     所以清单宽不能引用它，否则列宽会跟着照片走；--player-w 谁也不改 */
  --player-w:calc(var(--frame-h) * 16 / 9);
  --frame-w:var(--player-w);
  /* 清单宽度取「播放器宽度」与「每条标题都完整排成两行所需的最小宽度」中的小者；
     后者由脚本量出来写到 --list-fit 上，下面的 340 只是脚本未跑时的兜底。
     两种模式都要量（封面宽与标题都不一样），--list-fit 取其中大者，于是两个模式下这一列同宽，
     切模式时不会变宽变窄 */
  --list-fit:340px;
  --list-w:min(var(--list-fit),var(--player-w));
  /* 播放器宽度由可用高度定，高度用满时整块会比全局 .wrap 的 2400 上限更宽，这一页单独放开 */
  max-width:none;
  display:flex;flex-direction:column;
  height:100%;
  padding-top:32px;padding-bottom:28px;
  transition:--frame-h .32s cubic-bezier(.22,.68,.16,1);
}
/* 拖动窗口时尺寸要即时跟随，不要落后半秒 */
.video.is-dragging{transition:none}

/* 窗口窄到两栏排不下时不再上下堆叠：内容区自己横向滚（.video-scroll），播放器始终在清单右侧。
   960 是原先堆叠断点的宽度，这里当作两栏的可用最小宽；只有窗口矮到退回整页滚时才让位 */
@media (min-height:420px){
  .video{min-width:960px}
  /* 两栏这一支才要右列自己竖滚（堆叠时整页在滚，右列跟着内容长高）。
     不留常驻 gutter：画框宽度由「可用高度」或「这一张的比例」定，与滚动条是否出现无关，
     所以滚动条一出一没也不会让画框在临界处来回跳 */
  .video-main{
    overflow-y:auto;overscroll-behavior:contain;
    scrollbar-width:thin;scrollbar-color:rgba(224,224,224,.16) transparent;
  }
}
/* 标题行：标题在左，右侧一组竖排的「照片／视频」。这一行常驻在清单之上、不随清单滚走，
   清单的分组顶栏排在它下面；换模式时它也不跟着淡出，两颗按钮照旧可点 */
.video-head{
  flex:none;
  display:flex;align-items:center;justify-content:space-between;gap:18px;
  margin:0 0 26px;
}
.video-heading{
  margin:0;outline:none;white-space:nowrap;
  font-family:var(--display);font-weight:900;
  font-size:clamp(30px,3.4vw,44px);line-height:1.2;letter-spacing:.04em;
  color:var(--paper);
}
/* 模式切换两处同一套件：清单头顶竖排一组，页眉里横排一组（见 views.css 的 .bar-modes）。
   选中态就是全站那块三段彩条（定义在 base.css 的 --sweep-bg）——两端各 8px 红、中间半透
   明蓝；换边时新选中那颗从左扫进来、旧的那颗从左往右擦掉，与清单选中态同一条曲线 */
.video-modes{flex:none;display:flex;flex-direction:column;gap:4px}
.mode-btn{
  position:relative;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  /* 文字必须落在中间那段半透明蓝里：离两端的彩条各留 6px。这条内距是按右端 8px 彩条
     算出来的，改 --sweep-band 时要跟着改，一收就压到字上 */
  padding:4px 13px;border:1px solid rgba(224,224,224,.2);background:none;cursor:pointer;
  font:11px/1 var(--sans);letter-spacing:.14em;color:var(--ash);
  /* 页眉那组是绝对定位、可用宽算出来是负数，不写 nowrap 两个字的文案会被竖着拆开 */
  white-space:nowrap;
  transition:color .2s ease,border-color .2s ease;
}
.mode-btn:hover{color:var(--smoke);border-color:rgba(224,224,224,.45)}
.mode-btn:focus-visible{outline:1px solid var(--smoke);outline-offset:3px}
.mode-btn[aria-pressed="true"]{color:var(--paper);border-color:rgba(224,224,224,.34)}
.mode-fill{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background:var(--sweep-bg);
  clip-path:inset(0 100% 0 0);
}
/* 选中态的彩条由脚本的行内 clip-path 收尾，这里管的是没动过的那一颗：
   进视图、字体落定这类同步都不放动画，状态直接由这条规则表达 */
.mode-btn[aria-pressed="true"] .mode-fill{clip-path:inset(0 0 0 0)}
.mode-label{position:relative;z-index:1}

/* 整块从左边起排：清单钉在页面左内缘，右侧内容贴着清单，画框宽窄变化时不再带着整块左右挪 */
.video-body{
  width:100%;
  flex:1 1 0;min-height:0;
  display:grid;
  grid-template-columns:var(--list-w) minmax(0,1fr);
  grid-template-rows:minmax(0,1fr);
  gap:var(--body-gap);
}

/* ---- 左列清单 ---- */
/* 左列三段：常驻的标题行、分组顶栏、自带分栏的清单。三种分栏都不压在任何东西上，所以都不需要底衬 */
.video-side{
  position:relative;
  display:flex;flex-direction:column;
  min-width:0;min-height:0;
  padding-right:4px;
}
.video-list{
  position:relative;
  flex:1 1 0;min-height:0;
  overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:thin;scrollbar-color:rgba(224,224,224,.16) transparent;
}
.video-list:focus-visible{outline:1px solid rgba(224,224,224,.28);outline-offset:-1px}
.video-list::-webkit-scrollbar{width:5px}
.video-list::-webkit-scrollbar-track{background:transparent}
.video-list::-webkit-scrollbar-thumb{background:rgba(224,224,224,.14);border-radius:3px}
.video-list::-webkit-scrollbar-thumb:hover{background:rgba(224,224,224,.26)}

/* 清单没滚到底时列底浮一枚向下箭头：落在页面底内距里，不压最后一条。
   形制与首页文字列那枚完全相同，关键帧 intro-hint 定义在 base.css */
.vlist-hint{
  position:absolute;left:0;right:0;top:calc(100% + 4px);
  display:flex;justify-content:center;pointer-events:none;
  opacity:0;transition:opacity .38s ease;
}
.vlist-hint.is-on{opacity:1}
.vlist-hint svg{
  display:block;width:18px;height:18px;color:#de3546;
  animation:intro-hint 2.2s ease-in-out infinite;
}

/* ---- 换模式时的过场 ---- */
/* 清单从上到下逐行淡出，换过数据后再从上到下淡入；每一行的延迟由脚本按行号写进行内
   transition-delay。淡出的这段时间整列不可点，免得点到正在消失的那一份 */
.vgroup-name,.vitem{transition:opacity .17s ease}
.video-list.is-hidden .vgroup-name,
.video-list.is-hidden .vitem{opacity:0}
.video.is-switching .video-list{pointer-events:none}
/* 右列整块（画框与简介）一起淡出，等新清单淡入完成后才由脚本淡回，不在清单还是空的时候先亮起来 */
.video-main{transition:opacity .24s ease}
.video-main.is-switching{opacity:0}

.vgroup + .vgroup{margin-top:22px}
/* 分栏只由文字与右侧细线构成，不铺任何底色 */
.vgroup-name,.vgroup-now{
  display:flex;align-items:center;gap:16px;
  margin:0;padding:13px 0 11px;
  font-family:var(--serif);font-weight:400;
  font-size:14px;line-height:1;letter-spacing:.18em;
  color:rgba(224,224,224,.76);
}
.vgroup-name::after,.vgroup-now::after{
  content:"";flex:1 1 auto;height:1px;
  background:linear-gradient(90deg,rgba(224,224,224,.22),rgba(224,224,224,.03));
}
/* 列顶那条不随内容滚动；这一段的标签还在视野里时它静默，标签整行滚出去之后才浮出来接替 */
.vgroup-now{
  flex:none;opacity:0;transform:translateY(4px);
  transition:opacity .18s ease,transform .18s ease;
}
.vgroup-now.is-on{opacity:1;transform:none}
.vlist{margin:0;padding:0;list-style:none}

.vitem{
  position:relative;
  display:flex;align-items:center;gap:14px;width:100%;
  /* 右端 8px 是高光的两条彩条，正文列让出这一带并再留 8px 空隙，标题不会被色块压住 */
  padding:9px 16px 9px 12px;
  border:0;border-left:1px solid transparent;
  background:none;text-align:left;cursor:pointer;color:inherit;
}
/* 选中条目：一块矩形，两端各 8px 红、中间半透明蓝（见 --sweep-bg），三段无缝拼接 */
.vitem::before{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:var(--sweep-bg);
  clip-path:inset(0 100% 0 0);
}
/* 失选后从左缘起往右擦掉，右端两条彩条最后消失 */
.vitem.is-out::before{
  clip-path:inset(0 0 0 100%);
  transition:clip-path .52s cubic-bezier(.4,.05,.15,1);
}
/* 扫进来用动画不用过渡：每次都从左侧起放，不受这一条上次停在哪个位置影响 */
.vitem[aria-current="true"]::before{
  clip-path:inset(0 0 0 0);
  animation:vsweep .52s cubic-bezier(.4,.05,.15,1);
}
@keyframes vsweep{
  from{clip-path:inset(0 100% 0 0)}
  to{clip-path:inset(0 0 0 0)}
}
.vitem:focus-visible{outline:1px solid var(--smoke);outline-offset:-3px}
.vitem-art{
  position:relative;flex:none;width:96px;aspect-ratio:16/9;overflow:hidden;
  background:rgba(224,224,224,.045);
  box-shadow:inset 0 0 0 1px rgba(224,224,224,.07);
}
.vitem-art img{
  display:block;width:100%;height:100%;object-fit:cover;
  /* 压暗只走 filter 这一层：再叠 opacity 就是两层相乘，标称的 75% 到不了 */
  filter:saturate(.75) brightness(.75);
  transition:filter .4s ease,opacity .4s ease;
}
.vitem:hover .vitem-art img,
.vitem[aria-current="true"] .vitem-art img,
.vitem:focus-visible .vitem-art img{filter:saturate(1) brightness(1);opacity:1}
.vitem-body{display:flex;flex-direction:column;min-width:0}
.vitem-title{
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
  font:13px/1.5 var(--sans);letter-spacing:.01em;
  color:rgba(224,224,224,.68);
  transition:color .25s ease;
}
.vitem:hover .vitem-title{color:var(--smoke)}
.vitem[aria-current="true"] .vitem-title{color:var(--paper)}

/* ---- 右列播放器 ---- */
/* 右列自己竖着滚，与左侧清单互不牵连：高度不够时把画框与简介滚出来，而不是把画框压扁。
   滚动条与左侧清单同一套写法（细、几乎透明、悬停才亮），两条并排时看不出差别 */
.video-main{
  display:flex;flex-direction:column;gap:22px;
  min-width:0;min-height:0;
}
.video-main::-webkit-scrollbar{width:5px}
.video-main::-webkit-scrollbar-track{background:transparent}
.video-main::-webkit-scrollbar-thumb{background:rgba(224,224,224,.14);border-radius:3px}
.video-main::-webkit-scrollbar-thumb:hover{background:rgba(224,224,224,.26)}
/* 右列现在铺满清单之外的宽度，比按高度算出来的播放器还宽；播放器只取这一宽度里的 16:9，不跟着撑大。
   flex:none 是这一条的关键：默认的 flex-shrink 会让画框在高度不够时自己变矮，16:9 一破就把图裁掉了 */
.video-frame{
  flex:none;
  position:relative;width:min(100%,var(--frame-w));aspect-ratio:16/9;
  overflow:hidden;background:#070707;border:1px solid var(--line);
}
.video-frame iframe{
  position:absolute;inset:0;display:block;
  width:100%;height:100%;border:0;background:#000;
  opacity:0;transition:opacity .45s ease;
}
.video-frame.is-ready iframe{opacity:1}
.vposter{
  position:absolute;inset:0;z-index:1;width:100%;height:100%;object-fit:cover;
  filter:blur(26px) brightness(.42) saturate(.7);
  transform:scale(1.1);pointer-events:none;
  transition:opacity .5s ease;
}
.vposter[hidden]{display:none}
.video-frame.is-ready .vposter{opacity:0}
.vloading{
  position:absolute;inset:0;z-index:2;margin:0;
  display:flex;align-items:center;justify-content:center;gap:12px;
  font:10px/1 var(--sans);letter-spacing:.28em;color:rgba(140,140,140,.9);
  transition:opacity .4s ease;pointer-events:none;
}
.vloading::before{
  content:"";width:10px;height:10px;border-radius:50%;
  border:1px solid rgba(224,224,224,.22);border-top-color:var(--smoke);
  animation:vspin .8s linear infinite;
}
.video-frame.is-ready .vloading{opacity:0}
@keyframes vspin{to{transform:rotate(360deg)}}

/* ---- 照片模式：画框宽度跟着这一张（或这一组）走，高度由 --stage-h 定 ---- */
/* 画框尺寸由脚本现算后写在行内，切换照片时脚本按视频那条曲线把它滑过去（见 placeFrame）；
   这里不能对 --frame-h 做过渡，否则脚本量简介高度时读到的是动画中途的值 */
.video[data-mode="photo"]{transition:none}
.video[data-mode="photo"] .video-frame{
  height:var(--stage-h,var(--frame-h));
  aspect-ratio:auto;
  /* 画框正好裹住这一组照片：不垫深色底、不留边框，照片直接落在页面上 */
  background:none;border:0;
}
/* 多张时按脚本算出的切法摊开：每行等高、行宽正好等于整块宽度，中间只留 8px 缝 */
.vphoto{
  position:absolute;inset:0;z-index:1;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  opacity:0;transition:opacity .45s ease;
}
.video-frame.is-ready .vphoto{opacity:1}
/* 行高写成分式（分母是这一行各图比例之和），画框一滑，整块照片跟着缩放，不必逐帧改图尺寸 */
.vphoto-row{display:flex;gap:8px;justify-content:center}
.vphoto-row img{display:block;height:100%;width:auto;cursor:zoom-in}
/* 照片本身可点：键盘走到这里用 Enter 或空格打开全屏，焦点圈贴着图走
   （画框 overflow:hidden，圈往外放会被裁掉，所以往里收） */
.vphoto-row img:focus-visible{outline:1px solid var(--smoke);outline-offset:-3px}
/* 照片的清单缩略图与视频封面同形：都是 16:9，切模式时封面宽度不跟着变 */
.vitem-count{
  position:absolute;right:4px;bottom:4px;z-index:2;
  padding:1px 4px;background:rgba(15,15,15,.7);
  font:9px/1.4 var(--sans);letter-spacing:.08em;color:rgba(224,224,224,.8);
}

.vinfo{display:flex;flex-direction:column;gap:9px;min-width:0;flex:none}
/* 标题与标签走行内文字流，不用 flex：flex 里标题会占满整行宽，折行后第二行明明还有空，
   标签也只能另起一行。行内排法让标签接在标题最后一行的字尾后面，真放不下才整组换行。
   font-size:0 吃掉两个元素之间那个换行空白——它的宽度由容器字号决定，会让 14px 间距不准，
   而且容器自己的行高支柱会撑高整行；标题与标签各自带字号，不受影响 */
.vinfo-head{display:block;font-size:0}
.vtitle{
  display:inline;margin:0 14px 0 0;
  font-family:var(--serif);font-weight:400;
  font-size:clamp(18px,1.4vw,23px);line-height:1.45;letter-spacing:.02em;
  color:var(--paper);
}
/* 宽度钉在 max-content 上：行内块默认会被剩余空间压窄，压成几十像素时标签会自己在组内叠成一列；
   钉住之后行内断行只按整组宽度判断放不放得下 */
.vtags{
  display:inline-flex;flex-wrap:wrap;gap:6px;vertical-align:baseline;
  width:max-content;max-width:100%;
  margin:0;padding:0;list-style:none;
}
.vtags li{
  padding:3px 8px;border:1px solid rgba(224,224,224,.16);
  font:10px/1.5 var(--sans);letter-spacing:.1em;color:var(--ash);
}
/* 简介按右列整条宽度排版，不跟画框一样宽，也不再另设一道最大宽度 */
.vdesc{
  margin:0;white-space:pre-line;
  font-size:15px;line-height:1.85;color:rgba(224,224,224,.76);
}
.vdesc:empty{display:none}
/* 描述里带外链的条目（漫画一类）：链接自占一行，底下一条细线 */
.vdesc a{border-bottom:1px solid rgba(224,224,224,.3)}
.vdesc a:hover,.vdesc a:focus-visible{color:var(--paper);border-bottom-color:var(--smoke)}
.vdesc a:focus-visible{outline:1px solid var(--smoke);outline-offset:3px}

/* 只有窗口矮到整页开始滚（与首页同一道 420 门槛）时，才退回上下堆叠、整页滚 */
@media (max-height:419px){
  .video{height:auto;min-height:100%;padding-top:24px;padding-bottom:40px}
  .video-head{margin-bottom:20px}
  .video-body{display:block;width:100%;flex:0 0 auto}
  .video-main{gap:18px}
  .video-side{display:block;padding-right:0;margin-top:34px}
  .video-list{flex:none;min-height:0;overflow:visible}
  .vgroup-now{display:none}
  .vgroup-name{display:flex;padding-top:16px}
  .vitem{padding:10px 16px 10px 12px}
  .vitem-art{width:104px}
  .vtitle{font-size:19px}
  .vdesc{font-size:14px;line-height:1.8}
}

@media (max-height:419px){
  .video-scroll{overscroll-behavior:auto}
}

@media (prefers-reduced-motion:reduce){
  .video,.vitem,.vitem::before,.vitem-art img,.vposter,.video-frame iframe,.vloading,.vgroup-now,.vphoto,.vphoto-row img,.vgroup-name,.video-main,.mode-btn{transition:none}
  .vlist-hint svg{animation:none;opacity:.55}
  /* 扫开与擦除挂在下面两条上，权重比 .vitem::before 高，得按同样的选择器关掉 */
  .vitem.is-out::before,
  .vitem[aria-current="true"]::before{animation:none;transition:none}
  .vloading::before{animation-duration:2.4s}
}

/* ---- 全屏照片查看 ---- */
/* 用原生 <dialog>：模态层由浏览器管理，不必与页眉、载入黑场的 z-index 竞争。
   UA 给的居中与 100%-6px-2em 的宽高上限都要撤掉，整块铺满视口 */
html.pv-open{overflow:hidden}
.photo-view{
  /* 翻页键宽度与它离画心的间隙：画心的 max-width 由这两个数算出，图不会溜到键下面 */
  --pv-step-w:30px;
  --pv-step-gap:16px;
  position:fixed;inset:0;
  width:100%;height:100%;max-width:none;max-height:none;
  margin:0;padding:0;border:0;background:transparent;overflow:hidden;
  color:var(--smoke);
}
.photo-view:focus{outline:none}
.photo-view::backdrop{
  background:rgba(6,6,6,.9);
  -webkit-backdrop-filter:blur(14px) saturate(.85);
  backdrop-filter:blur(14px) saturate(.85);
  opacity:0;transition:opacity .26s ease;
}
.photo-view.is-open::backdrop{opacity:1}
/* 入场整块略微放大就位；退场反过来，动画走完脚本才真正 close */
.pv-shell{
  display:flex;flex-direction:column;height:100%;
  padding:0 var(--pad-x) 20px;
  opacity:0;transform:scale(.988);
  transition:opacity .26s ease,transform .26s cubic-bezier(.22,.68,.16,1);
}
.photo-view.is-open .pv-shell{opacity:1;transform:none}

/* 页眉：标题在左，右侧一组「下载／关闭」。标题可能很长，允许折行，不撑高整块 */
.pv-head{
  flex:none;display:flex;align-items:flex-start;justify-content:space-between;gap:24px;
  padding:20px 0 14px;
}
.pv-title{
  margin:0;min-width:0;
  font-family:var(--serif);font-weight:400;
  font-size:clamp(16px,1.25vw,20px);line-height:1.5;letter-spacing:.03em;
  color:var(--paper);
}
.pv-actions{flex:none;display:flex;align-items:center;gap:8px}
/* 下载是一枚带 download 的链接，与关闭同一形制，所以只写一颗 */
.pv-btn{
  display:inline-block;
  padding:5px 14px;border:1px solid rgba(224,224,224,.2);background:none;cursor:pointer;
  font:11px/1 var(--sans);letter-spacing:.14em;color:var(--ash);text-decoration:none;
  transition:color .2s ease,border-color .2s ease;
}
.pv-btn:hover,.pv-btn:focus-visible{color:var(--paper);border-color:rgba(224,224,224,.45)}
.pv-btn:focus-visible{outline:1px solid var(--smoke);outline-offset:3px}

/* 画心：原图与占位图叠在同一个中心点，都按自身比例在可用框内取最大。
   左右各让出一条翻页键的宽度加间隙，横长的图不会伸到键下面 */
.pv-stage{position:relative;flex:1 1 0;min-height:0;overflow:hidden}
.pv-stage img{
  position:absolute;inset:0;margin:auto;display:block;
  width:auto;height:auto;max-height:100%;
  max-width:calc(100% - var(--pv-step-w) - var(--pv-step-gap) - var(--pv-step-w) - var(--pv-step-gap));
}
/* 原图未到之前先铺展示稿：它已随画框下载过，这里直接取缓存。压暗虚化，读起来是占位不是成品 */
.pv-under{
  filter:blur(18px) brightness(.42) saturate(.8);
  transform:scale(1.02);
  transition:opacity .45s ease;
}
.pv-img{opacity:0;transition:opacity .45s ease}
.photo-view.is-loaded .pv-img{opacity:1}
.photo-view.is-loaded .pv-under{opacity:0}

/* 多图条目在两侧给出翻页：位置贴着画心边缘，不压住居中的图 */
.pv-step{
  position:absolute;top:50%;z-index:2;transform:translateY(-50%);
  display:flex;align-items:center;justify-content:center;
  width:var(--pv-step-w);height:76px;padding:0;
  border:3px solid rgba(224,224,224,.16);
  background:rgba(10,10,10,.44);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  color:var(--ash);cursor:pointer;
  transition:color .2s ease,border-color .2s ease,background-color .2s ease;
}
.pv-step svg{display:block;width:12px;height:12px}
.pv-step:hover,.pv-step:focus-visible{
  color:var(--paper);border-color:rgba(224,224,224,.4);background:rgba(10,10,10,.7);
}
.pv-step:focus-visible{outline:1px solid var(--smoke);outline-offset:2px}
.pv-step.is-prev{left:0}
.pv-step.is-next{right:0}
.pv-step[hidden]{display:none}

/* 底部这一条常驻：载入时是进度与百分比，载完之后只剩「第几张／共几张」。
   单图条目没有序号可报，整条收起来，画心顺势长高——高度走过渡，载入完成那一刻不跳。
   多图条目的高度不改，图片可用区在载入前后一致 */
.pv-status{
  flex:none;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:10px;min-height:64px;max-height:64px;padding:14px 0 0;
  transition:max-height .3s ease,min-height .3s ease,padding-top .3s ease,opacity .22s ease;
}
.photo-view.is-plain .pv-status{
  max-height:0;min-height:0;padding-top:0;opacity:0;overflow:hidden;
}
.pv-status-line{
  display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;gap:14px;
  margin:0;
}
.pv-status-text{font:11px/1 var(--sans);letter-spacing:.22em;color:var(--ash)}
.pv-pct{
  font:10px/1 var(--sans);letter-spacing:.1em;
  color:rgba(140,140,140,.8);font-variant-numeric:tabular-nums;
}
.pv-pct:empty{display:none}
.pv-track{display:none;width:min(320px,62vw);height:2px;background:rgba(224,224,224,.14);overflow:hidden}
.photo-view.is-loading .pv-track{display:block}
.pv-fill{
  display:block;width:100%;height:100%;background:var(--smoke);
  transform:scaleX(0);transform-origin:left center;
}
/* 服务器没给 Content-Length 时退成一条来回扫的带子，不给假百分比 */
.pv-track.is-unknown .pv-fill{width:30%;animation:pvflow 1.2s cubic-bezier(.4,.05,.15,1) infinite}
@keyframes pvflow{
  from{transform:translateX(-120%)}
  to{transform:translateX(340%)}
}

@media (max-width:720px){
  .photo-view{--pv-step-w:26px;--pv-step-gap:12px}
  .pv-head{padding-top:16px}
  .pv-step{height:64px}
}

@media (prefers-reduced-motion:reduce){
  .photo-view::backdrop,.pv-shell,.pv-under,.pv-img,.pv-status{transition:none}
  .pv-track.is-unknown .pv-fill{animation-duration:2.4s}
}
