/* ===== PROJECT PAGE: default grid layout ===== */
.project-grid{
  display:grid;
  grid-template-columns:1fr 1fr;
  width:100%;height:100vh;
}
.media-area{
  border-right:3px solid #000;
  display:flex;align-items:center;justify-content:center;
  background:#f0f0f0;
  overflow:hidden;
}
.media-placeholder{font-size:14px;letter-spacing:1px;text-transform:uppercase;color:#888}
.media-area video,.media-area img,.media-area iframe{display:block;width:100%;height:100%;object-fit:cover;border:none;outline:none}
.info-area{
  padding:32px;
  overflow-y:auto;
  font-size:13px;
  line-height:1.7;
}
.info-area h2{
  font-size:20px;font-weight:700;letter-spacing:2px;text-transform:uppercase;
  border-bottom:3px solid #000;padding-bottom:8px;margin-bottom:24px;
}
.info-area p{margin-bottom:16px}

/* ===== shared ===== */
.redact{background:#000;color:#000;padding:0 4px;letter-spacing:2px;margin:0 2px}

/* 作品信息栏：每件作品描述顶部的字段化事实行。
   注意：描述被注入的容器在部分布局里是 <p>，因此这里只用 <span> 构造
   （CSS display 不影响解析，<span> 是 phrasing content，安全）。
   子元素成对出现，整体作为一个 grid，标签列自动对齐。
   不留上边框：grid/edge/gallery 三种布局的 h2 本身已有 3px 下边框，
   再加一条会形成 24px 间隔的双平行线。下边框足以界定这个块。 */
.work-meta{
  display:grid;
  grid-template-columns:88px 1fr;
  gap:3px 14px;
  margin:0 0 32px;
  border-bottom:3px solid #000;
  padding:0 0 14px;
  font-size:12.5px;
  line-height:1.7;
  letter-spacing:0.5px;
  text-align:left;
}
.work-meta-k{font-weight:700;color:#888;letter-spacing:1px}
.work-meta-v{color:#000;min-width:0}

/* 信息栏上方那条分割线（= 标题的 3px 下边框）与它、以及它与信息栏下边框之间
   必须等距。标题的 margin-bottom:24px 对这个块偏大：1440px 下渲染实测，
   上边框到第一行 28px、末行到下边框 19px（英文 29 / 17），两条线明显不等距。
   故描述片段以信息栏开头时，把标题的下边距收到与信息栏 padding-bottom 相同的
   14px（移动 12px），使上下都约 19px。
   **这两个值必须与 .work-meta 的 padding-bottom 一起改**，否则又会不等距。
   :has() 不匹配（描述不是以信息栏开头，或浏览器不支持）时维持标题原有的 24px。 */
.info-area h2:has(+ #grid-desc > .work-meta),
.gallery-body h2:has(+ #gallery-desc > .work-meta),
.edge-body h2:has(+ #edge-desc > .work-meta){margin-bottom:14px}

/* 正文里的分节小标题 */
.work-sec{display:block;font-weight:700;margin-bottom:8px}

/* 作品副标题：嵌在标题（h2）内部，位于标题文字与 h2 下边框之间，
   使副标题与标题成为一个整体（参考 Works 页 .works-title + .works-brief 的配对）。
   内容取自 project.subtitle，未单独给则退回 project.brief，由 js/project.js 的
   setTitle() 渲染。只在作品页出现，不参与首页卡片与 Works 列表。
   注意 text-transform 必须归位，否则继承 h2 的 uppercase。 */
h2 .work-sub{
  display:block;
  font-size:12.5px;font-weight:400;color:#888;
  letter-spacing:0.5px;line-height:1.5;
  text-transform:none;
  margin-top:6px;
}
@media(max-width:768px){
  h2 .work-sub{font-size:11.5px;margin-top:4px}
}

/* 不换行：用于 12–36V、2025.10.22–25 这类不该在连字符/短横处断开的记号 */
.nb{white-space:nowrap}

/* 作品页可折叠块：把长引文（如 riverrun 的轨道文本对照）从主叙述里移出来，
   保持正文可扫读。样式与 changelog 的 details 一致，但用 class 作用域限定，
   不依赖 changelog.css（那个文件只在 changelog 页加载）。 */
.work-details{border:2px solid #000;margin:0 0 16px}
.work-details>summary{padding:10px 14px;cursor:pointer;font-size:13px;font-weight:700;letter-spacing:1px;list-style:none}
.work-details>summary::-webkit-details-marker{display:none}
.work-details>summary::before{content:'[+] ';margin-right:6px}
.work-details[open]>summary::before{content:'[-] '}
.work-details>summary:hover{background:#000;color:#fff}
.work-details[open]>summary{border-bottom:2px solid #000}
.work-details-body{padding:14px}

/* 引文块（riverrun 的轨道文本对照等） */
.track-text{margin:0 0 16px;padding:12px 16px;border-left:3px solid #000;background:#f9f9f9;font-size:12.5px;line-height:1.9}
.track-text:last-child{margin-bottom:0}

/* mixer 布局的描述栏只有 380px 宽（css 同文件 .mixer-desc），
   信息栏的 88px 标签列在这里太占位，收窄到 68px。 */
.mixer-desc .work-meta{grid-template-columns:68px 1fr;gap:3px 10px}

@media(max-width:768px){
  .work-meta{grid-template-columns:72px 1fr;gap:3px 10px;margin-bottom:24px;padding:0 0 12px;font-size:12px}
  /* 与信息栏移动端的 padding-bottom（12px）配套，见上 */
  .info-area h2:has(+ #grid-desc > .work-meta),
  .gallery-body h2:has(+ #gallery-desc > .work-meta),
  .edge-body h2:has(+ #edge-desc > .work-meta){margin-bottom:12px}
}

/* related works cross-links */
.project-related{margin-top:32px;display:flex;flex-direction:column;gap:6px}
.project-related-link{display:inline-block;align-self:flex-start;font-size:13px;letter-spacing:0.5px;color:#000;text-decoration:none;border-bottom:1px solid #000;padding-bottom:2px}
.project-related-link:hover{background:#000;color:#fff}

/* ===== WWHBH layout ===== */
.wwhbh-panel{display:none;flex-direction:column;align-items:center;padding:80px 40px 40px}
/* 实时晕染层（js/ink-wwhbh.js）。
   position:fixed 铺满的是「视口」而不是「文档」——这件作品的晕染是
   「你正在待着的这个房间的状态」，不是某一页的背景，所以滚动时它不跟着走。

   z-index:200 —— **墨盖在整个页面内容之上**（作者要求「全部盖住，包括标题」）。
   导航是 z-index:100，同样在墨之下。因为墨层是 pointer-events:none，
   底下的按钮与导航仍然可以正常点击，只是可能看不清；
   关闭按钮那一小块由 js/ink-wwhbh.js 把墨压淡，保留可辨认的关闭入口。 */
.wwhbh-ink{position:fixed;inset:0;z-index:200;pointer-events:none;overflow:hidden}
.wwhbh-ink canvas{display:block;width:100%;height:100%}
.wwhbh-body{max-width:800px;width:100%;text-align:left}
.wwhbh-body h2{font-size:20px;font-weight:700;letter-spacing:2px;text-transform:uppercase;margin-bottom:32px}
.wwhbh-body p{line-height:2.4;font-size:14px;letter-spacing:0.5px;margin-bottom:32px}
/* 麦克风状态与控制：紧贴标题下方。
   页面加载即自动申请权限，这里显示 申请中／待点击／聆听中／被拒／不可用。
   状态行占据剩余宽度，按钮只在其有意义时（重试／关闭）出现且为自适应宽度。 */
.wwhbh-mic{display:flex;align-items:center;gap:16px;margin:-14px 0 32px;min-height:34px}
.wwhbh-status{margin:0;flex:1;font-size:13px;letter-spacing:1px;color:#888;line-height:1.5}
.wwhbh-status.on{color:#000;font-weight:700}
/* 待点击时整行可点（浏览器自动播放策略要求至少一次用户手势） */
.wwhbh-status.clickable{cursor:pointer;color:#000;font-weight:700;text-decoration:underline}
.wwhbh-mic .btn-mic{width:auto;flex:none;padding:8px 18px;font-size:12px;letter-spacing:1px}
.btn-mic{
  width:100%;font-size:14px;font-weight:700;
  letter-spacing:2px;text-transform:uppercase;
  border:3px solid #000;background:#fff;color:#000;
  padding:12px;cursor:pointer;
}
.btn-mic:hover{background:#000;color:#fff}
.btn-mic.on{background:#000;color:#fff}

/* ===== ECCE HOMO layout ===== */
.ecce-panel{display:none;flex-direction:column;align-items:center;padding:80px 40px 40px}
.ecce-panel>h2{font-size:20px;font-weight:700;letter-spacing:2px;text-transform:uppercase;margin-bottom:24px;align-self:flex-start;max-width:800px;width:100%}
.ecce-still{width:100%;max-width:800px;border-bottom:3px solid #000;display:block}
.ecce-audio{width:100%;max-width:800px;display:block;margin:0;padding:0}
.ecce-text{padding:24px 0 0;max-width:800px;width:100%}
.ecce-text #ecce-desc{line-height:2.4;font-size:14px;letter-spacing:0.5px}

/* Teletype scene display (The JustType Study) */
.tt-wrap{width:100%;margin:8px 0 0;line-height:1.5}
.tt-block{font-family:'DejaVu Sans Mono',Menlo,Consolas,monospace;font-size:13px;line-height:1.7;white-space:pre;overflow-x:auto;background:#f4f4f4;color:#000;padding:16px 18px;border:1px solid #e4e4e4;border-radius:6px;box-shadow:0 1px 3px rgba(0,0,0,0.06);margin:0 0 16px}
.tt-block .tt-h{font-weight:700}
.tt-download{display:inline-block;margin-top:4px;font-size:13px;letter-spacing:0.5px;color:#000;text-decoration:none;border-bottom:1px solid #000}
.tt-download:hover{background:#000;color:#fff}

/* ===== EDGE layout ===== */
.edge-panel{display:none;flex-direction:column;align-items:center;padding:80px 40px 40px}
.edge-media{width:100%;max-width:800px;aspect-ratio:16/9;overflow:hidden;background:#f0f0f0}
.edge-media iframe{display:block;width:100%;height:100%;border:none}
.edge-body{max-width:800px;width:100%;text-align:left;padding-top:24px}
.edge-body h2{font-size:20px;font-weight:700;letter-spacing:2px;text-transform:uppercase;border-bottom:3px solid #000;padding-bottom:8px;margin-bottom:24px}
.edge-body p{line-height:2.4;font-size:14px;letter-spacing:0.5px}

/* ===== GALLERY layout ===== */
.gallery-panel{display:none;flex-direction:column;align-items:center;padding:80px 40px 40px}
.gallery-body{max-width:800px;width:100%;text-align:left}
.gallery-body h2{font-size:20px;font-weight:700;letter-spacing:2px;text-transform:uppercase;border-bottom:3px solid #000;padding-bottom:8px;margin-bottom:24px}
.gallery-body p{line-height:2.4;font-size:14px;letter-spacing:0.5px}
/* 分组网格（原先是一条等高横滑胶片条）。
   6U104HP 的图片从 11 张涨到 21 张（11 产品 + 10 参展）后，横滑条要拖约 15000px
   —— 约 18 屏，而且看不出还剩多少张、也无法跳转；横滑还会和触控板的页面滚动抢手势。
   改为纵向网格：一屏看得到全貌，页面自然纵向滚动，与上方正文衔接。
   每格固定 4:3、object-fit:contain：不裁切、不变形，留白沿用旧胶片条的 #f0f0f0。
   点开仍是同一个 Lightbox，所以尺寸变小不损失观看质量。 */
.gallery-sections{width:100%;max-width:800px;margin-top:24px;border-top:3px solid #000;padding-top:24px}
.gallery-section + .gallery-section{margin-top:44px}
.gallery-section-title{font-size:12px;font-weight:700;letter-spacing:2px;text-transform:uppercase;line-height:1;margin-bottom:14px}
.gallery-group + .gallery-group{margin-top:26px}
.gallery-group-title{font-size:11px;font-weight:400;letter-spacing:1px;line-height:1;margin-bottom:8px}
.gallery-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}
.gallery-grid img{display:block;width:100%;aspect-ratio:4/3;object-fit:contain;background:#f0f0f0;cursor:zoom-in}

/* ===== MOBILE ===== */
@media(max-width:768px){
  .project-grid{grid-template-columns:1fr;height:auto;min-height:100vh}
  .media-area{border-right:none;border-bottom:3px solid #000;min-height:40vw}
  .info-area{padding:20px 16px}
  .info-area h2{font-size:16px}
  .wwhbh-panel{padding:70px 16px 24px}
  .wwhbh-mic{gap:10px;margin:-10px 0 24px;min-height:30px}
  .wwhbh-status{font-size:12px}
  .wwhbh-mic .btn-mic{padding:7px 12px;font-size:11px}
  .ecce-panel{padding:70px 16px 24px}
  .edge-panel{padding:70px 16px 24px}
  .edge-media{aspect-ratio:16/9}
  .gallery-panel{padding:70px 16px 24px}
  .gallery-grid{grid-template-columns:repeat(2,1fr)}
}

/* ===== MIXER layout (riverrun) ===== */
.mixer-panel{display:none;flex-direction:column;height:100vh;height:100dvh;padding:76px 20px 18px;gap:10px;overflow:hidden;max-width:1080px;margin:0 auto;width:100%}
.mixer-header{padding:0 4px}
.mixer-header h2{font-size:18px;font-weight:700;letter-spacing:2px;text-transform:uppercase;line-height:1}
.mixer-panel.lowercase .mixer-header h2{text-transform:none;letter-spacing:1px}
.mixer-body{display:flex;flex:1;min-height:0;gap:14px}
.mixer-stage{position:relative;flex:1;min-width:0;border:3px solid #000;background:#fff;overflow:hidden}
.mixer-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;touch-action:none;cursor:crosshair}
/* 说明列：桌面在右侧（与交互框纵向对齐），手机在交互下方 */
.mixer-desc{width:380px;flex:none;border:3px solid #000;background:#fff;overflow-y:auto;padding:14px 16px 20px;font-size:13px;line-height:1.85;letter-spacing:0.3px}
.mixer-desc p{margin-bottom:14px}
.mixer-desc .project-related{margin-top:24px}
.mixer-hud{position:absolute;top:10px;right:10px;display:flex;align-items:center;gap:8px;font-size:11px;letter-spacing:0.5px;z-index:3}
.btn-mixer-sm{font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase;border:2px solid #000;background:#fff;color:#000;padding:6px 10px;cursor:pointer}
.btn-mixer-sm:hover{background:#000;color:#fff}
#mixer-stop{display:none}
.mixer-center{position:absolute;inset:0;z-index:2;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.5)}
.btn-mixer{font-size:15px;font-weight:700;letter-spacing:2px;text-transform:uppercase;border:3px solid #000;background:#000;color:#fff;padding:14px 28px;cursor:pointer}
.btn-mixer:hover{background:#fff;color:#000}
.btn-mixer:disabled{opacity:.6;cursor:default}

@media(max-width:768px){
  .mixer-panel{flex-direction:column;height:auto;min-height:100dvh;padding:64px 12px 48px;gap:8px;overflow:visible;max-width:none;margin:0}
  .mixer-body{display:flex;flex-direction:column;flex:none;gap:8px}
  .mixer-header h2{font-size:15px}
  .mixer-stage{height:40dvh;flex:none}
  .mixer-desc{width:auto;flex:none;border:none;background:transparent;overflow:visible;padding:6px 2px 0;font-size:12.5px;line-height:1.85}
  .btn-mixer{font-size:13px;padding:12px 22px}
  .mixer-hud{top:8px;right:8px;gap:6px}
  .btn-mixer-sm{font-size:10px;padding:5px 8px}
}

/* ===== GALLERY LIGHTBOX ===== */
.lightbox{
  position:fixed;inset:0;z-index:200;
  display:none;
  align-items:center;justify-content:center;
  background:rgba(0,0,0,.92);
}
.lightbox.open{display:flex}
.lightbox img{
  max-width:92vw;max-height:88vh;
  object-fit:contain;
}
.lightbox-nav{
  position:absolute;top:50%;transform:translateY(-50%);
  width:48px;height:64px;
  background:transparent;color:#fff;
  border:none;cursor:pointer;
  font-size:40px;line-height:1;
  display:flex;align-items:center;justify-content:center;
}
.lightbox-nav:hover{background:rgba(255,255,255,.15)}
.lightbox-prev{left:8px}
.lightbox-next{right:8px}
.lightbox-close{
  position:absolute;top:16px;right:20px;
  width:44px;height:44px;
  background:transparent;color:#fff;
  border:none;cursor:pointer;
  font-size:32px;line-height:1;
}
.lightbox-close:hover{background:rgba(255,255,255,.15)}
/* 位置指示：网格化后可以从 21 张里的任意一张进入，没有「第几张」会迷路 */
.lightbox-count{
  position:absolute;bottom:16px;left:50%;transform:translateX(-50%);
  color:#fff;font-size:12px;letter-spacing:1px;
}

@media(max-width:768px){
  .lightbox-nav{width:40px;height:56px;font-size:32px}
  .lightbox-close{top:10px;right:14px;width:40px;height:40px;font-size:28px}
  .lightbox-count{bottom:10px;font-size:11px}
}

/* ===== 首屏布局选择（绘制前生效）=====
   六个布局面板默认全部隐藏，只有 <html data-layout="…"> 指定的那个显示。
   该属性由 project-template.html 末尾的同步内联脚本在首次绘制前写入。
   默认隐藏是失败安全的方向：属性没写上时最坏是空白，
   绝不会在 defer 脚本到达之前先闪出默认的 grid 样板布局（改动前的实际表现）。
   js/project.js 仍会用行内样式重设一遍显示，与本节规则不冲突。 */
.project-grid,.wwhbh-panel,.ecce-panel,.edge-panel,.gallery-panel,.mixer-panel{display:none}
html[data-layout="grid"]    .project-grid{display:grid}
html[data-layout="gallery"] .gallery-panel{display:flex}
html[data-layout="ecce"]    .ecce-panel{display:flex}
html[data-layout="edge"]    .edge-panel{display:flex}
html[data-layout="wwhbh"]   .wwhbh-panel{display:flex}
html[data-layout="mixer"]   .mixer-panel{display:flex}
