/* =========================================================
   心屿 · 蓝色系纸片主题
   tokens / 三套光线 / 基础排版 / 通用组件
   ========================================================= */

/* ---------- 1. 设计令牌 ---------- */
:root{
  /* 晴昼 */
  --paper:        #e9f0f7;
  --paper-hi:     #f8fbff;
  --paper-lo:     #dde9f3;
  --paper-edge:   #c2d6e8;
  --ink:          #16232f;
  --ink-soft:     #3c5468;
  --muted:        #7a93a9;
  --line:         #cddbe9;
  --line-dash:    #a9c4dd;

  --indigo:       #24618f;
  --teal:         #2f7d74;
  --iris:         #4f63a8;
  --sand:         #b3763c;
  --mist:         #8ab3d6;
  --rose:         #a95c6c;
  --seal:         #a83a35;
  --pencil:       #8b98a6;
  --accent:       var(--indigo);

  --tape:         rgba(138,179,214,.55);
  --tape-ink:     #22405c;

  --shadow-s:  0 1px 2px rgba(24,52,80,.09);
  --shadow-m:  0 1px 1px rgba(24,52,80,.05), 0 6px 14px -8px rgba(24,52,80,.42);
  --shadow-l:  0 2px 3px rgba(24,52,80,.07), 0 18px 38px -20px rgba(24,52,80,.48);
  --shadow-lift: 0 3px 6px rgba(24,52,80,.1), 0 28px 52px -24px rgba(24,52,80,.52);
  --hair: rgba(255,255,255,.62);

  /* 线只有两档身份，全站照这两个走：
     --rule-row 是同一列表里行与行之间压的一道发线（实、浅、1px）；
     --rule-seam 是卡片里换了话题的那道缝（铅笔虚线，2px，比正文重一点点）。
     一张卡里绝不两种混排，也不许两道叠着挨在一起 —— 那看着像忘了收工。 */
  --rule-row: 1px solid var(--line);
  --rule-seam: 2px dashed var(--line-dash);

  /* 身后那层：默认给渐变，不是光秃秃一张纸色。雪花的水色也在这儿，换主题就跟着换 */
  --bg-grad: linear-gradient(172deg,#f2f7fc 0%,#e3edf6 46%,#d5e4f1 100%);
  --bg-wash: color-mix(in srgb, var(--paper) 22%, transparent);
  --sky-flake:#7ea6c9; --sky-alpha:.5;

  --r-xs: 3px; --r-s: 7px; --r-m: 12px; --r-l: 18px;
  --maxw: 1220px;
  --gap: 24px;

  --font-body: "PingFang SC","Hiragino Sans GB","Microsoft YaHei",-apple-system,"Segoe UI",Roboto,sans-serif;
  --font-serif: "Songti SC","STSong","SimSun",Georgia,serif;
  --font-hand: "STXingkai","华文行楷","STKaiti","KaiTi","楷体","DFKai-SB",var(--font-serif);
  --font-mono: "JetBrains Mono","Cascadia Code",Consolas,"Courier New",monospace;

  /* 动效：所有交互都用这两条曲线，手感才统一 */
  --ease-ink:    cubic-bezier(.22,.78,.28,1);
  --ease-spring: cubic-bezier(.34,1.34,.44,1);
  --t-fast: .16s; --t: .26s; --t-slow: .5s;
}

/* 暮蓝 */
[data-theme="dusk"]{
  --paper:        #dee3ef;
  --paper-hi:     #eef1f8;
  --paper-lo:     #d3dae8;
  --paper-edge:   #b6c0d6;
  --ink:          #1f2536;
  --ink-soft:     #464f6b;
  --muted:        #7c86a4;
  --line:         #c3cbdc;
  --line-dash:    #a6b0c9;
  --indigo:       #35549a;
  --teal:         #3f7a8b;
  --iris:         #66619f;
  --sand:         #a97a46;
  --mist:         #98a6cd;
  --rose:         #94596d;
  --seal:         #9d3b3b;
  --pencil:       #8a90a4;
  --tape:         rgba(152,166,205,.5);
  --tape-ink:     #292d48;
  --hair: rgba(255,255,255,.5);
  --bg-grad: linear-gradient(172deg,#e9ecf5 0%,#d8dee9 50%,#c5cddf 100%);
  --bg-wash: color-mix(in srgb, var(--paper) 20%, transparent);
  --sky-flake:#9aa6cd; --sky-alpha:.5;
}

/* 夜航 */
[data-theme="night"]{
  --paper:        #101922;
  --paper-hi:     #192432;
  --paper-lo:     #0e1720;
  --paper-edge:   #28384a;
  --ink:          #e0ecf6;
  --ink-soft:     #a5bdd3;
  --muted:        #6b849b;
  --line:         #243548;
  --line-dash:    #324860;
  --indigo:       #6fa8dc;
  --teal:         #58a89b;
  --iris:         #8f9ce4;
  --sand:         #d2a066;
  --mist:         #7a9abe;
  --rose:         #c98290;
  --seal:         #c9544c;
  --pencil:       #6b849b;
  --accent:       var(--indigo);
  --tape:         rgba(111,168,220,.26);
  --tape-ink:     #e0ecf6;
  --hair: rgba(255,255,255,.07);
  --bg-grad: linear-gradient(172deg,#16222f 0%,#111c27 52%,#0a131d 100%);
  --bg-wash: color-mix(in srgb, var(--paper) 16%, transparent);
  --sky-flake:#eaf4ff; --sky-alpha:.62;
  --shadow-s:  0 1px 2px rgba(0,0,0,.5);
  --shadow-m:  0 1px 1px rgba(0,0,0,.32), 0 6px 14px -8px rgba(0,0,0,.85);
  --shadow-l:  0 2px 3px rgba(0,0,0,.36), 0 18px 38px -20px rgba(0,0,0,.95);
  --shadow-lift: 0 3px 6px rgba(0,0,0,.45), 0 28px 52px -24px rgba(0,0,0,1);
}

/* ---------- 2. 基础 ---------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--font-body); font-size:clamp(16px, 15.4px + .22vw, 16.8px); line-height:1.78;
  letter-spacing:.012em; overflow-x:hidden;
  font-kerning:normal; text-rendering:optimizeLegibility;
  transition:background var(--t-slow) var(--ease-ink), color var(--t-slow) var(--ease-ink);
}
h1,h2,h3,h4,h5{ margin:0; font-weight:700; line-height:1.35; letter-spacing:.01em; text-wrap:balance; }
p{ margin:0 0 .8em; text-wrap:pretty; }
a{ color:inherit; text-decoration:none; }
ul,ol{ margin:0; padding:0; list-style:none; }
button{ font:inherit; color:inherit; }
img{ max-width:100%; display:block; }
code{ font-family:var(--font-mono); font-size:.9em; }
::selection{ background:color-mix(in srgb,var(--mist) 70%, transparent); color:var(--ink); }

/* 细处：滚动条、焦点环 —— 只在这些地方看得出有没有用心 */
*{ scrollbar-width:thin; scrollbar-color:var(--paper-edge) transparent; }
*::-webkit-scrollbar{ width:9px; height:9px; }
*::-webkit-scrollbar-track{ background:transparent; }
*::-webkit-scrollbar-thumb{ background:var(--paper-edge); border-radius:var(--r-s); border:2px solid var(--paper); }
*::-webkit-scrollbar-thumb:hover{ background:var(--mist); }
:focus-visible{ outline:2px solid var(--iris); outline-offset:3px; }

/* 水纹 + 纸纹：背景不是光晕糊一团，是几笔水线
   纸纹不用 mix-blend-mode —— 一层全屏混合会把整份文档的「快速滚动」捷径打掉，
   每个滚动帧都要拿身后的内容重新混一次。灰噪点直接走 opacity，肉眼差别很小，想调淡调浓动这两个数就行。 */
.grain{
  position:fixed; inset:0; z-index:0; pointer-events:none; opacity:.3;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}
[data-theme="night"] .grain{ opacity:.16; }
.wash{
  position:fixed; inset:0; z-index:0; pointer-events:none;
  background:
    linear-gradient(180deg, color-mix(in srgb,var(--mist) 26%, transparent), transparent 34%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='74'%3E%3Cg fill='none' stroke='%237ea6c9' stroke-width='1.1' stroke-linecap='round' opacity='.5'%3E%3Cpath d='M0 18c20-11 40 11 60 0s40 11 60 0 40 11 60 0 40 11 60 0'/%3E%3Cpath d='M0 55c20-11 40 11 60 0s40 11 60 0 40 11 60 0 40 11 60 0'/%3E%3C/g%3E%3C/svg%3E");
  background-size:auto, 240px 74px;
  opacity:.5;
}
[data-theme="dusk"] .wash{ opacity:.42; }
[data-theme="night"] .wash{
  background:
    linear-gradient(180deg, rgba(111,168,220,.1), transparent 38%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='74'%3E%3Cg fill='none' stroke='%236fa8dc' stroke-width='1' stroke-linecap='round' opacity='.28'%3E%3Cpath d='M0 18c20-11 40 11 60 0s40 11 60 0 40 11 60 0 40 11 60 0'/%3E%3Cpath d='M0 55c20-11 40 11 60 0s40 11 60 0 40 11 60 0 40 11 60 0'/%3E%3C/g%3E%3C/svg%3E");
  background-size:auto, 240px 74px;
  opacity:.7;
}
.shell{ position:relative; z-index:1; max-width:var(--maxw); margin:0 auto; padding:0 22px 80px; }

/* 身后那一层：不铺图的时候是跟光线走的渐变，不是纯色一张 */
#bg{ position:fixed; inset:0; z-index:0; pointer-events:none; background:var(--paper); }
#bg[data-bg="theme"]{ background-image:var(--bg-grad); }
/* 铺图时只压很薄一层纸色：图要看得出来，卡片自己会负责把字撑住 */
#bg.is-img::after{ content:""; position:absolute; inset:0; background:var(--bg-wash); }

/* ---------- 铺了背景图的时候，让图真的看得见 ----------
   门牌是 .shell 的兄弟，#bg 又是 body 第一个元素，选不到后代 ——
   所以由 sky.js 往 <html> 上挂 has-bg-img / bg-frost 两个开关。 */
/* 水波和薄雾是纸站的打扮，压在画上就成了脏东西 */
.has-bg-img .wash{ display:none; }
.has-bg-img .grain{ opacity:.14; }
[data-theme="night"] .has-bg-img .grain{ opacity:.1; }
/* 卡片从实色纸底改成半透明，图从底下透上来一点。
   实度不再钉死在 72% —— 跟着「▦ 背景」里那条滑杆走（上面 .card 已经按 --veil 算了），
   这里只留边框和影子这两样：压在画上太重的描边会脏。 */
.has-bg-img .card:not(.flat){
  border-color: color-mix(in srgb, var(--paper-edge) 62%, transparent);
  box-shadow: var(--shadow-s), inset 0 1px 0 var(--hair);
}
/* 磨砂：想彻底看清图背后的形状再开。每滚一帧都要重新采样卡片身后那片，
   主页一万五千像素滚起来是会掉帧的 —— 所以默认关，颜色令牌那套不动。 */
.bg-frost .card:not(.flat){ backdrop-filter:blur(9px) saturate(1.06); -webkit-backdrop-filter:blur(9px) saturate(1.06); }
.bg-frost .masthead:not(.is-ghost){ backdrop-filter:blur(7px); -webkit-backdrop-filter:blur(7px); }
/* 飘着的雪和水珠：整屏一层 canvas，很淡，不接鼠标。门牌(40)和弹层(70)都压在它上面 */
#sky{ position:fixed; inset:0; z-index:3; pointer-events:none; }

/* ---------- 3. 门牌 ---------- */
.masthead{
  position:sticky; top:0; z-index:40;
  display:flex; align-items:center; gap:18px; flex-wrap:wrap;
  padding:12px 4px 8px; margin:0 -8px;
  /* 底色听「▦ 背景」里那条滑杆（--veil），和卡片同一个旋钮 —— 先前钉死在 97%，她拉到底也拉不动它。
     不给这条带子加磨砂：她要的就是身后那张图整张透上来，糊开一层就成雾了（2026-10-29 加过一次，当天撤）。
     省下的是真钱 —— sticky 元素上的 backdrop-filter 每滚一帧都要把身后整屏重模糊一次。 */
  background:color-mix(in srgb, var(--paper) calc(var(--veil,1) * 100%), transparent);
  border-bottom:1px solid var(--line);
  transition:box-shadow var(--t) var(--ease-ink), border-color var(--t) var(--ease-ink),
             background var(--t) var(--ease-ink);
}
.masthead.is-scrolled{ box-shadow:0 12px 26px -24px rgba(24,52,80,.75); border-bottom-color:var(--paper-edge); }
/* 浮在主页那整屏图上的那一段：纸色退干净，字换成图上的白。
   JS 只在跨过图底那一次动 class —— 滚动中途不碰样式。 */
.masthead.is-ghost{ background:transparent; border-bottom-color:transparent; }
.masthead.is-ghost.is-scrolled{ box-shadow:none; }
.masthead.is-ghost .brand{ --indigo:#eaf4ff; --paper-hi:rgba(12,26,42,.3); }
.masthead.is-ghost .brand-name{ color:#f4f9ff; text-shadow:0 1px 12px rgba(6,18,32,.6); }
.masthead.is-ghost .brand-sub{ color:rgba(244,249,255,.76); }
.masthead.is-ghost .nav-item{ color:rgba(244,249,255,.82); text-shadow:0 1px 10px rgba(6,18,32,.55); }
.masthead.is-ghost .nav-item:hover{ color:#fff; }
.masthead.is-ghost .nav-item.is-active{ color:#fff; }
.masthead.is-ghost .nav-ink{ background:linear-gradient(90deg, transparent, #f4f9ff 14%, #f4f9ff 86%, transparent); }
.masthead.is-ghost .btn{ background:rgba(10,22,36,.34); border-color:rgba(244,249,255,.3); color:#f4f9ff; box-shadow:none; }
.masthead.is-ghost .btn:hover{ background:rgba(10,22,36,.62); border-color:#f4f9ff; box-shadow:none; }
.masthead.is-ghost .tide{ opacity:0; }
.brand{ display:flex; align-items:center; gap:12px; margin-right:auto; min-width:0; }
.brand svg{ width:31px; height:31px; flex:none; transition:transform var(--t-slow) var(--ease-spring); }
.brand:hover svg{ transform:translateY(-2px) rotate(-5deg); }
.brand-name{ font-size:19px; font-family:var(--font-serif); letter-spacing:.14em; }
.brand-sub{ font-size:11.5px; color:var(--muted); letter-spacing:.08em; margin:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* 导航：目录式文字 + 一条会滑的墨线，每项前头一个描几笔的小图标 */
.nav{ position:relative; display:flex; gap:1px; flex-wrap:wrap; }
.nav-item{
  position:relative; z-index:1; display:inline-flex; align-items:center; gap:6px;
  padding:7px 9px 9px; font-size:13.5px; letter-spacing:.05em;
  color:var(--muted); border-radius:9px 9px 0 0;
  transition:color var(--t) var(--ease-ink), transform var(--t) var(--ease-ink);
}
.nav-ic{ width:14px; height:14px; flex:none; opacity:.66; transition:opacity var(--t) var(--ease-ink) }
.nav-item:hover{ color:var(--ink); transform:translateY(-1.5px); }
.nav-item:hover .nav-ic{ opacity:.9 }
.nav-item.is-active{ color:var(--accent); font-weight:700; }
.nav-item.is-active .nav-ic{ opacity:1 }
.nav-ink{
  position:absolute; left:0; bottom:0; height:2px; width:0; opacity:0; pointer-events:none;
  border-radius:var(--r-xs); background:linear-gradient(90deg, transparent, var(--accent) 14%, var(--accent) 86%, transparent);
  transform:translateX(0);
  transition:transform var(--t-slow) var(--ease-spring), width var(--t-slow) var(--ease-ink), opacity var(--t) var(--ease-ink);
}
.nav-ink.show{ opacity:1; }

.mast-actions{ display:flex; gap:8px; align-items:center; }
/* 「目录」只在窄屏出现：宽屏门牌 14 栏本来就全露着，多一枚按钮是给人添乱。
   挂 .mast-actions 是因为下面 .btn 也定 display —— 同权重它在后头会赢，这一条得压住它。 */
.mast-actions .toc-only{ display:none; }
.btn{
  display:inline-flex; align-items:center; gap:6px;
  padding:6px 14px; border-radius:var(--r-s); font-size:13px; cursor:pointer;
  background:var(--paper-hi); border:1px solid var(--line);
  box-shadow:var(--shadow-s), inset 0 1px 0 var(--hair);
  transition:transform var(--t) var(--ease-ink), box-shadow var(--t) var(--ease-ink),
             border-color var(--t) var(--ease-ink), background var(--t) var(--ease-ink), color var(--t);
}
/* 门牌按钮的图标那一截：<i> 默认是斜体，这些符号一斜就歪了。
   行高跟着文字走（不写死 1），不然只剩图标的「⌕」会比旁边矮一截。 */
.btn .ic{ font-style:normal; }
.btn:hover{ transform:translateY(-1.5px); box-shadow:var(--shadow-m), inset 0 1px 0 var(--hair); border-color:var(--paper-edge); }
.btn:active{ transform:translateY(0) scale(.985); box-shadow:var(--shadow-s); }
.btn.is-on{ background:var(--accent); color:var(--paper-hi); border-color:var(--accent); box-shadow:var(--shadow-m); }
.btn.solid{ background:var(--accent); color:var(--paper-hi); border-color:var(--accent); }
.btn.tiny{ padding:3px 10px; font-size:12px; border-radius:var(--r-s); }
.linkbtn{ border:none; background:none; cursor:pointer; padding:0; }

/* ---------- 4. 纸片卡片 ----------
   纯信息卡 hover 只换影子，不跟着抬 —— 全站都在飘就是模板感 */
.card{
  position:relative;
  /* 底色跟着「▦ 背景」里那条浮层透明度（--veil，sky.js 写在 :root 上）掺透明，
     身后的图才透得出来。字和边框不跟着淡 —— 淡了就读不掉了。 */
  background:linear-gradient(178deg,
    color-mix(in srgb,var(--paper-hi) calc(var(--veil,1) * 100%), transparent),
    color-mix(in srgb,var(--paper-lo) calc(var(--veil,1) * 100%), transparent));
  border:1px solid var(--paper-edge);
  border-radius:var(--r-m);
  box-shadow:var(--shadow-m), inset 0 1px 0 var(--hair);
  padding:22px 24px;
  transition:transform var(--t) var(--ease-ink), box-shadow var(--t) var(--ease-ink), border-color var(--t) var(--ease-ink);
}
.card:hover{ box-shadow:var(--shadow-l), inset 0 1px 0 var(--hair); border-color:var(--mist); }
.tilt-l{ transform:rotate(-.4deg); } .tilt-r{ transform:rotate(.5deg); }
.card.lift:hover{ transform:translateY(-4px); }
.tilt-l.lift:hover,.tilt-r.lift:hover{ transform:rotate(0deg) translateY(-4px); }
.card.flat{ background:none; border:none; box-shadow:none; padding:0; }
.card.flat:hover{ box-shadow:none; border-color:transparent; }

/* 稿纸：左边一道红 margin 线 + 三个装订孔，正文落在格子上 */
.sheet{ padding:26px 30px 22px 54px; border-radius:var(--r-s) var(--r-m) var(--r-m) var(--r-s); }
.sheet::before{
  content:""; position:absolute; left:40px; top:10px; bottom:10px; width:1px;
  background:linear-gradient(180deg, transparent, color-mix(in srgb,var(--rose) 48%, transparent) 10%, color-mix(in srgb,var(--rose) 48%, transparent) 90%, transparent);
}
.sheet::after{
  content:""; position:absolute; left:15px; top:0; bottom:0; width:11px; opacity:.5;
  background-image:radial-gradient(circle at 5.5px 5.5px, color-mix(in srgb,var(--ink) 26%, transparent) 3.3px, transparent 3.7px);
  background-repeat:repeat-y; background-size:11px 96px; background-position:0 48px;
}
@media (max-width:720px){
  .sheet{ padding:20px 16px 18px 34px; } .sheet::before{ left:24px; } .sheet::after{ left:7px; width:9px; }
  .run-slot{ display:none; }   /* 窄屏左边距只有 7px 空地，竖排那一枚挤不进，宁可不挂 */
}

/* 心帖那一卷：读到哪一页，装订边里这一枚跟着走到哪 —— 竖排几个字，不占正文一格。
   槽本身零高度（sticky 的容器是这张稿纸卡，所以纸读完它就跟着纸走没了，不会飘到下一篇）。 */
/* height 那句不是多余：竖排把「行高」变成了横向的栏宽、把「可用高度」当成了能排几个字的依据，
   而槽是 0 高 —— 不写出 max-content，Chrome 就把这四个字压回横排（实测 69×18 而不是 23×67）。
   left 负着走是因为槽在稿纸的正文框里，装订边（那 54px，含左边打孔那一道）在正文框外头。 */
.run-slot{ position:sticky; top:calc(var(--mast-h, 76px) + 20px); height:0; z-index:2; }
.run-head{ position:absolute; left:-26px; top:0; writing-mode:vertical-rl; white-space:nowrap;
  height:max-content;
  font-family:var(--font-hand); font-size:12.5px; letter-spacing:.34em; color:var(--pencil);
  opacity:.8; text-shadow:0 0 7px var(--paper-hi); }

.taped::before{
  content:""; position:absolute; top:-13px; left:50%; width:104px; height:26px;
  transform:translateX(-50%) rotate(-2.5deg);
  background:repeating-linear-gradient(45deg, var(--tape) 0 7px, rgba(255,255,255,.28) 7px 14px);
  border-left:1px solid rgba(255,255,255,.45); border-right:1px solid rgba(0,0,0,.06);
  box-shadow:0 2px 5px rgba(30,60,90,.18); opacity:.95;
}
.pinned .pin{
  position:absolute; top:-9px; width:17px; height:17px; border-radius:50%;
  background:radial-gradient(circle at 34% 32%, #ffffffa8, transparent 42%), var(--teal);
  box-shadow:0 3px 6px rgba(30,60,90,.4), inset 0 -2px 3px rgba(0,0,0,.18);
}

/* ---------- 5. 小节标题 ----------
   标题前一颗朱色小印，副标题用行楷写 —— 手写体是最快去掉模板感的办法 */
.sec-head{ display:flex; align-items:baseline; gap:12px; margin-bottom:17px; }
.sec-title{ position:relative; font-size:19.5px; font-family:var(--font-serif); letter-spacing:.1em; padding-left:14px; }
.sec-title::before{
  content:""; position:absolute; left:0; top:.44em; width:5px; height:5px;
  background:var(--seal); opacity:.8; transform:rotate(45deg); border-radius:1px;
}
.sec-sub{ font-family:var(--font-hand); font-size:15.5px; color:var(--pencil); letter-spacing:.04em; }
.sec-line{ flex:1; height:0; border-top:1px dashed var(--line-dash); }
.sec-tag{ font-size:11px; padding:2px 9px; border-radius:999px;
  background:var(--paper-lo); border:1px solid var(--line); color:var(--muted); white-space:nowrap;
  font-variant-numeric:tabular-nums; }

/* ---------- 6. 空位 ---------- */
.slot{
  color:var(--muted); font-style:normal;
  background:linear-gradient(180deg,transparent 62%, color-mix(in srgb,var(--mist) 42%, transparent) 0);
  border-bottom:1px dashed var(--line-dash);
  padding:0 4px; border-radius:var(--r-xs); cursor:text;
}
.slot::before{ content:"待填写"; opacity:.8; font-size:.92em; }
.slot-filled{ color:inherit; background:none; border-bottom:none; padding:0; cursor:auto; }
.slot-filled::before{ content:none; }
.ml,.ap-body,.note-body,.tl-text,.quote,.md{ white-space:pre-wrap; }
.quote{ font-family:var(--font-serif); font-size:15px; line-height:1.95; margin:0; }
.ml:not(.slot-filled),.ap-body:not(.slot-filled),.note-body:not(.slot-filled),
.tl-text:not(.slot-filled),.quote:not(.slot-filled){ min-height:1.7em; cursor:text; }
.ml:not(.slot-filled)::before,.ap-body:not(.slot-filled)::before,.note-body:not(.slot-filled)::before,
.tl-text:not(.slot-filled)::before,.quote:not(.slot-filled)::before{
  content:"点这里写点什么…"; color:var(--muted); opacity:.72; font-size:.92em;
}
[data-edit]{ transition:box-shadow .18s; }
body.is-editing [data-edit]{ box-shadow:0 0 0 2px color-mix(in srgb,var(--iris) 55%, transparent) inset; border-radius:var(--r-s); }
body.is-editing [data-edit]:hover{ background:color-mix(in srgb,var(--iris) 10%, transparent); }

/* ---------- 7. 布局 ----------
   侧栏固定靠左 320px，正文永远占宽栏 —— 按类名分配列，DOM 顺序随意 */
.layout{ display:grid; grid-template-columns:320px minmax(0,1fr); gap:var(--gap); align-items:start; }
.layout > .rail{ grid-column:1; grid-row:1; }
.layout > .stream{ grid-column:2; grid-row:1; min-width:0; }
.rail{ display:flex; flex-direction:column; gap:var(--gap); min-width:0; }
.rail-sticky{ position:sticky; top:76px; display:flex; flex-direction:column; gap:var(--gap); }
.stream{ display:flex; flex-direction:column; gap:var(--gap); min-width:0; }

/* 页眉：手帐的「第几页」，铅笔写的
   标题不是淡入，是「揭」—— 元素自己当那块布，clip-path 从下往上收，字从纸底下托上来。
   曲线用 expo-out（前四成就走完大半），所以是「唰」一下停住，不是慢慢飘。三件错开 60/160/260ms。 */
.page-head{ margin:30px 0 20px; }
.page-head::before{
  content:"第 " attr(data-page) " 页"; display:block; margin-bottom:6px;
  font-family:var(--font-hand); font-size:14.5px; color:var(--pencil);
  letter-spacing:.1em; transform:rotate(-.8deg); transform-origin:left;
}
html.enter .page-head::before{ animation:fade .5s var(--ease-ink) backwards; }
.page-title{
  font-family:var(--font-serif); font-size:clamp(28px,4vw,42px); line-height:1.15; letter-spacing:.03em;
}
html.enter .page-title{ animation:unveil .66s cubic-bezier(.16,1,.3,1) .06s backwards; }
.page-desc{ color:var(--muted); font-size:13.5px; margin:7px 0 0; letter-spacing:.05em; }
html.enter .page-desc{ animation:rise .46s cubic-bezier(.16,1,.3,1) .16s backwards; }
.page-desc code{ font-size:12px; color:var(--ink-soft); background:var(--paper-lo); padding:1px 5px; border-radius:var(--r-xs); }

/* ---------- 8. 页脚 ---------- */
/* 去处那一排：页脚、目录那页、404 用的是同一份 markup（core.js 的 placeLinks）。
   页脚里横着排、到窄屏自己折；目录里两栏摊开。不做抬起、不做图标底衬 —— 就是一行行字。 */
.place{
  display:inline-flex; align-items:center; gap:6px;
  color:var(--muted); text-decoration:none; font-size:12.5px; letter-spacing:.06em;
  transition:color var(--t-fast);
}
.place .nav-ic{ width:13px; height:13px; opacity:.55; }
.place:hover{ color:var(--accent); }
.place:hover .nav-ic{ opacity:.9; }
.place.is-here{ color:var(--accent); font-weight:700; }
.foot-places{ flex:1 1 100%; display:flex; flex-wrap:wrap; gap:8px 18px; padding-bottom:4px; }
.toc-grid{ display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:0 10px; padding:6px 0 2px; }
.toc-grid .place{ min-height:40px; font-size:14.5px; letter-spacing:.08em; border-bottom:1px dashed var(--line-dash); }
.place-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(96px, 1fr)); gap:10px 8px; }
.notfound{ text-align:left; }
.nf-go{ display:flex; gap:10px; margin-bottom:16px; }
.nf-hint{ font-size:12.5px; color:var(--muted); margin:0 0 10px; letter-spacing:.06em; }
.foot{
  margin-top:44px; padding:26px 8px 0; border-top:1px dashed var(--line-dash);
  display:flex; flex-wrap:wrap; gap:14px 26px; align-items:center; justify-content:space-between;
  font-size:12.5px; color:var(--muted);
}
.foot em{ font-family:var(--font-serif); font-style:italic; letter-spacing:.04em; }
/* 备案号是法规件（工信部要求首页标明并链到备案管理系统），所以跟着页脚那行字一样轻，
   只给一条稿纸上的虚线；悬停才扫实。不加底色、不抬起、不当按钮做。 */
.beian{
  color:inherit; text-decoration:none; letter-spacing:.04em;
  border-bottom:1px dashed var(--line-dash); padding-bottom:1px;
  transition:color var(--t-fast), border-bottom-style var(--t-fast);
}
.beian:hover,.beian:focus-visible{ color:var(--accent); border-bottom-style:solid; }
/* 阿里云过审通知原文要求「网站首页底部中间位置」放备案号，页脚那套 flex 是 space-between，
   单独一行占满才落得在中线上（公安备案号下来也挂这一行）。 */
.beian-row{ width:100%; text-align:center; }
/* 两个都是法规件，同一行并排；窄屏放不下自己折两行，居中不塌。 */
.beian-row .beian + .beian{ margin-left:18px; }
/* 数据来源角标：一眼看出当前读的是本地文件还是数据库，主人和访客要长得不一样。 */
.datasrc{
  font-family:var(--font-mono); font-size:11px; letter-spacing:.02em;
  padding:2px 8px; border-radius:999px; border:1px solid var(--paper-edge);
  background:var(--paper-lo); color:var(--ink-soft); white-space:nowrap;
}
.datasrc[data-state="file"]{ border-style:dashed; color:var(--pencil); }
.datasrc[data-state="db-empty"]{ border-color:var(--sand); color:var(--sand); }
.datasrc[data-state="db-mine"]{ background:rgba(47,125,116,.12); border-color:var(--teal); color:var(--teal); }
.datasrc[data-state="db-anon"]{ background:rgba(138,179,214,.18); border-color:var(--mist); }

/* ---------- 9. 角标 ---------- */
.corner{ position:fixed; right:18px; bottom:18px; z-index:50; display:flex; flex-direction:column; gap:7px; align-items:center; }
.corner .pct,.corner .top{
  width:40px; height:40px; border-radius:var(--r-m); display:grid; place-items:center;
  background:var(--paper-hi); border:1px solid var(--paper-edge);
  box-shadow:var(--shadow-m), inset 0 1px 0 var(--hair);
}
.corner .pct{ font-size:11px; font-variant-numeric:tabular-nums; color:var(--ink-soft); font-family:var(--font-mono); }
.corner .top{ cursor:pointer; font-size:15px; color:var(--ink-soft);
  transition:transform var(--t) var(--ease-spring), color var(--t), opacity var(--t-slow); }
.corner .top:hover{ transform:translateY(-3px); color:var(--accent); }
.corner .top:active{ transform:translateY(-1px) scale(.95); }
/* 右下角的「稿」：页面上改了还没导出时亮起来 */
.corner .draftbtn{
  height:25px; padding:0 10px; border-radius:999px; display:grid; place-items:center; cursor:pointer;
  font-size:11.5px; letter-spacing:.03em; font-variant-numeric:tabular-nums;
  background:var(--paper-hi); border:1px solid var(--paper-edge); color:var(--muted);
  box-shadow:var(--shadow-m), inset 0 1px 0 var(--hair);
  transition:transform var(--t) var(--ease-spring), color var(--t), border-color var(--t);
}
.corner .draftbtn:hover{ transform:translateY(-2px); color:var(--accent); }
.corner .draftbtn.is-dirty{ color:var(--seal); border-color:color-mix(in srgb,var(--seal) 42%, var(--paper-edge)); }

/* ---------- 10. 通用小件 ---------- */
.chips{ display:flex; flex-wrap:wrap; gap:8px; }
.chip{ font-size:12.5px; padding:3px 11px; border-radius:999px;
  background:var(--paper-lo); border:1px solid var(--line); color:var(--ink-soft);
  transition:transform var(--t) var(--ease-spring), border-color var(--t), color var(--t), background var(--t); cursor:pointer; }
.chip:hover{ transform:translateY(-2px); border-color:var(--accent); color:var(--accent); }
.chip.on{ background:var(--accent); color:var(--paper-hi); border-color:var(--accent); }

/* 层级导航（详情页顶上那一行）：分隔不用千篇一律的 ‹ › 或斜杠，落一枚空心邮戳 ——
   淡墨的小虚线圈，正好和稿纸的铅笔语言一路。整行替掉以前那个「← 回手帐列表」的药丸按钮。 */
.trail{ display:flex; flex-wrap:wrap; align-items:center; gap:7px; margin-bottom:15px;
  font-size:12.5px; color:var(--muted); letter-spacing:.03em; }
.trail a{ color:var(--ink-soft); text-decoration:none; border-bottom:1px solid transparent;
  transition:color var(--t-fast), border-color var(--t-fast); }
.trail a:hover{ color:var(--accent); border-bottom-color:var(--accent); }
.trail .stamp{ width:9px; height:9px; border-radius:50%; border:1px dashed var(--line-dash); flex:none; }
.trail .here{ font-family:var(--font-serif); color:var(--ink); }
/* 筛选那一排（相册的专辑、画集的标签、笔记房的分类/月份/标签）跟着手帐 .tab 的语言走：
   字 + 底下一条墨线，不涂成一排实心药丸 —— 一排涂色胶囊是最"后台界面"的东西。
   不能点的那些签子（.chips 里的标签）还是药丸，那是贴在物件上的小签，不是控件。 */
.albums .chip, .kb-pick .chip{ background:none; border-color:transparent; padding:4px 10px; color:var(--muted) }
.albums .chip:hover, .kb-pick .chip:hover{ transform:none; color:var(--accent);
  background:color-mix(in srgb,var(--paper-lo) 62%, transparent) }
.albums .chip.on, .kb-pick .chip.on{ background:none; color:var(--accent); font-weight:700;
  box-shadow:inset 0 -2px 0 var(--accent) }
.kv{ display:grid; grid-template-columns:auto 1fr; gap:9px 16px; font-size:14px; }
.kv dt{ color:var(--muted); font-size:12.5px; letter-spacing:.06em; white-space:nowrap; }
.kv dd{ margin:0; }
.num{ font-family:var(--font-serif); font-variant-numeric:tabular-nums; }
/* 装订记里那一枚纸色：色号旁边给一块真能看的，字和色对得上 */
.sw{ display:inline-block; width:11px; height:11px; border-radius:var(--r-xs);
  border:1px solid var(--paper-edge); vertical-align:-1px; margin-right:4px; }
.empty{
  padding:26px 18px; text-align:center; color:var(--muted); font-size:13.5px;
  border:1px dashed var(--line-dash); border-radius:var(--r-m); background:color-mix(in srgb,var(--paper-lo) 55%, transparent);
}
.empty b{ display:block; font-family:var(--font-serif); font-size:15px; color:var(--ink-soft); margin-bottom:4px; }
/* 筛空了是另一回事：东西在，只是她刚打的那个词不命中。不画虚线框也不放小兽（那是「还没有」的说法），
   就一行实说 + 一枚真能点回去的按钮。 */
.no-hit{ display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:6px 12px;
  padding:14px 14px; font-size:13.5px; color:var(--muted); letter-spacing:.02em;
  border-radius:var(--r-s); background:color-mix(in srgb,var(--paper-lo) 45%, transparent); }
.no-hit .btn{ margin-left:2px; }
/* 计数和日期走同一档：数字等宽，翻页 / 打卡时位数一变不会把整行挤得跳一下 */
.post-meta, .kb-item-m, .jar-count, .photo-date, .sb-time, .gb-date, .log-items li{ font-variant-numeric:tabular-nums; }
.mono{ font-family:var(--font-mono); font-size:12.5px; }
.dim{ color:var(--muted); }
/* 元信息前的小标签：用汉字，不用表情 */
.meta-k{ font-style:normal; color:var(--muted); opacity:.72; margin-right:4px; letter-spacing:.08em; }

/* markdown 正文 —— 长文用宋体排，像文集而不像后台页面；首字下沉一格。
   2.05 倍行距在 16.5px 上其实松得发散（一行看不到头就断了），收到 1.85，字号跟着视口走。 */
.md-body{ font-family:var(--font-serif); font-size:clamp(16.5px, 15.8px + .25vw, 18px); line-height:1.85; letter-spacing:.02em; max-width:42em; color:var(--ink); }
.md-body > p:first-child::first-letter{
  float:left; font-size:2.7em; line-height:.92; padding:.06em .12em 0 0;
  color:var(--indigo); font-weight:700;
}
.md-body h2{ font-size:20px; margin:32px 0 13px; font-family:var(--font-serif); letter-spacing:.06em;
  padding-left:11px; border-left:3px solid var(--indigo); }
.md-body h3{ font-size:18px; margin:36px 0 13px; font-family:var(--font-serif); letter-spacing:.16em;
  padding-bottom:5px; border-bottom:1px dashed var(--line-dash); }
.md-body h4{ font-size:16px; margin:20px 0 8px; color:var(--ink-soft); }
.md-body p{ margin:0 0 18px; white-space:pre-wrap; }  /* 她连打两个空格的地方就是换气，别让浏览器吃掉 */
.md-body p:last-child{ margin-bottom:0; }
.md-body ul{ margin:0 0 14px; font-family:var(--font-body); font-size:.9em; line-height:1.75; }
.md-body ul li{ padding-left:18px; position:relative; }
.md-body ul li::before{ content:""; position:absolute; left:2px; top:11px; width:6px; height:6px;
  border-radius:50%; background:var(--mist); }
.md-body ol{ list-style:decimal; padding-left:22px; margin:0 0 14px; font-family:var(--font-body); font-size:.9em; }
.md-body blockquote{ margin:0 0 16px; padding:10px 16px; border-left:3px solid var(--teal);
  background:var(--paper-lo); border-radius:0 var(--r-s) var(--r-s) 0; color:var(--ink-soft); font-style:normal; }
.md-body code{ font-family:var(--font-mono); background:var(--paper-lo); padding:1px 6px; border-radius:var(--r-xs); border:1px solid var(--line); font-size:.86em; }
.md-body pre{ background:var(--paper-lo); border:1px solid var(--line); border-radius:var(--r-s);
  padding:14px 16px; overflow-x:auto; margin:0 0 14px; }
.md-body pre code{ background:none; border:none; padding:0; }
.md-body a{ color:var(--accent); border-bottom:1px dashed var(--accent); transition:color var(--t-fast), border-color var(--t-fast); }
.md-body a:hover{ color:var(--seal); border-bottom-style:solid; }
.md-body hr{ border:none; border-top:1px dashed var(--line-dash); margin:24px 0; }
.md-body img{ border-radius:var(--r-s); margin:12px 0; box-shadow:var(--shadow-m); }
/* 站内双链：和站外链接分得开 —— 一条点线，颜色走水绿 */
.md-body a.xlink{ color:var(--teal); border-bottom-style:dotted; border-bottom-color:color-mix(in srgb,var(--teal) 52%, transparent); }
.md-body a.xlink:hover{ color:var(--seal); border-bottom-style:solid; }

/* 表格：笔记里七成是参数对照表，窄屏必须能横着滚，不能把字压成一列 */
.tbl-wrap{ overflow-x:auto; margin:0 0 18px; border:1px solid var(--line); border-radius:var(--r-s);
  background:color-mix(in srgb,var(--paper-hi) 55%, transparent); }
.tbl{ border-collapse:collapse; width:100%; font-family:var(--font-body); font-size:13.5px; line-height:1.75; }
.tbl th,.tbl td{ padding:7px 12px; text-align:left; vertical-align:top;
  border-bottom:1px solid var(--line); border-right:1px dashed var(--line-dash); }
.tbl th{ background:var(--paper-lo); color:var(--ink-soft); font-weight:700; white-space:nowrap; letter-spacing:.03em; }
.tbl tr:last-child td{ border-bottom:none; }
.tbl th:last-child,.tbl td:last-child{ border-right:none; }
.tbl tbody tr:hover{ background:color-mix(in srgb,var(--mist) 13%, transparent); }

/* 代码块：整块铺深（和 Obsidian 里看到的一致），顶上那条放语言、行数和复制 */
.code{ --code-bg:#14212f; --code-line:#26374a; --code-fg:#dcebf7; --code-dim:#8fb0cc;
  position:relative; margin:0 0 18px; border:1px solid var(--code-line); border-radius:var(--r-s);
  background:var(--code-bg); box-shadow:var(--shadow-m); overflow:hidden; }
[data-theme="night"] .code{ --code-bg:#0b1520; --code-line:#22344a; }
.code > figcaption{ display:flex; align-items:center; gap:10px; padding:5px 10px;
  background:color-mix(in srgb,var(--code-line) 52%, var(--code-bg)); border-bottom:1px solid var(--code-line);
  font-family:var(--font-mono); font-size:11.5px; color:var(--code-dim); letter-spacing:.04em; }
.code-lang{ color:color-mix(in srgb,var(--code-fg) 88%, transparent); }
.code-n::before{ content:"·"; margin-right:10px; opacity:.5; }
.code-copy{ margin-left:auto; font:inherit; color:var(--code-dim); background:transparent;
  border:1px solid var(--code-line); border-radius:var(--r-s); padding:1px 9px; cursor:pointer;
  transition:color var(--t-fast), border-color var(--t-fast), background var(--t-fast); }
.code-copy:hover{ color:var(--code-fg); border-color:var(--code-dim); background:color-mix(in srgb,var(--code-line) 45%, transparent); }
.code pre{ margin:0; padding:12px 14px; border:none; border-radius:0; background:none;
  color:var(--code-fg); font-family:var(--font-mono); font-size:13px; line-height:1.66;
  overflow:auto; white-space:pre; }
.code pre code{ background:none; border:none; padding:0; font-size:inherit; color:inherit; }
/* 长代码折起来只留 230px，里面还能滚 —— 一屏命令历史会把整篇笔记顶下去 */
.code.is-long:not(.open) pre{ max-height:230px; }
.code-more{ display:block; width:100%; font:inherit; font-size:12px; padding:6px 10px; cursor:pointer;
  color:var(--code-dim); background:color-mix(in srgb,var(--code-line) 40%, var(--code-bg));
  border:none; border-top:1px solid var(--code-line); transition:color var(--t-fast), background var(--t-fast); }
.code-more:hover{ color:var(--code-fg); background:color-mix(in srgb,var(--code-line) 62%, var(--code-bg)); }
.code:not(.is-long) pre{ max-height:none; }

/* mermaid：站上没有渲染引擎，把定义折起来 —— 至少能看清她画的是什么 */
details.mm{ margin:0 0 18px; border:1px dashed var(--line-dash); border-radius:var(--r-s);
  background:color-mix(in srgb,var(--paper-lo) 55%, transparent); }
details.mm > summary{ cursor:pointer; list-style:none; padding:8px 12px; font-size:12.5px; color:var(--ink-soft); font-family:var(--font-body); }
details.mm > summary::-webkit-details-marker{ display:none; }
details.mm > summary::before{ content:"▸"; display:inline-block; margin-right:8px; transition:transform .2s var(--ease-ink); }
details.mm[open] > summary::before{ transform:rotate(90deg); }
details.mm pre{ margin:0; border:none; border-top:1px dashed var(--line-dash); border-radius:0; background:none;
  color:var(--ink-soft); font-size:12.5px; }

/* 待办勾：Obsidian 里的 - [x] */
.md-body li.todo{ padding-left:2px; }
.md-body li.todo::before{ display:none; }
.todo-tick{ display:inline-grid; place-items:center; width:16px; height:16px; margin-right:8px;
  vertical-align:-3px; border-radius:var(--r-xs); border:1px solid var(--line-dash);
  background:var(--paper-hi); color:transparent; font-size:11px; font-family:var(--font-body); }
.todo-tick.on{ background:var(--teal); border-color:var(--teal); color:#f5fbfa; }
/* 锚点跳过去别被 sticky 的门牌压住半行 —— 门牌高度是 core.js 现场量的，手机上比桌面高一截 */
.md-body h2[id],.md-body h3[id],.md-body h4[id],.md-body h5[id]{ scroll-margin-top:calc(var(--mast-h, 76px) + 16px); }

/* ---------- 11. 弹层 ---------- */
.mask{
  position:fixed; inset:0; z-index:70; display:none; place-items:center; padding:24px;
  background:color-mix(in srgb, #0c1a28 62%, transparent); backdrop-filter:blur(5px);
}
.mask.show{ display:grid; animation:maskIn var(--t) var(--ease-ink); }
@keyframes maskIn{ from{ opacity:0 } to{ opacity:1 } }
.dialog{
  background:var(--paper-hi); border:1px solid var(--paper-edge); border-radius:var(--r-l);
  box-shadow:var(--shadow-l), inset 0 1px 0 var(--hair); max-width:min(720px,92vw); width:100%; padding:22px;
  max-height:86vh; max-height:86dvh; overflow:auto; animation:popIn .34s var(--ease-spring) backwards;
}
@keyframes popIn{ from{ opacity:0; transform:translateY(14px) scale(.97) } to{ opacity:1; transform:none } }
.search-box{
  width:100%; padding:11px 14px; font:inherit; font-size:15px; color:var(--ink);
  background:var(--paper-lo); border:1px solid var(--line); border-radius:var(--r-s); outline:none;
  transition:border-color var(--t) var(--ease-ink), box-shadow var(--t) var(--ease-ink), background var(--t);
}
.search-box:focus{ border-color:var(--accent); background:var(--paper-hi); box-shadow:0 0 0 3px color-mix(in srgb,var(--iris) 20%, transparent); }
.search-hit{ display:block; padding:10px 12px; border-radius:var(--r-s); cursor:pointer;
  transition:background var(--t-fast), transform var(--t) var(--ease-ink); }
.search-hit:hover{ background:var(--paper-lo); transform:translateX(4px); }
.search-hit.is-on{ background:var(--paper-lo); box-shadow:inset 3px 0 0 var(--accent); transform:translateX(4px); }
.search-hit b{ display:block; font-size:14.5px; }
.search-hit span{ font-size:12px; color:var(--muted); }

/* ---------- 12. 响应式 ---------- */
@media (max-width:1080px){
  .layout{ grid-template-columns:minmax(0,1fr); }
  .layout > .rail, .layout > .stream{ grid-column:auto; grid-row:auto; }
  .rail-sticky{ position:static; }
}
@media (max-width:720px){
  .shell{ padding:0 14px 60px; }
  .card{ padding:18px 16px; }
  .brand-sub{ display:none; }
  /* 门牌收拢成两行：品牌 + 一排纯图标按钮第一行，导航第二行。
     sticky 的门牌是手机上最贵的一屏高度（以前 182px，占掉 390×844 的五分之一），
     --mast-h 由 core.js 现场量，hero 那几张整屏图会自己跟着缩，不用再动 JS。 */
  .masthead{ gap:8px 10px; padding:7px 4px 4px; }
  .brand{ gap:9px; }
  .brand svg{ width:26px; height:26px; }
  .brand-name{ font-size:17px; letter-spacing:.1em; }
  .mast-actions{ gap:5px; flex:none; }
  .mast-actions .toc-only{ display:inline-flex; }
  /* 图标按钮：文字收进 title，只留 ▦ ☾ ✎ ⚷ —— 窄屏上「背景」两个字换来的宽度不值 */
  .mast-actions .lbl{ display:none; }
  .mast-actions .btn{ flex:none; width:40px; height:40px; padding:0; justify-content:center; }
  .mast-actions .btn .ic{ font-size:17px; }
  .nav{ order:3; width:100%; overflow-x:auto; flex-wrap:nowrap; padding-bottom:0; scrollbar-width:none; }
  .nav::-webkit-scrollbar{ display:none; }
  /* 行高收掉是这里的重点：默认 1.85 的正文行距套在 13px 的页签上，白送 7px 空的。
     省下来的高度还给内容 —— 手机上门牌每少 1px，读的那屏就多 1px。 */
  .nav-item{ white-space:nowrap; padding:10px 9px 9px; font-size:13px; line-height:1.35; }
  /* 全站输入框以前是 13.3–15.5px，iOS 一看字号小于 16 就自动把整页放大，
     打完字还不缩回去 —— 手机上每次写字都得先把页面挪回来。窄屏一律抬到 16px。
     勾选、单选、滑杆不改：它们不弹键盘，16px 反而碍事。 */
  :is(input, textarea, select):not([type=checkbox]):not([type=radio]):not([type=range]){ font-size:16px }
}
/* 320 那一档（iPhone SE 一代、老安卓）：五个 40 的图标加上「心屿」，刚好差三四个像素
   就挤回三行 —— 图标间隙和字距各收一点，门牌保住两行。 */
@media (max-width:380px){
  .masthead{ gap:8px 6px; }
  .brand{ gap:7px; }
  .brand-name{ font-size:16px; letter-spacing:.06em; }
  .mast-actions{ gap:3px; }
}
/* ---------- 12b. 触屏：命中区垫到指头大小 ----------
   这些控件是照着鼠标做的：30px 的 chip、28px 的播放键，指针只有 1px 准头所以够用，
   指头不行。只加 padding、字号一律不动 —— 字已经够小，放大只会把行挤回两行。
   鼠标能悬停的机器上完全不生效，桌面那套紧凑排版一点没变。 */
@media (hover:none){
  .btn:not(.tiny){ min-height:40px; }
  .btn.tiny{ min-height:38px; padding:8px 12px; }
  .chip{ padding:8px 14px; }
  .brand{ min-height:40px; }
  .nav-item{ padding:12px 9px 11px; }
  .search-hit{ padding:14px 12px; }
  .corner .draftbtn{ height:36px; }
  /* 登录那张脸：字太小 iPhone 一聚焦就把整页放大；底下那行「注册一个名字」是行内链接，指头点不中 */
  .gate-fld input{ font-size:16px; }
  .gate-to{ padding:9px 8px; margin:-9px -8px; }
  /* 层级导航那几个字是行内链接，本体只有 12.5px 高 —— 指头点不中。透明地往外撑一圈，字的位置不动。 */
  .trail a{ padding:11px 3px; margin:-11px -3px; }
}
/* ---------- 13. 动效 ----------
   只用 keyframes + animation-fill-mode:backwards：
   动画被禁掉/浏览器不跑动画时，内容本身仍是可见的最终状态，不会白屏 */
@keyframes rise{ from{ opacity:0; transform:translateY(15px) } to{ opacity:1; transform:none } }
@keyframes fade{ from{ opacity:0 } to{ opacity:1 } }
@keyframes unfold{ from{ opacity:0; clip-path:inset(0 0 100% 0) } to{ opacity:1; clip-path:inset(0 0 0 0) } }
/* 揭字：只有下边那一道在动（top/left/right 都贴着框），所以看不到「被剪」，只看到字升上来。
   末尾 inset(0 0 0 0) 是终态，等于不裁；动画被 reduce 掐掉时看到的就是那行标题本身。 */
@keyframes unveil{ from{ clip-path:inset(0 0 100% 0); transform:translateY(.45em) } to{ clip-path:inset(0 0 0 0); transform:none } }
@keyframes cardIn{ from{ opacity:0; transform:translateY(18px) } to{ opacity:1; transform:none } }
/* 入场这一整套只在 html.enter 挂着时跑：首开那一页、以及不认识 View Transition 的引擎切页时。 */
html.enter #view{ animation:fade .22s var(--ease-ink); }
/* 页面切换：只交叠透明度，老那页 .09 秒退、新那页 .2 秒进。
   以前这里两边都挂着整屏 filter:blur(4px/8px)，.46 秒 —— 那是把整屏（连带开屏那张大图、身后那层
   背景、纸纹）每帧重画一遍，她的机器上直接掉帧，看着就是「闪一下、卡住了」。
   现在这两个伪元素上只剩透明度：合成器拿两张现成的纹理调个 alpha，跟不过渡一样便宜。
   入场动画（下面那批 cardIn / unveil）由 html.enter 管，切页时 core.js 把它摘掉 ——
   快照那一刻新页面必须已经是摊好的样子，否则叠出来的是一屏空白。 */
::view-transition-old(root){ animation:xyOut .07s ease both }
::view-transition-new(root){ animation:xyIn .18s var(--ease-ink) both }
@keyframes xyOut{ from{ opacity:1 } to{ opacity:0 } }
@keyframes xyIn{ from{ opacity:0; transform:translateY(10px) } to{ opacity:1; transform:none } }
@keyframes xyPlainOut{ from{ opacity:1 } to{ opacity:0 } }
@keyframes xyPlainIn{ from{ opacity:0 } to{ opacity:1 } }
/* 跟手的墨点：一层不接点击的纸。圈慢（一帧追 17%）、点快（40%），所以移动时两者错开，
   停下来才收在同一处。is-hot 那一档是 JS 一路插值出来的 --hot，长大和洇墨都 smooth。
   原生光标留着没关 —— 她要在正文里选字。 */
.inkcur{ position:fixed; left:0; top:0; z-index:60; pointer-events:none; --hot:0; opacity:0; transition:opacity .2s var(--ease-ink) }
.inkcur.is-live{ opacity:1 }
.ic-ring{ position:absolute; left:0; top:0; width:26px; height:26px; border-radius:50%;
  border:1px solid color-mix(in srgb,var(--ink) calc((34 + var(--hot) * 30) * 1%),transparent);
  background:color-mix(in srgb,var(--ink) calc(var(--hot) * 7 * 1%),transparent) }
.ic-dot{ position:absolute; left:0; top:0; width:5px; height:5px; border-radius:50%;
  background:color-mix(in srgb,var(--ink) calc((52 + var(--hot) * 34) * 1%),transparent) }
@media (hover:none){ .inkcur{ display:none } }
/* 减弱动效：糊和位移这两样收掉，换页只留透明度交错。
   「该动的都动」默认是开着的（core.js 的 alive，挂在 html.is-alive），开着的时候这一整块都不生效 ——
   她那台机器常年报系统 reduce，整块无条件生效的话站就是死的，她的原话是「我没说减少动态效果啊」。
   她把那一枚点掉，才回到这里：只留透明度，位移和翻页那一下的动静全收掉。 */
@media (prefers-reduced-motion:reduce){
  html:not(.is-alive)::view-transition-old(root){ animation:xyPlainOut .07s ease both }
  html:not(.is-alive)::view-transition-new(root){ animation:xyPlainIn .16s ease both }
  html.enter:not(.is-alive) .page-title{ animation:xyPlainIn .3s var(--ease-ink) backwards !important }
  html.enter:not(.is-alive) .page-desc, html.enter:not(.is-alive) .page-head::before{ animation:xyPlainIn .34s var(--ease-ink) backwards !important }
  html.enter:not(.is-alive) .stream > *, html.enter:not(.is-alive) .rail-sticky > *,
  html.enter:not(.is-alive) .post-list > *, html.enter:not(.is-alive) .tiles > *,
  html.enter:not(.is-alive) .photos > *, html.enter:not(.is-alive) .nine-list > *,
  html.enter:not(.is-alive) .kb-month > *{
    animation:xyPlainIn .34s var(--ease-ink) backwards !important }
}
html.enter .stream > *, html.enter .rail-sticky > *, html.enter .post-list > *, html.enter .tiles > *,
html.enter .photos > *, html.enter .nine-list > *, html.enter .kb-month > *{
  animation:cardIn .52s cubic-bezier(.16,1,.3,1) backwards;
  animation-delay:calc(var(--i, 0) * 40ms);
}
/* 大数字翻牌：一位一张牌往下落。perspective 写在 transform 里，不用给父级加；
   终态就是「没有 transform」，所以 reduce 把动画掐掉时看到的就是那个数本身，不会翻成空白 */
.flip{ display:inline-block; font-style:normal; }
html.enter .flip{
  animation:flap .44s var(--ease-ink) backwards;
  animation-delay:calc(var(--i, 0) * 60ms); }
@keyframes flap{ 0%{ transform:perspective(240px) rotateX(78deg) translateY(-.08em); opacity:.2 } 55%{ opacity:1 } to{ transform:none } }
.post-title{ position:relative; }
.post-title::after{
  content:""; position:absolute; left:0; right:100%; bottom:-3px; height:1px;
  background:var(--accent); transition:right var(--t-slow) var(--ease-ink);
}
.post:hover .post-title::after{ right:0; }
details.src[open] > .ml{ animation:unfold .34s var(--ease-ink); }

/* ---------- 14. 潮线与扁舟：滚动到哪，船就划到哪 ----------
   交给原生滚动驱动动画（animation-timeline），跑在合成器上：以前每滚一格 JS 就往 :root
   写一次 --p，等于全文档重算样式，而潮线的 width、扁舟的 left 又都是要重排的几何量。
   不支持的老引擎走下面那套 --p 兜底写法（这时才需要 JS 每帧写 --p）。 */
.tide{ position:absolute; left:0; right:0; bottom:-1px; height:14px; pointer-events:none; z-index:2;
  container-type:inline-size; }
.tide::before{
  content:""; position:absolute; left:0; bottom:0; height:2px; width:100%; border-radius:var(--r-xs);
  background:linear-gradient(90deg, color-mix(in srgb,var(--mist) 45%, transparent), var(--accent));
  transform-origin:left center; transform:scaleX(var(--p, 0));
}
.tide-boat{ position:absolute; bottom:2px; left:0; transform:translateX(calc(var(--p, 0) * (100cqw - 100%))); }
.tide-boat svg{ display:block; width:26px; height:16px; animation:bob 3.6s ease-in-out infinite; }
@keyframes bob{ 0%,100%{ transform:translateY(0) rotate(-1.6deg) } 50%{ transform:translateY(-2.5px) rotate(2deg) } }
@keyframes tideRise{ from{ transform:scaleX(0) } to{ transform:scaleX(1) } }
@keyframes sail{ from{ transform:translateX(0) } to{ transform:translateX(calc(100cqw - 100%)) } }
@supports (animation-timeline:scroll()){
  .tide::before{ animation:tideRise linear both; animation-timeline:scroll(root block); }
  .tide-boat{ animation:sail linear both; animation-timeline:scroll(root block); }
  /* 「该动的都动」默认开着，这两条不用例外；她把那一枚点掉时，下面那条 reduce 兜底
     会把动画掐了、--p 钉在 .62 —— 潮线静止在六成，两边都不会「划到别处去」。 */
}

/* ---------- 15. 落款 / 印章 / 眉批 ---------- */
.colophon{
  display:flex; align-items:flex-end; justify-content:space-between; gap:20px; flex-wrap:wrap;
  margin-top:28px; padding-top:16px; border-top:1px dashed var(--line-dash);
}
.colophon .sign{ font-family:var(--font-hand); font-size:24px; line-height:1.15; color:var(--ink-soft); letter-spacing:.05em; }
.colophon .where{ font-size:12.5px; color:var(--muted); font-family:var(--font-serif); letter-spacing:.1em; margin-top:3px; }
.seal{
  position:relative; flex:none; width:50px; height:50px; display:grid; place-items:center;
  color:var(--seal); border:2px solid var(--seal); border-radius:var(--r-s); transform:rotate(-8deg);
  font-family:var(--font-serif); font-size:14px; line-height:1.05; text-align:center; letter-spacing:.02em;
  opacity:.85; box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--seal) 26%, transparent);
}
html.enter .seal{ animation:stamp .5s var(--ease-spring) backwards .35s; }
@keyframes stamp{ from{ opacity:0; transform:rotate(-24deg) scale(1.5) } 60%{ opacity:.95 } to{ opacity:.85; transform:rotate(-8deg) scale(1) } }
.seal:hover{ transform:rotate(-8deg) scale(1.06); transition:transform var(--t) var(--ease-spring); }

/* 眉批：写在自己本子边上的话，铅笔字 */
.margin-note{
  margin:0 0 20px; padding:1px 0 1px 14px;
  font-family:var(--font-hand); font-size:17.5px; line-height:1.6; color:var(--pencil); letter-spacing:.04em;
  border-left:2px solid color-mix(in srgb,var(--sand) 52%, transparent);
}
/* 还没写的眉批不占地方，只在编辑模式露出来给她填 */
body:not(.is-editing) .margin-note.is-blank{ display:none; }

/* ---------- 16. 手写句 ----------
   她自己写的句子一律用行楷，和界面文字分开 */
.quote{ font-family:var(--font-hand); font-size:21px; line-height:1.7; color:var(--ink-soft); letter-spacing:.03em; }
.id-motto{ font-family:var(--font-hand); font-size:17px; }
.hand{ font-family:var(--font-hand); }

/* ---------- 17. 小兽 ----------
   五种都从你心帖的原话里来，颜色跟着光线走 */
:root{ --art-elk:#9a7b3a; --art-fly:#a94b46; --art-roller:#2f5f8a; --art-dragon:#8b8a34; --art-fox:#7f97ad; --art-hut:#a8802f; }
[data-theme="dusk"]{ --art-elk:#b0924c; --art-fly:#c4666a; --art-roller:#5f8fc0; --art-dragon:#a3a24e; --art-fox:#93aac2; --art-hut:#c49a44; }
[data-theme="night"]{ --art-elk:#c8a552; --art-fly:#d0655f; --art-roller:#6ba3d6; --art-dragon:#bdb54f; --art-fox:#9fbdd8; --art-hut:#d9b35f; }
.crit{ display:block; width:100%; height:100%; overflow:visible; }
.crit .dot{ fill:currentColor; stroke:none; }
.crit .tint{ fill:currentColor; stroke:none; opacity:.2; }
.crit-elk{ color:var(--art-elk); }
.crit-butterfly{ color:var(--art-fly); }
.crit-roller{ color:var(--art-roller); }
.crit-seadragon{ color:var(--art-dragon); }
.crit-fox{ color:var(--art-fox); }
.crit-hut{ color:var(--art-hut); }

/* ---------- 17b. 放大展示那一只（收藏「想画进画里的东西」点开来那张）
   两步：先把线一根一根描出来（critDraw，靠 JS 把每条路径的长度塞进 --len），
   描完再开始动。终态都是「不动也就是对的那张脸」，所以 prefers-reduced-motion
   把动画整条掐掉之后，看到的是画好的线稿，不会停在空白上。 */
.crit-live{ stroke-width:1.35; }
.crit-live .p-arm, .crit-live .p-wing, .crit-live .p-fin, .crit-live .p-ear,
.crit-live .p-eye, .crit-live .p-horn, .crit-live .p-frost, .crit-live .p-smoke{
  transform-box:view-box; }
.crit-draw{ stroke-dasharray:var(--len);
  animation:critDraw .5s linear var(--dl, 0ms) backwards, critFade .34s ease var(--dl, 0ms) backwards; }
@keyframes critDraw{ from{ stroke-dashoffset:var(--len) } to{ stroke-dashoffset:0 } }
@keyframes critFade{ from{ opacity:0 } to{ opacity:1 } }

/* 各自动的地方：蝴蝶和佛法僧扇翅膀、海龙的水草飘、狐狸的霜晶闪、小屋挥手冒烟、麋鹿点头带眨眼 */
.crit-live .p-wing{ transform-origin:50% 46%; animation:critFlap 1.5s var(--ease-ink) 1.15s infinite backwards; }
.crit-roller .p-wing{ animation-duration:2.3s; }
@keyframes critFlap{ 0%,100%{ transform:scaleX(1) } 50%{ transform:scaleX(.42) } }
.crit-live.crit-elk{ transform-origin:50% 92%; animation:critNod 5.4s ease-in-out 1.15s infinite backwards; }
@keyframes critNod{ 0%,100%{ transform:rotate(-2.4deg) } 50%{ transform:rotate(2.4deg) } }
.crit-live .p-eye{ transform-origin:50% 64%; animation:critBlink 4.6s ease-in-out 1.4s infinite backwards; }
@keyframes critBlink{ 0%,90%,100%{ transform:scaleY(1) } 94%{ transform:scaleY(.1) } }
.crit-live .p-horn{ animation:critGlint 3.6s ease-in-out 1.2s infinite backwards; }
@keyframes critGlint{ 0%,100%{ opacity:.5 } 50%{ opacity:1 } }
.crit-live .p-fin{ transform-origin:38% 52%; animation:critFlutter 2.6s ease-in-out 1.15s infinite backwards; }
@keyframes critFlutter{ 0%,100%{ transform:rotate(-5deg) } 50%{ transform:rotate(6deg) } }
.crit-live.crit-seadragon{ transform-origin:50% 50%; animation:critSway 6.4s ease-in-out 1.15s infinite backwards; }
@keyframes critSway{ 0%,100%{ transform:rotate(-4deg) translateY(2px) } 50%{ transform:rotate(4deg) translateY(-2px) } }
.crit-live .p-ear{ transform-origin:50% 40%; animation:critTwitch 5.2s ease-in-out 1.5s infinite backwards; }
@keyframes critTwitch{ 0%,84%,100%{ transform:rotate(0) } 88%{ transform:rotate(-7deg) } 92%{ transform:rotate(5deg) } }
.crit-live .p-frost{ transform-origin:50% 59%; animation:critTwinkle 2.9s ease-in-out 1.2s infinite backwards; }
@keyframes critTwinkle{ 0%,100%{ opacity:.35; transform:scale(.9) } 50%{ opacity:1; transform:scale(1.12) } }
.crit-live .p-arm{ transform-origin:75% 62.5%; animation:critWave 1.5s var(--ease-spring) 1.15s infinite backwards; }
@keyframes critWave{ 0%,100%{ transform:rotate(-14deg) } 50%{ transform:rotate(24deg) } }
.crit-live .p-smoke{ transform-origin:68% 20%; animation:critSmoke 3.4s linear 1.4s infinite backwards; }
@keyframes critSmoke{ 0%{ opacity:0; transform:translateY(3px) scale(.7) } 30%{ opacity:.9 } 100%{ opacity:0; transform:translateY(-7px) scale(1.25) } }
.crit-live.crit-hut{ transform-origin:50% 100%; animation:critBob 3.8s ease-in-out 1.15s infinite backwards; }
@keyframes critBob{ 0%,100%{ transform:translateY(0) } 50%{ transform:translateY(-2.5px) } }

/* 空状态里蹲一只 */
.empty.has-art{ display:grid; justify-items:center; gap:7px; padding:22px 18px 24px; }
.empty .empty-crit{ width:58px; height:58px; opacity:.72;
  transition:opacity var(--t-slow), transform var(--t) var(--ease-spring); }
.empty.has-art:hover .empty-crit{ opacity:1; transform:translateY(-3px); }

/* 页脚那一队，慢慢游过去 */
.critters{ display:flex; gap:clamp(18px,5vw,44px); align-items:flex-end; justify-content:center;
  margin:38px 0 -4px; opacity:.55; }
.crit-i{ width:34px; height:34px; }
.crit-i svg{ animation:critDrift 8s ease-in-out infinite; }
.crit-i-butterfly svg{ animation-duration:6.2s; animation-delay:-1.4s; }
.crit-i-roller svg{ animation-duration:9.6s; animation-delay:-3.2s; }
.crit-i-seadragon svg{ animation-duration:7.4s; animation-delay:-5s; }
.crit-i-fox svg{ animation-duration:10.2s; animation-delay:-2.2s; }
@keyframes critDrift{ 0%,100%{ transform:translateY(0) } 50%{ transform:translateY(-6px) } }

/* 滚出视口的循环动画先停掉：它们不停，浏览器就永远有个合成任务在排队，白白拖慢滚动 */
.critters.is-off .crit-i svg, .np-eq.is-off i{ animation-play-state:paused; }

@media (prefers-reduced-motion:reduce){
  /* 这一条是整个站的总闸：一压，hover 那点小过渡、错开摊开、翻牌、落印、水线、小兽全停。
     它只听她的：「该动的都动」（html.is-alive，默认开着）点掉才生效。
     不加 html:not(.is-alive) 这道闸的话，她那台报 reduce 的机器看到的站就是死的 ——
     「动态效果咋没了 我没说减少动态效果啊」。 */
  html:not(.is-alive) *{ transition:none !important; animation:none !important; }
  /* 潮线和扁舟靠滚动驱动动画活着，动画一停就退回 var(--p, 0) 那个兜底值 —— 等于海岸线消失、船钉在左边。
     这里不恢复动画，只给一个不动的中间态：停在六成，两边都不会「划到别处去」。老引擎上 JS 往 :root 写的
     --p 会被这条盖掉，同样静止。
     唯一的例外是主页脚下那四片浪：她要的就是「活的水」，reduce 下改成小行程慢速涌，见 sections.css 的 .drift。 */
  html:not(.is-alive) .tide{ --p:.62; }
}

/* ---------- 18. 打印 ---------- */
/* 她要的是「一页书」，不是一张截图。所以：光线强制回晴昼那套数值（夜航印到 A4 上就是一张灰纸片子，
   还费墨），界面上的件全收掉，正文自己重排成 11pt 宋体、1.75 倍行距；外链把地址本写出来 —— 纸上点不动。
   <details> 摊开这一步 CSS 办不到，在 core.js 的 beforeprint 里。 */
@page{ margin:16mm 15mm }
@media print{
  :root, [data-theme="dusk"], [data-theme="night"]{
    --paper:#fff; --paper-hi:#fff; --paper-lo:#f5f7f9; --paper-edge:#d3d7dc;
    --ink:#14181c; --ink-soft:#2c343c; --muted:#6b7480;
    --line:#dcdfe4; --line-dash:#c5cad1; --pencil:#939ba5;
    --indigo:#1c3d5f; --teal:#2c6a63; --iris:#1c3d5f; --sand:#8a5c2e; --mist:#cfd9e2;
    --rose:#8c5560; --seal:#8f3b36; --accent:#1c3d5f;
    --bg-grad:none; --bg-wash:none; --hair:transparent; --veil:1;
    --shadow-s:none; --shadow-m:none; --shadow-l:none; --shadow-lift:none;
  }
  /* 门牌、进度角标、播放器、右侧那一栏、背景颗粒、页脚那一队小兽、还有所有只给手点的控件 */
  .grain, .wash, .masthead, .corner, .toast, .mask, .critters, .rail, .dock, .kb-fab, .inkcur, .nine-peek,
  .run-slot, .gb-acts, .gb-del, .gb-row, .field, .btn, .sec-tag, .kb-tools, .kb-pager,
  .plate figcaption i, .art-note, .datasrc, .drift, .sky, .foot-places{ display:none !important }
  body{ background:#fff !important; color:var(--ink); font-size:11pt }
  .shell{ max-width:none }
  .layout{ display:block }
  .stream{ gap:0 }
  .card, .card.lift:hover, .card:hover{
    background:none !important; border:none; box-shadow:none; padding:0; border-radius:0; transform:none !important }
  .sheet{ padding:0 } .sheet::before, .sheet::after{ display:none }
  .page-head{ margin:0 0 14pt }
  .article-head{ border-bottom:1px solid var(--line) }
  .md-body{ font-size:11pt; line-height:1.75; max-width:none; color:var(--ink) }
  .md-body h2, .md-body h3, .md-body h4{ break-after:avoid; page-break-after:avoid }
  .md-body p{ orphans:3; widows:3 }
  .md-body img, .plate img, .photo img, .art-item img{ max-width:100%; break-inside:avoid }
  .md-body pre, .md-body code, .md-body table{ font-size:9pt; white-space:pre-wrap; break-inside:avoid }
  .post, .kb-item, .sb-item, .gb-item, .tl-item{ break-inside:avoid }
  /* 纸上的链接点不动，所以外部地址跟在字后面写出来；站内 # 路由写了也没用，不写 */
  .md-body a[href^="http"]::after{ content:"（" attr(href) "）"; font-size:8.5pt; color:var(--muted); word-break:break-all }
  .foot{ border-top:1px solid var(--line); margin-top:18pt; padding-top:8pt; font-size:9pt; color:var(--muted) }
}
