/* v1.1 additions. Original book spacing, media and MathML rules stay in toc.css. */
:root{--reader-scale:1;--header-duration:220ms;--header-ease:cubic-bezier(.4,0,.2,1);--reader-serif-zh:"Songti SC","STSong","Noto Serif CJK SC",serif;--reader-kai-zh:"Songti SC","STSong","Noto Serif CJK SC",serif;--reader-serif-en:Georgia,"Times New Roman",serif;}
.header-slot{display:flow-root;}
.blog-header{position:relative;z-index:30;background:var(--paper);transform:translateY(0);}
.header-tools{display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
.language-switch{font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));white-space:nowrap;}
.theme-icon{display:none;}
.header-stuck .blog-header{position:fixed;top:0;left:0;right:0;transform:translateY(0);transition:transform var(--header-duration) var(--header-ease);}
.header-stuck.header-hidden .blog-header{transform:translateY(-100%);}
.header-measuring .blog-header{transition:none!important;}
.rail{transition:transform .35s var(--ease),visibility .35s;}
.rail-handle{transition:left .35s var(--ease),background-color .2s var(--ease);}
.prose :is(h1,h2,h3,h4,[id]){scroll-margin-top:calc(var(--sticky-header-height,48px) + 24px);}
.prose{font-size:calc(calc(18px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));font-family:var(--reader-body-font,var(--blog-font));}
.prose h1{font-size:calc(calc(clamp(30px,4vw,42px) * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.prose h2{font-size:calc(calc(28px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.prose h3{font-size:calc(calc(22px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.prose h4{font-size:calc(calc(20px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.prose .caption,.prose figcaption{font-size:calc(calc(15px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
html:lang(zh)[data-reader-font="serif"]{--reader-body-font:var(--reader-local-font,var(--reader-serif-zh)),var(--reader-serif-zh);}
html:lang(zh)[data-reader-font="kai"]{--reader-body-font:var(--reader-local-font,var(--reader-kai-zh)),var(--reader-kai-zh);}
html:lang(en)[data-reader-font="serif"]{--reader-body-font:var(--reader-local-font,var(--reader-serif-en)),var(--reader-serif-en);}
.translation-notice{padding:16px 20px;margin:0 0 24px;background:var(--soft);border-left:3px solid var(--accent);font:calc(16px * var(--text-factor,var(--text-zoom-scale,1)))/1.7 var(--blog-font);color:var(--ink-2);}
.original-language{font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));color:var(--muted);}
.reader-toggle{border:1px solid var(--line);border-radius:6px;cursor:pointer;background:var(--paper);color:var(--ink);font:calc(16px * var(--text-factor,var(--text-zoom-scale,1)))/1 var(--blog-font);min-width:44px;min-height:44px;padding:8px;}
.reader-panel{position:fixed;inset:calc(var(--sticky-header-height,105px) + 12px) max(24px,calc((100vw - 1000px)/2)) auto auto;margin:0;padding:24px;width:340px;max-width:calc(100vw - 48px);border:1px solid var(--line);border-radius:12px;background:var(--paper);color:var(--ink);box-shadow:0 8px 34px rgba(0,0,0,.16);font:calc(15px * var(--text-factor,var(--text-zoom-scale,1)))/1.5 var(--blog-font);}
.reader-panel[open]{animation:reader-in var(--header-duration) var(--header-ease);}
.reader-panel:not([open]){display:none;}
.reader-panel::backdrop{background:transparent;}
.reader-panel-title:focus{outline:none;}
.reader-choices .size-a{line-height:1;font-weight:500;}.reader-choices .size-0{font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));}.reader-choices .size-1{font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));}.reader-choices .size-2{font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));}.reader-choices .size-3{font-size:calc(19px * var(--text-factor,var(--text-zoom-scale,1)));}.reader-choices .size-4{font-size:calc(22px * var(--text-factor,var(--text-zoom-scale,1)));}
.theme-icon svg{width:14px;height:14px;display:block;}
.blog-footer a:only-child{margin-left:auto;}
.reader-panel-head{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:24px;}
.reader-panel-title,.rail-title{font:600 calc(18px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font);margin:0;text-wrap:balance;}
.reader-panel-head button{border:0;background:none;color:var(--ink);font:calc(26px * var(--text-factor,var(--text-zoom-scale,1)))/1 var(--blog-font);width:44px;height:44px;cursor:pointer;}
.reader-panel fieldset{border:0;padding:0;margin:0 0 24px;min-width:0;}
.reader-panel fieldset:last-child{margin-bottom:0;}
.reader-panel legend{padding:0;margin-bottom:8px;color:var(--muted);}
.reader-choices{display:flex;gap:8px;}
.reader-choices button{flex:1;min-width:0;min-height:44px;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink);font:calc(16px * var(--text-factor,var(--text-zoom-scale,1)))/1.5 var(--blog-font);cursor:pointer;}
.reader-choices button[aria-pressed="true"]{background:var(--soft);border-color:var(--ink);box-shadow:inset 0 -2px var(--ink);}
/* Previews use local fallbacks; unselected web fonts never cause a request. */
.reader-choices .font-sample{font-size:calc(24px * var(--text-factor,var(--text-zoom-scale,1)));}
.reader-choices .font-serif{font-family:var(--reader-serif-zh);}
.reader-choices .font-kai{font-family:var(--reader-kai-zh);}
html:lang(en) .reader-choices .font-serif{font-family:var(--reader-serif-en);}
html[data-reader-font="serif"] .reader-choices .font-serif,html[data-reader-font="kai"] .reader-choices .font-kai{font-family:var(--reader-body-font);}
@keyframes reader-in{from{opacity:0;transform:translateY(12px);}}
@media(max-width:599px){
  .blog-header{--gutter:24px;}
  .header-tools{gap:12px;}
  .header-stuck .blog-header{height:48px;min-height:48px;padding-block:0;flex-wrap:nowrap;gap:8px;}
  .header-stuck .blog-name{flex-basis:auto;white-space:nowrap;font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));}
  .header-stuck .header-tools{gap:8px;flex-wrap:nowrap;}
  .header-stuck .blog-themes{padding:2px;gap:0;}
  .header-stuck .blog-themes button{min-height:34px;min-width:28px;padding:0 5px;font-size:calc(15px * var(--text-factor,var(--text-zoom-scale,1)));}
  .header-stuck .theme-word{display:none;}
  .header-stuck .theme-icon{display:inline-flex;align-items:center;justify-content:center;}
  .header-stuck .language-switch{font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));}
  .prose h2{font-size:calc(calc(26px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
}
@media(width < 1280px){
  .reader-desktop{display:none;}
  .toc-fab,.to-top-fab,.to-top-fab.is-visible{transition:transform var(--header-duration) var(--header-ease),opacity var(--header-duration) var(--header-ease),visibility var(--header-duration);}
  .header-hidden :is(.toc-fab,.to-top-fab){transform:translateY(18px);opacity:0;visibility:hidden;pointer-events:none;}
  .reader-panel{inset:auto 24px max(24px,env(safe-area-inset-bottom,0px));width:auto;max-width:none;max-height:80dvh;overflow:auto;}
  .blog-footer{padding-bottom:calc(var(--toc-fab-bottom) + 2 * var(--toc-fab-size) + var(--fab-gap) + 16px);}
}
@media(prefers-reduced-motion:reduce){
  .blog-header,.rail,.rail-handle,.toc-fab,.to-top-fab{transition:none!important;}
  .reader-panel[open]{animation:none;}
}
/* pre4: the header controls share one frame, rhythm and monochrome state. */
:root{--reader-hand-en:Georgia,"Times New Roman",serif;}
.ui-icon{display:inline-block;width:24px;height:24px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle;}
.header-tools{gap:10px;flex-wrap:nowrap;}
.blog-languages,.blog-themes{display:flex;align-items:center;gap:2px;border:1px solid var(--line);border-radius:6px;padding:3px;height:44px;}
.blog-languages a,.blog-themes button{display:flex;align-items:center;justify-content:center;min-height:36px;padding:0 10px;border:0;border-radius:3px;font:calc(14px * var(--text-factor,var(--text-zoom-scale,1)))/1 var(--blog-font);color:var(--muted);background:none;text-decoration:none;white-space:nowrap;}
.blog-languages a[aria-current],.blog-themes button[aria-pressed="true"]{background:var(--soft);color:var(--ink);box-shadow:inset 0 -2px var(--ink);}
.blog-languages a:hover,.blog-themes button:hover,.reader-toggle:hover{background:var(--soft);color:var(--ink);}
.reader-toggle{height:44px;min-height:44px;min-width:44px;display:inline-grid;place-items:center;border:1px solid var(--line);border-radius:6px;font:calc(14px * var(--text-factor,var(--text-zoom-scale,1)))/1 var(--blog-font);}
.theme-icon{display:inline-flex;align-items:center;justify-content:center;}.theme-word{display:none;}
.theme-icon .ui-icon{width:24px;height:24px;}
.header-stuck .blog-header{min-height:56px;padding-block:6px;flex-wrap:nowrap;gap:8px;}
.header-stuck .blog-name{flex-basis:auto;font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));white-space:nowrap;}
.header-stuck .header-tools{gap:6px;flex-wrap:nowrap;}
.header-stuck :is(.blog-languages,.blog-themes){height:34px;padding:2px;gap:0;}
.header-stuck :is(.blog-languages a,.blog-themes button){min-height:28px;min-width:26px;padding:0 5px;font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));}
.header-stuck .reader-desktop{height:34px;min-height:34px;min-width:34px;padding:4px;}
.header-stuck .blog-header .ui-icon{width:20px;height:20px;}
/* Desktop rail: only the list scrolls; title and return button keep their space. */
@media(min-width:1280px){
  .rail{min-height:0;gap:16px;}
  .rail-title{flex:none;color:var(--ink);}
  .rail > .rail-list{flex:1 1 0;min-height:0;overflow-y:auto;overscroll-behavior:contain;align-content:start;margin:0;scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--ink) 25%,transparent) transparent;}
  .rail-to-top{display:inline-flex;align-items:center;justify-content:center;gap:8px;flex:none;align-self:flex-start;min-height:44px;max-width:100%;margin:0;padding:10px 14px;border:0;border-radius:24px;background:var(--paper);color:var(--ink);box-shadow:0 2px 12px var(--shadow,rgba(17,17,17,.16)),inset 0 0 0 1px var(--line);font:calc(15px * var(--text-factor,var(--text-zoom-scale,1)))/1.45 var(--blog-font);cursor:pointer;text-decoration:none;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .18s var(--ease),visibility 0s .18s;}
  .rail-to-top.is-visible{opacity:1;visibility:visible;pointer-events:auto;transition:opacity .18s var(--ease),visibility 0s;}
  .rail-to-top:hover{text-decoration:none;background:var(--soft);}
  .rail-to-top:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
  .rail-to-top .ui-icon{width:24px;height:24px;}
}
/* Leave room below the cover even in a 600px-high laptop window. */
@media(min-width:1280px) and (max-height:800px){.rail{gap:8px;padding-top:8px;padding-bottom:max(8px,env(safe-area-inset-bottom,0px));}}
@media(min-width:1280px) and (prefers-reduced-motion:reduce){.rail-to-top,.rail-to-top.is-visible{transition:none;}}
.toc-fab .list{width:24px;height:24px;}
.to-top-fab{width:var(--toc-fab-size);height:var(--toc-fab-size);}
.post-cover{width:100%;margin:0;background:#F7F5F0;}.post-cover img{display:block;width:min(100%,1600px,140vh,calc(200vh - 460px));max-height:min(70vh,calc(100vh - 230px));aspect-ratio:2/1;height:auto;margin-inline:auto;object-fit:contain;border-radius:0;}
.post-cover ~ .reader .post-shell.column{margin-top:0;padding-top:32px;}
.toc-inline{margin-bottom:24px;display:none;}
.home-intro p{margin:16px 0 0;color:var(--ink-2);font-size:calc(18px * var(--text-factor,var(--text-zoom-scale,1)));max-width:42em;}
html:lang(en)[data-reader-font="kai"]{--reader-body-font:var(--reader-local-font,var(--reader-hand-en)),var(--reader-hand-en);}
html:lang(en) .font-kai{font-family:var(--reader-hand-en);}
.font-sample{display:flex;align-items:center;justify-content:center;flex-direction:column;gap:2px;}
.typeface-preview{display:block;height:30px;width:48px;fill:currentColor;}
.font-choice-name{font:calc(12px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font);color:var(--muted);}
@media(width < 1280px){.reader-desktop{display:none;}.header-stuck .blog-header{height:48px;min-height:48px;}.header-stuck .blog-name{font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));}}
@media(max-width:639px){
 .toc-inline{display:flow-root;}.post-shell.column{margin-top:16px;}
 .post-cover ~ .reader .post-shell.column{margin-top:0;padding-top:20px;}
 .blog-header{gap:16px;}.header-tools{gap:8px;}.blog-name{flex-basis:100%;}
 .blog-languages a,.blog-themes button{padding-inline:8px;}
 .header-stuck .blog-header{width:100%;padding-inline:12px;}
 .header-stuck .blog-name{font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));letter-spacing:-.03em;}
 .header-stuck .header-tools{gap:5px;}.header-stuck .blog-languages a{padding-inline:4px;font-size:calc(11px * var(--text-factor,var(--text-zoom-scale,1)));}
 .header-stuck .blog-themes button{padding:0 3px;min-width:24px;}
}
@media(max-width:359px){.header-stuck .blog-header{padding-inline:6px;gap:4px;}.header-stuck .blog-name{font-size:calc(11px * var(--text-factor,var(--text-zoom-scale,1)));}.header-stuck .blog-languages a{font-size:calc(10px * var(--text-factor,var(--text-zoom-scale,1)));padding-inline:3px;}.header-stuck .blog-themes button{min-width:20px;}.header-stuck .theme-icon .ui-icon{width:18px;height:18px;}}
/* pre6: optional heading faces have their own real weights; no synthetic bold. */
html[data-reader-font="serif"] :is(.prose h1,.prose h2,.prose h3,.prose h4,.post-list h3,.home h1),
html[data-reader-font="kai"] :is(.prose h1,.prose h2,.prose h3,.prose h4,.post-list h3,.home h1){font-family:var(--reader-heading-font,var(--reader-body-font));font-weight:var(--reader-heading-weight,700);font-synthesis:none;}
/* Match the Chinese default heading rule's specificity, including traditional text.
   Keep this separate from the shared English/home declarations above. */
html:lang(zh)[data-reader-font="serif"] :is(.prose h1,.prose h2,.prose h3,.prose h4,.prose .dek,.rail,.rail *,.toc-pop,.toc-pop *,.toc-inline,.toc-inline *),
html:lang(zh)[data-reader-font="kai"] :is(.prose h1,.prose h2,.prose h3,.prose h4,.prose .dek,.rail,.rail *,.toc-pop,.toc-pop *,.toc-inline,.toc-inline *){font-family:var(--reader-heading-font,var(--reader-body-font));font-weight:var(--reader-heading-weight,700);font-synthesis:none;}
/* Every absolute font declaration receives one multiplier at build time.
   Relative and inherited text already follows its parent's computed size. */
html.text-zoom :is(.prose h1,.home h1,.post-list h3,.post-subtitle){--text-factor:var(--title-text-scale);}
/* Keep Aa's reader scale; cap the subtitle independently of the enlarged prose. */
html.text-zoom .prose .dek{--text-factor:var(--title-text-scale);font-size:calc(calc(20.7px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
html.text-zoom :is(.blog-header,.reader-panel,.site-menu,.site-toast,.mobile-reader-controls,.toc-fab,.to-top-fab,.rail,.rail-handle,.toc-pop,.toc-inline){--text-factor:var(--ui-text-scale);}
.theme-cycle{display:none;}
.header-tight .blog-header{flex-wrap:nowrap;gap:8px;}
.header-tight .blog-header .blog-name{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.header-tight .header-tools{flex:0 0 auto;min-width:0;gap:6px;flex-wrap:nowrap;}
.header-tight .blog-languages a[aria-current],.header-tight .blog-themes{display:none;}
.header-tight .blog-languages{flex:none;}
.header-tight .theme-cycle{display:inline-grid;place-items:center;flex:none;width:44px;height:44px;padding:8px;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink);cursor:pointer;}
.header-tight.header-stuck .theme-cycle{width:34px;height:34px;padding:4px;}
.theme-cycle:focus-visible{outline:2px solid var(--accent);outline-offset:4px;}
html.text-zoom :is(.reader-panel,.toc-pop,.rail) :is(h2,p,a,legend){overflow-wrap:anywhere;}
/* translation review status: upright among the italic note, a small proofreading mark in front (11-01) */
.prose .caption .review-status{font-style:normal;white-space:nowrap;}
.prose .caption .review-status .ui-icon{width:1.1em;height:1.1em;vertical-align:-.2em;margin-right:.2em;}
/* blog-v1.2: main-site globe, one Aa and theme cycle, in a single header row. */
.blog-header,.header-stuck .blog-header{flex-wrap:nowrap;gap:16px;}
.blog-header .blog-name,.header-stuck .blog-header .blog-name{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.blog-header .header-tools{flex:0 0 auto;display:flex;align-items:center;gap:16px;flex-wrap:nowrap;}
.language-control{position:relative;display:flex;align-items:center;}
.blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle){position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;gap:.35em;margin:0;padding:0;border:0;border-radius:0;min-width:30px;min-height:30px;height:30px;background:none;color:var(--ink);font:calc(15px * var(--text-factor,var(--text-zoom-scale,1)))/1.2 var(--blog-font);white-space:nowrap;cursor:pointer;transition:color .3s var(--ease);}
.blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle) svg{width:18px;height:18px;flex:none;}
.blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle):hover{color:var(--ink-2);background:none;}
.blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle):focus-visible{outline:2px solid var(--accent);outline-offset:4px;}
.script-note{margin:8px 0 0;font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));color:var(--muted);}
/* The existing contents and back-to-top positions and scroll rules stay intact. */
@media(max-width:639px){
 .blog-header,.header-stuck .blog-header{width:100%;min-height:64px;height:auto;margin:0;padding:16px 24px;gap:12px;}
 .header-stuck .blog-header{min-height:48px;height:48px;padding-block:8px;}
 .blog-header .blog-name,.header-stuck .blog-header .blog-name{font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));letter-spacing:-.02em;flex-basis:auto;}
 .blog-header .header-tools,.header-stuck .header-tools{gap:12px;}
 .blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle){width:30px;min-width:30px;min-height:30px;height:30px;border:1px solid var(--muted);border-radius:50%;padding:0;}
 .blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle) svg{width:15px;height:15px;}
 .lt-label,.tt-label,.rt-label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
 .reader-panel{max-height:80dvh;overflow:auto;}
}
.header-tight .blog-header .blog-name{flex:1 1 0;}
.header-tight .blog-header :is(.lt-label,.tt-label,.rt-label){position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}
.header-tight .blog-header .header-tools{gap:12px;}
.header-tight .blog-header .theme-cycle{width:30px;height:30px;padding:0;}
@media(prefers-reduced-motion:reduce){.blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle){transition:none;}}
/* Imported drafts inherit the shared reader, rail, header and both themes. */
.draft-label{font-size:.75em;color:var(--muted);border:1px solid var(--line);border-radius:3px;padding:.1em .4em;}
.language.is-original{color:var(--accent);background:var(--accent-soft);}
.draft-label.is-reviewed{color:var(--accent);border-color:currentColor;background:var(--accent-soft);}
:root[data-theme="dark"] :is(.language.is-original,.draft-label.is-reviewed){background:color-mix(in srgb,var(--accent) 30%,var(--paper));}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) :is(.language.is-original,.draft-label.is-reviewed){background:color-mix(in srgb,var(--accent) 30%,var(--paper));}}
.imported .dek{color:var(--muted);font-size:1.15em;line-height:1.5;}
.imported .byline{color:var(--muted);font-size:.85em;}
.imported .num{color:var(--accent);margin-right:.5em;}
.prose figcaption{color:var(--muted);line-height:1.6;margin-top:.7em;}
.prose figcaption .no{color:inherit;font-weight:600;margin-right:.5em;}
.imported figure .scroll{max-width:100%;overflow-x:auto;}
.imported figure img{display:block;max-width:100%;height:auto;}
.imported .swipe{display:none;}
.imported pre{max-width:100%;overflow:auto;}
html[data-theme="dark"] .imported .fig-mono{filter:invert(1) hue-rotate(180deg);}
@media(prefers-color-scheme:dark){html:not([data-theme="light"]) .imported .fig-mono{filter:invert(1) hue-rotate(180deg);}}
/* v1.2 selected title, archive and appendix styles. */
.post-list>li:last-child{border-bottom:0}
.blog-footer{margin-top:24px}
.post-year{margin:36px 0 12px;color:var(--muted);font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));font-weight:400;letter-spacing:.02em}
.post-list h3{margin-bottom:8px}
.post-list .post-subtitle{margin:0 0 12px;color:var(--ink-2);font-size:calc(18px * var(--text-factor,var(--text-zoom-scale,1)));line-height:1.6}
.prose .dek{margin:12px 0 clamp(40px,6vw,56px);color:var(--ink-2);font-size:1.15em;line-height:1.5;font-weight:400}
.prose .post-title{margin-bottom:0}
.post-updates{margin:44px 0 8px;padding-top:18px;border-top:1px solid var(--line);color:var(--muted)}
.prose .post-updates .pu-label{margin:0 0 14px;padding:0;font-size:calc(18px * var(--text-factor,var(--text-zoom-scale,1)));line-height:1.5;font-weight:400;color:var(--muted);letter-spacing:.02em}
.pu-entry+.pu-entry{margin-top:24px}
.prose .post-updates time{display:block;font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));line-height:1.6;color:var(--muted);font-variant-numeric:tabular-nums;margin:0 0 6px}
.prose .post-updates ul{margin:0;padding:0 0 0 1.15em;list-style:disc}
.prose .post-updates li{margin:0 0 6px;padding:0;font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));line-height:1.75;color:var(--muted)}
.prose .post-updates li::before{content:none}
.prose .post-updates li::marker{color:var(--muted)}
.post-updates,.post-neighbors{--text-factor:calc(var(--reader-scale,1) * var(--text-zoom-scale,1))}
.post-neighbors{margin:32px 0 8px;padding-top:18px;border-top:1px solid var(--line);display:flex;flex-wrap:wrap;justify-content:space-between;gap:16px;font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));font-family:var(--blog-font)}
.post-neighbors a{max-width:100%;overflow-wrap:anywhere}
.post-neighbors span{display:inline-block;width:100%;color:var(--muted)}
.post-subtitle,.dek,.post-neighbors a{text-wrap:balance}
/* Framework section numbering and optional display title. */
.prose h2:has(>.num){display:flex;gap:.6em;align-items:baseline}
.prose h2>.num{color:var(--accent);flex:none;font-variant-numeric:tabular-nums}
.header-stuck .blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle) svg{width:18px;height:18px}
@media(max-width:639px){.header-stuck .blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle) svg{width:15px;height:15px}}

/* round8: home reading content shares the article preference scale and fonts. */
.home{font-family:var(--reader-body-font,var(--blog-font));}
.home h1{font-size:calc(calc(clamp(34px,5vw,54px) * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));text-wrap:balance;}
.home-intro .home-subtitle{margin:12px 0 0;font-size:calc(calc(24px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));font-weight:500;color:var(--ink);text-wrap:balance;}
.home-intro .home-note{margin:8px 0 0;font-size:calc(calc(18px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));color:var(--ink-2);text-wrap:pretty;}
.home .post-year{font-size:calc(calc(16px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.home .post-list h3{font-size:calc(calc(clamp(23px,3vw,30px) * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.home .post-list .post-subtitle{font-size:calc(calc(18px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.home .post-summary{font-size:calc(calc(16px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.home .post-meta{font-size:calc(calc(14px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
.home .language{font-size:calc(calc(12px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}
html:lang(zh)[data-reader-font="serif"] .home :is(h1,h2,h3),html:lang(zh)[data-reader-font="kai"] .home :is(h1,h2,h3),
html:lang(en)[data-reader-font="serif"] .home :is(h1,h2,h3),html:lang(en)[data-reader-font="kai"] .home :is(h1,h2,h3){font-family:var(--reader-heading-font,var(--reader-body-font));font-weight:var(--reader-heading-weight,700);font-synthesis:none;}
html.text-zoom .home-subtitle{--text-factor:var(--title-text-scale);}
@media(max-width:599px){.home-intro .home-subtitle{font-size:calc(calc(22px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)));}}

html:lang(zh) .home .post-year,html:lang(zh)[data-reader-font] .home .post-year{font-family:inherit;font-weight:400;}

/* Header settings reuse the reader dialog frame, placement and animation. */
.language-options ul{display:flex;gap:8px;list-style:none;padding:0;margin:0;}
.language-options li{flex:1;min-width:0;margin:0;padding:0;}
.language-options a{display:flex;align-items:center;justify-content:center;box-sizing:border-box;min-height:44px;padding:0;font:calc(16px * var(--text-factor,var(--text-zoom-scale,1)))/1.5 var(--blog-font);background:var(--paper);border:1px solid var(--line);border-radius:6px;color:var(--ink);text-decoration:none;}
.language-options a[aria-current]{background:var(--soft);border-color:var(--ink);box-shadow:inset 0 -2px var(--ink);}
.language-options a:hover,.language-options a:focus-visible{background:var(--soft);}
.color-choices button{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;padding:12px 4px;}
.color-choices span{font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));overflow-wrap:anywhere;}

/* Mobile settings share the contents button baseline and header visibility state. */
@media(width < 1280px){
 :root{--toc-fab-size:48px;--fab-gap:12px;--toc-fab-bottom:max(16px,calc(env(safe-area-inset-bottom,0px) + 10px));}
 .header-tools.mobile-reader-controls{position:fixed;z-index:12;right:max(14px,env(safe-area-inset-right,0px));bottom:var(--toc-fab-bottom);display:flex;align-items:center;flex-wrap:nowrap;gap:var(--fab-gap);transition:transform var(--header-duration) var(--header-ease),opacity var(--header-duration) var(--header-ease),visibility var(--header-duration);}
 .mobile-reader-controls :is(.lang-toggle,.reader-toggle,.theme-cycle){position:relative;display:grid;place-items:center;flex:none;width:var(--toc-fab-size);height:var(--toc-fab-size);min-width:var(--toc-fab-size);min-height:var(--toc-fab-size);margin:0;padding:0;border:0;border-radius:50%;background:var(--paper);color:var(--ink);box-shadow:0 2px 12px var(--shadow,rgba(17,17,17,.16)),inset 0 0 0 1px var(--line);cursor:pointer;}
 .mobile-reader-controls :is(.lt-label,.rt-label,.tt-label){position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;}
 .mobile-reader-controls svg{width:18px;height:18px;flex:none;}
 .mobile-reader-controls button:hover{background:var(--soft);}
 .mobile-reader-controls button:focus-visible{outline:2px solid var(--accent);outline-offset:4px;}
 .header-hidden .mobile-reader-controls{transform:translateY(18px);opacity:0;visibility:hidden;pointer-events:none;}
 .blog-footer{padding-bottom:calc(var(--toc-fab-bottom) + var(--toc-fab-size) + 16px);}
 body:has(.toc-fab) .blog-footer{padding-bottom:calc(var(--toc-fab-bottom) + var(--toc-fab-size) + var(--fab-gap) + 2 * var(--rocker-half,44px) + 16px);}
}
@media(width < 1280px) and (prefers-reduced-motion:reduce){.mobile-reader-controls{transition:none!important;}}

.reader-refresh{margin-top:24px;}
.reader-refresh[hidden]{display:none;}

/* Shared continuous text-size control; the tick follows the thumb's travel. */
.reader-size-control{display:flex;align-items:center;gap:12px;color:var(--ink);}
.reader-size-control .size-a{flex:none;line-height:1;font-weight:500;}
.reader-size-control .size-0{font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));}
.reader-size-control .size-4{font-size:calc(22px * var(--text-factor,var(--text-zoom-scale,1)));}
.reader-size-track{position:relative;flex:1;min-width:0;}
.reader-size-default{position:absolute;left:calc(22px + (100% - 44px) * 3 / 7);top:calc(50% + 6px);height:6px;width:2px;transform:translateX(-50%);background:var(--ink);pointer-events:none;}
.reader-size-control input{display:block;appearance:none;-webkit-appearance:none;box-sizing:border-box;width:100%;height:44px;margin:0;padding:0;border:0;border-radius:6px;background:transparent;color:var(--ink);touch-action:none;cursor:pointer;}
.reader-size-control input::-webkit-slider-runnable-track{height:4px;border-radius:6px;background:var(--muted);}
.reader-size-control input::-moz-range-track{height:4px;border-radius:6px;background:var(--muted);}
.reader-size-control input::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;width:44px;height:44px;margin-top:-20px;border:12px solid var(--paper);border-radius:50%;background:var(--ink);}
.reader-size-control input::-moz-range-thumb{box-sizing:border-box;width:44px;height:44px;border:12px solid var(--paper);border-radius:50%;background:var(--ink);}
.reader-size-control input:focus-visible{outline:2px solid var(--accent);outline-offset:4px;}

/* From 600px the sticky bar spans the window, so it never shows as a white box over the title image; the padding keeps the text on the page column. Phones already span it. */
@media(min-width:600px){.header-stuck .blog-header{width:100%;padding-inline:max(var(--gutter),calc((100% - 1000px) / 2));}}

/* Identity list in the site article: real text that wraps, so phones see the notes without sideways scrolling. */
.prose .identity-map{margin:0 0 1.5em;padding:20px;background:var(--soft);font-size:calc(calc(15px * var(--text-factor,var(--text-zoom-scale,1))) * var(--text-factor,var(--text-zoom-scale,1)));line-height:1.6}
.prose .identity-map p{margin:0;font-size:inherit;line-height:inherit}
.prose .identity-map .im-lead{font-weight:700}
.prose .identity-map .im-lead:not(:first-child){margin-top:1.1em}
.prose .identity-map .im-main{font-weight:500;margin-top:.55em}
.prose .identity-map .im-sub{margin-left:1.3em}
.prose .identity-map .im-note{color:var(--muted);font-size:calc(max(14px,.88em) * var(--text-factor,var(--text-zoom-scale,1)))}  /* 11/11: labels never under 14px */
.prose .identity-map .im-note.sub{margin-left:1.5em}
.prose .identity-map .past{color:var(--muted)}

/* Home list images, as magazines do it: the newest article carries its banner, the rest the whole banner, small, beside the text. */
.post-lead,.post-thumb{display:block}
.post-lead img,.post-thumb img{display:block;width:100%;height:auto}
.post-lead{margin:0 0 22px}
.post-list>li.has-thumb{display:flow-root}
.has-thumb .post-thumb{float:right;width:128px;margin:0 0 2px 16px}
@media(min-width:600px){.has-thumb .post-thumb{width:224px;margin:0 0 2px 32px}}
.has-thumb h3,.has-thumb .post-subtitle{text-wrap:wrap}

/* Previous and next at the end of the contents, so a reader can move on from the middle of an article. */
/* Previous and next leave the page, so they sit below the contents list as their own group and never look like a section. */
.toc-leave{flex:none;display:grid;gap:8px;margin:0;padding-top:14px;border-top:1px solid var(--line);font-size:calc(calc(14px * var(--text-factor,var(--text-zoom-scale,1))) * var(--text-factor,var(--text-zoom-scale,1)));line-height:1.4;}
.toc-leave a{display:block;min-height:44px;color:var(--ink);text-decoration:none;}
.toc-leave-label{display:flex;align-items:center;gap:4px;color:var(--muted);}
.toc-leave .ui-icon{width:14px;height:14px;transform:rotate(-90deg);}
.toc-leave .is-next .ui-icon{transform:rotate(90deg);}
.toc-leave a:hover .t{text-decoration:underline;text-underline-offset:3px;}
.toc-leave a:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
.toc-pop .toc-leave{padding:14px 16px 12px;}
/* A phone on its side has no room for a fixed group: the whole panel scrolls and the group follows the list. */
@media(max-height:480px){
  .toc-pop .pop-inner{overflow-y:auto;overscroll-behavior:contain;}
  .toc-pop .pop-head{position:sticky;top:0;z-index:1;background:var(--paper);}
  .toc-pop .pop-inner .rail-list{flex:none;overflow:visible;}
}
/* Categories (11-07, dev): a quiet row above the home list, like the Work switch on ashton.is; the line at the end of a post */
.post-filter{margin:28px 0 4px}
.post-filter ul{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0;color:var(--muted);font-size:calc(calc(16px * var(--reader-scale,1)) * var(--text-factor,var(--text-zoom-scale,1)))}
.post-filter li+li::before{content:"\00b7";content:"\00b7"/"";padding:0 .5em;color:var(--muted)}
.post-filter a{display:inline-block;min-height:44px;padding:10px 0;color:var(--muted);text-decoration:none}
.post-filter a:hover{color:var(--ink)}
.post-filter a[aria-current]{color:var(--ink);text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:.3em}
.post-filter span[aria-disabled]{display:inline-block;padding:10px 0;opacity:.45}
.post-filter+.post-year{margin-top:12px}
.post-list>li[hidden],.post-year[hidden],.post-list[hidden]{display:none}

/* Third typeface (11-07). Zhuque Fangsong has one weight; a 0.02em stroke brings it to the weight of LXGW WenKai
   Medium (measured: 98% of its ink). Characters Zhuque lacks fall back to the body face, not the system. */
html:lang(zh)[data-reader-font="kai"] :is(.prose h1,.prose h2,.prose h3,.prose h4,.prose .dek,.rail,.rail *,.toc-pop,.toc-pop *,.toc-inline,.toc-inline *,.post-list h3,.home h1,.home h2,.home h3){font-family:var(--reader-heading-font,var(--reader-body-font)),var(--reader-body-font);-webkit-text-stroke:.02em currentColor;}
html:lang(zh)[data-reader-font="kai"] .prose{font-variant-numeric:lining-nums;}
html:lang(en)[data-reader-font="kai"] :is(.prose h1,.prose h2,.prose h3,.prose h4,.post-list h3,.home h1,.home h2,.home h3){font-style:italic;}
.post-list.tag-list>li{padding:14px 0 16px}
.tag-list .post-meta{margin-bottom:4px}
.tag-list h3{margin:0}
.blog-footer{align-items:center}
/* Footer links (11/8): the main site (MX short mark) and RSS, each with its name; they look and hover like the
   blog's other links (accent, underline thickens on hover). Corners and filled icons belong to the main site. */
.blog-footer-icons{display:inline-flex;align-items:center;gap:18px;margin-left:auto}
.blog-footer-icons .icon-link{display:inline-flex;align-items:center;gap:6px;min-height:44px}
.blog-footer-icons svg{flex:none}
/* Site mark (11/8): the solid mountain sits left of the name, as tall as the name (Han ink height; a little over
   cap height in English); phones show the mark only (the name stays for screen readers). */
.blog-name{display:inline-flex;align-items:center;gap:.4em}
.blog-mark{flex:none;width:auto;height:.92em;aspect-ratio:19.2/13.8}
.blog-header:lang(en) .blog-mark{height:.78em}
.blog-name-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Phones (11/8): at the top the mark and the full name; once the header is stuck, the mark alone, larger. */
@media (max-width:639px){
  .header-stuck .blog-name .blog-mark{height:22px}
  .header-stuck .blog-name .blog-name-text{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
}
/* Current category (11/8): the accent colour; the others stay muted. No colour per category. */
.post-filter a[aria-current]{color:var(--accent)}
/* ---- v1.6 (dev, 11/9) ----
   Category and tags no longer look alike (山山 11/8, 11/9). The category is a section name: plain bold text set
   before the date. A tag is a small tag-shaped chip with a punched hole. Both keep that look on the home list,
   in an article, on a category page and on the tags page. */
/* 11/9 22:20: the category on a list item is the same thing as an entry in the row above the list, so it is set the same way: the reading typeface, the same size, regular weight, no underline until it is pointed at. It outranks the tags by its place (a line of its own on a phone), its size and its colour, not by a second typeface. */
.post-kicker{color:var(--accent);font-family:var(--reader-body-font,var(--blog-font));font-size:calc(calc(16px * var(--reader-scale,1)) * var(--text-factor,var(--text-zoom-scale,1)));font-weight:400;letter-spacing:0;text-decoration:none;padding-block:6px;margin-block:-6px}
.post-kicker:hover{color:var(--accent);text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:.3em}
.post-tag{position:relative;display:inline-flex;align-items:center;gap:.4em;min-height:28px;padding:2px 10px 2px 21px;background:color-mix(in srgb,var(--ink) 11%,var(--paper));color:var(--ink-2);font:400 calc(14px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--reader-body-font,var(--blog-font));letter-spacing:0;text-decoration:none;white-space:nowrap;clip-path:polygon(11px 0,100% 0,100% 100%,11px 100%,0 50%)}
.post-tag::before{content:"";position:absolute;left:10px;top:50%;width:5px;height:5px;margin-top:-2.5px;border-radius:50%;background:var(--paper)}
a.post-tag:hover{background:var(--ink);color:var(--paper);text-decoration:none}
a.post-tag:focus-visible{outline:2px solid var(--accent);outline-offset:3px;clip-path:none}
/* Home and category lists: the tags under the summary. On a phone the category takes a line of its own above
   the date, so the date and the status labels keep their room beside a small image and the title is not squeezed. */
.post-tags{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}
@media(max-width:599px){.post-list:not(.tag-list) .post-meta{row-gap:7px}.post-list:not(.tag-list) .post-meta .post-kicker{flex-basis:100%}}
/* End of an article: one labelled row for the category, one for the tags. */
.post-taxonomy{display:grid;gap:12px;margin:48px 0 0;font-family:var(--reader-body-font,var(--blog-font));font-weight:400}
.tax-row{display:flex;align-items:baseline;gap:14px;min-width:0}
.tax-label{flex:none;min-width:2.4em;color:var(--muted);font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));letter-spacing:.04em}
.tax-row:lang(en) .tax-label{min-width:4.9em;letter-spacing:.01em}
.post-taxonomy .post-category{color:var(--ink);font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));font-weight:400;text-decoration:none}
.post-taxonomy .post-category:hover{color:var(--accent);text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:.3em}
.tax-tags{display:flex;flex-wrap:wrap;gap:8px;min-width:0}
/* Everything that leaves the article in one place: Previous and Next, then All articles and Subscribe as buttons. */
.post-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(0,1fr));gap:12px;margin:22px 0 8px;font-family:var(--blog-font)}
.post-action{appearance:none;display:flex;align-items:center;justify-content:center;min-height:48px;padding:0 16px;border:1px solid var(--ink);border-radius:6px;background:none;color:var(--ink);font-family:var(--blog-font);font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)));font-weight:600;line-height:1.3;text-align:center;text-decoration:none}
.post-actions .post-action:hover{background:var(--soft);text-decoration:none}
.post-action.is-main,.post-actions .post-action.is-main{background:var(--ink);color:var(--paper)}
.post-actions .post-action.is-main:hover,.subscribe-form .post-action.is-main:hover{background:var(--ink-2)}
.post-action:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
/* Contents panel: All articles sits to the right of Previous and Next. */
.toc-leave{grid-template-columns:minmax(0,1fr) auto;column-gap:16px}
.toc-leave a:not(.is-all){grid-column:1}
.toc-leave a.is-all{grid-column:2;grid-row:1;align-self:start;display:inline-flex;align-items:center;min-height:44px;padding:0 12px;border:1px solid var(--line);border-radius:6px;font-weight:600;white-space:nowrap}
.toc-leave a.is-all:hover{border-color:var(--ink)}
/* Tags page: a search box, an index of every tag in use, then each tag with its articles. */
.tag-tools{margin:4px 0 0}
.tag-search{display:grid;gap:8px;margin:0 0 20px}
.tag-search-label{color:var(--muted);font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));font-family:var(--blog-font)}
.tag-search input{appearance:none;width:100%;min-height:48px;margin:0;padding:0 14px;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink);font:calc(16px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font)}
.tag-search input::placeholder{color:var(--muted);opacity:1}
.tag-search input:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-color:var(--ink)}
.tag-index{display:flex;flex-wrap:wrap;gap:8px}
.tag-n{color:var(--muted);font-size:calc(12px * var(--text-factor,var(--text-zoom-scale,1)));font-variant-numeric:tabular-nums}
a.post-tag:hover .tag-n{color:inherit}
.post-tag.is-dim{opacity:.4}
.tag-empty{margin:24px 0 0;color:var(--muted);font-family:var(--blog-font)}
.tag-group[hidden],.tag-empty[hidden]{display:none}
.tag-group .post-year{margin:40px 0 12px}
.post-year .post-tag.is-heading{min-height:30px;font-size:calc(15px * var(--text-factor,var(--text-zoom-scale,1)))}
/* Dev only: an article without its banner shows the picture frame in paper colours, never a broken image. */
.cover-ph{display:grid;box-sizing:border-box;width:100%;aspect-ratio:2/1;padding:4%;background:#F7F4EF;color:#6B665C}
.ph-in{display:grid;place-content:center;justify-items:center;gap:10px;min-width:0;background:#EFEBE3}
.ph-mark{width:clamp(26px,9vw,60px);height:auto;aspect-ratio:19.2/13.8;color:#C9C3B8}
.ph-label{font:500 calc(13px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font);letter-spacing:.06em}
.post-cover.is-placeholder{background:#F7F4EF}
a.is-placeholder,a.is-placeholder:hover{text-decoration:none}
.post-cover .cover-ph{width:min(100%,1600px,140vh,calc(200vh - 460px));max-height:min(70vh,calc(100vh - 230px));margin-inline:auto}
.cover-ph-thumb{padding:5%}
.cover-ph-thumb .ph-label{display:none}
.cover-ph-thumb .ph-mark{width:26%}
/* Subscribe (dev preview): an email address and a language. */
.subscribe-form{display:grid;gap:18px;max-width:520px;margin:0 0 56px;font-family:var(--blog-font)}
.sf-field{display:grid;gap:8px}
.sf-label{padding:0;color:var(--muted);font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)))}
.sf-field input{appearance:none;width:100%;min-height:48px;margin:0;padding:0 14px;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink);font:calc(16px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font)}
.sf-field input::placeholder{color:var(--muted);opacity:1}
.sf-field input:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-color:var(--ink)}
.sf-lang{min-width:0;margin:0;padding:0;border:0}
.sf-lang legend{margin-bottom:8px}
.sf-choices{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.sf-choice{position:relative;display:block}
.sf-choice input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
.sf-choice span{display:flex;align-items:center;justify-content:center;min-height:48px;border:1px solid var(--line);border-radius:6px;color:var(--ink);font-size:calc(16px * var(--text-factor,var(--text-zoom-scale,1)))}
.sf-choice input:checked+span{background:var(--soft);border-color:var(--ink);box-shadow:inset 0 -2px var(--ink)}
.sf-choice input:focus-visible+span{outline:2px solid var(--accent);outline-offset:2px}
.subscribe-form .post-action{width:100%;font-family:inherit;cursor:pointer}
.sf-note{min-height:1.6em;margin:0;color:var(--muted);font-size:calc(15px * var(--text-factor,var(--text-zoom-scale,1)))}
.subscribe-page .sub-h{margin:0 0 12px;font-size:calc(22px * var(--text-factor,var(--text-zoom-scale,1)))}
/* Footer, dev: Subscribe and Archive at the left, the icons at the right. */
.blog-footer-links{display:inline-flex;align-items:center;gap:18px}
.blog-footer-links a{display:inline-flex;align-items:center;min-height:44px}
/* Phones: the link home is the mark and the name, not the whole row (山山 11/9). */
@media(max-width:599px){.blog-header .blog-name{flex:0 1 auto}}

/* Shared shell navigation, one-tap keys, menu and subscription panel (11/9).
   Navigation follows the reader's typeface at regular weight; transient messages use the UI face. */
.site-nav,.menu-toggle,.lang-glyph{display:none}
.site-nav{font:400 calc(15px * var(--text-factor,var(--text-zoom-scale,1)))/1.2 var(--reader-body-font,var(--blog-font))}
@media(width >= 1280px){
  .site-nav{display:flex;align-items:center;flex:none;gap:26px;margin:0 26px 0 auto}
  .site-nav :is(a,.nav-subscribe){appearance:none;display:inline-flex;align-items:center;gap:6px;min-height:30px;margin:0;padding:0;border:0;background:none;color:var(--ink);font:inherit;text-decoration:none;cursor:pointer;transition:color .3s var(--ease,ease)}
  .site-nav :is(a,.nav-subscribe):hover{color:var(--ink-2)}
  .site-nav a[aria-current]{color:var(--accent)}
  .site-nav :is(a,.nav-subscribe):focus-visible{outline:2px solid var(--accent);outline-offset:4px}
  .site-nav .ui-icon{width:16px;height:16px}
  .blog-header :is(.lang-toggle,.reader-toggle,.theme-cycle){font-family:var(--reader-body-font,var(--blog-font));font-weight:400}
}
/* Match the header icon selectors, including the stuck header, before setting sizes. */
.menu-toggle{--menu-icon:24px}
.header-stuck .menu-toggle{--menu-icon:34px}
@media(width < 1280px){
  .blog-header .menu-toggle{display:inline-grid;place-items:center;flex:none;width:44px;height:44px;margin:-10px calc((var(--menu-icon) - 44px) / 2) -10px auto;padding:0;border:0;border-radius:50%;background:none;color:var(--ink);cursor:pointer;-webkit-tap-highlight-color:transparent}
  .blog-header .menu-toggle svg.ui-icon{width:var(--menu-icon);height:var(--menu-icon)}
  .menu-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
  .reader-refresh{display:none!important}
}
.lang-toggle > svg{display:none}
.lang-toggle .lang-glyph{position:relative;display:block;flex:none;width:32px;height:27px}
.lang-glyph .lg-now,.lang-glyph .lg-other{position:absolute;padding:1px 2px;border-radius:3px;background:var(--paper);font:500 calc(12px * var(--text-factor,var(--text-zoom-scale,1)))/1 var(--blog-font);font-style:normal;letter-spacing:0;transition:transform .16s cubic-bezier(.4,0,.2,1),color .16s}
.lang-glyph .lg-now{left:0;top:0;z-index:1;color:var(--ink)}
.lang-glyph .lg-other{right:0;bottom:0;color:var(--muted)}
:root:lang(zh) .lang-glyph .lg-now,:root:lang(en) .lang-glyph .lg-other{font-size:calc(13px * var(--text-factor,var(--text-zoom-scale,1)))}
.lang-glyph.is-swapping .lg-now{transform:translate(13px,12px);z-index:0;color:var(--muted)}
.lang-glyph.is-swapping .lg-other{transform:translate(-13px,-12px);z-index:1;color:var(--ink)}
.theme-cycle svg.is-turning{animation:key-turn .24s cubic-bezier(.2,.7,.2,1)}
@keyframes key-turn{from{opacity:0;transform:rotate(-70deg) scale(.6)}to{opacity:1;transform:none}}
.site-menu{position:fixed;inset:0 0 0 auto;width:min(340px,100vw);max-width:100vw;height:100dvh;max-height:100dvh;margin:0;padding:0;border:0;border-left:1px solid var(--line);background:var(--paper);color:var(--ink);font:400 calc(16px * var(--text-factor,var(--text-zoom-scale,1)))/1.5 var(--reader-body-font,var(--blog-font));overflow:auto;overscroll-behavior:contain}
.site-menu:not([open]){display:none}
.site-menu::backdrop{background:rgba(0,0,0,.4)}
.site-menu-in{display:flex;flex-direction:column;box-sizing:border-box;min-height:100%;padding:12px 22px calc(22px + env(safe-area-inset-bottom,0px))}
.site-menu-head{display:flex;align-items:center;justify-content:space-between;margin:0 -10px 6px 0}
.site-menu-title{margin:0;color:var(--muted);font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)));letter-spacing:.04em}
.site-menu-close{display:inline-grid;place-items:center;width:44px;height:44px;padding:0;border:0;background:none;color:var(--ink);font:inherit;cursor:pointer}
.site-menu-close .ui-icon{width:24px;height:24px}
.site-menu-go ul{list-style:none;margin:0;padding:0}
.site-menu-go li{margin:0;padding:0}
.site-menu-go > ul > li:not(.site-menu-cats) > :is(a,.site-menu-subscribe){appearance:none;display:flex;align-items:center;gap:10px;min-height:52px;margin:0;padding:0;border:0;background:none;color:var(--ink);font:inherit;font-size:calc(21px * var(--text-factor,var(--text-zoom-scale,1)));font-weight:400;letter-spacing:-.01em;text-decoration:none;cursor:pointer}
.site-menu-go > ul > li > a[aria-current],.site-menu-go .site-menu-cats a[aria-current]{color:var(--accent)}
.site-menu-go .ui-icon{width:20px;height:20px}
.site-menu-go .site-menu-cats{display:flex;flex-wrap:wrap;gap:0 20px;margin:0 0 6px;padding:0 0 8px}
.site-menu-cats a,.site-menu-cats span{display:inline-flex;align-items:center;min-height:44px;color:var(--ink-2);font-size:calc(17px * var(--text-factor,var(--text-zoom-scale,1)));text-decoration:none}
.site-menu-cats span[aria-disabled]{opacity:.4}
.site-menu-acts{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:14px 0 0;padding:16px 0 0;border-top:1px solid var(--line)}
.site-menu-acts button{display:flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:0 10px;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink);font:inherit;font-size:calc(15px * var(--text-factor,var(--text-zoom-scale,1)));line-height:1.3;cursor:pointer}
.site-menu-acts .ui-icon{width:18px;height:18px}
.site-menu-acts button:hover{background:var(--soft)}
.site-menu-out{display:flex;flex-wrap:wrap;align-items:center;gap:4px 22px;margin:10px 0 0}
.site-menu-out a{display:inline-flex;align-items:center;gap:8px;min-height:44px;color:var(--ink-2);font-size:calc(15px * var(--text-factor,var(--text-zoom-scale,1)));text-decoration:none}
.site-menu-out :is(.ui-icon,.ic-mx){width:18px;height:18px;flex:none}
.site-menu-out .is-dev{color:var(--muted)}
.site-menu-out .is-dev small{padding:1px 6px;border:1px solid var(--line);border-radius:3px;font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)))}
.site-menu :is(a,button):focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.site-toast{position:fixed;left:50%;bottom:calc(84px + env(safe-area-inset-bottom,0px));z-index:60;max-width:calc(100vw - 32px);padding:8px 14px;border-radius:18px;background:var(--ink);color:var(--paper);font:calc(14px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font);text-align:center;opacity:0;transform:translate(-50%,8px);pointer-events:none;transition:opacity .18s,transform .18s}
.site-toast[data-on]{opacity:1;transform:translate(-50%,0)}
.subscribe-panel .sub-lead{margin:0 0 16px;color:var(--ink-2)}
.subscribe-panel .sub-way{display:flex;align-items:center;gap:16px}
.subscribe-panel .sub-link{display:inline-flex;align-items:center;gap:8px;min-height:44px;color:var(--accent)}
.subscribe-panel .sub-link .ui-icon{width:20px;height:20px}
.subscribe-panel .sub-copy{appearance:none;flex:none;margin-left:auto;min-height:44px;padding:0 12px;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink);font:400 calc(14px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font);cursor:pointer}
.subscribe-panel .sub-copy:hover{background:var(--soft)}
.subscribe-panel .sub-note{margin:8px 0 16px;color:var(--muted);font-size:calc(14px * var(--text-factor,var(--text-zoom-scale,1)))}
.subscribe-panel .sub-soon{margin:0;padding-top:16px;border-top:1px solid var(--line);color:var(--ink);font-size:calc(15px * var(--text-factor,var(--text-zoom-scale,1)))}
.subscribe-panel :is(.sub-link,.sub-copy):focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.blog-footer-links .footer-subscribe{appearance:none;display:inline-flex;align-items:center;min-height:44px;margin:0;padding:0;border:0;background:none;color:var(--accent);font:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.2em;cursor:pointer}
.blog-footer-links .footer-subscribe:hover{text-decoration-thickness:2px}
.blog-footer-links .footer-subscribe:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
button.post-action{font-family:inherit;cursor:pointer}
.prose .post-cta{margin:40px 0 0}
.prose .post-cta .post-action{text-decoration:none}
/* A figure's sources and licence: a line of its own under the caption, one size down. */
.prose figcaption .credit{display:block;margin-top:.35em;font-size:calc(calc(14px * var(--reader-scale)) * var(--text-factor,var(--text-zoom-scale,1)))}
/* 11/10: phone contents sheet. The section list keeps one height whatever the neighbours' titles are; the head and the
   previous/next block take what they need and the sheet grows upward (he corrected the first attempt at 02:46). */
.toc-pop .toc-leave .t{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
/* 11/11: the phone sheet's heights (as tall as the screen allows, the list keeping one height) are in toc.css. */
/* 11/10: second-level headings carry a short accent bar (he chose it over colouring the whole line) */
.prose h3{padding-bottom:.34em;background:linear-gradient(var(--accent),var(--accent)) left bottom/2.4em 2px no-repeat}
@media(prefers-reduced-motion:reduce){
  .site-nav :is(a,.nav-subscribe),.site-toast,.lang-glyph .lg-now,.lang-glyph .lg-other{transition:none}
  .theme-cycle svg.is-turning{animation:none}
}
/* 11/10: image viewer (click a figure to see it full screen; buttons as on the main site) */
/* Append to reader-v11.css. Only new lightbox selectors. */
.image-viewer-trigger { cursor: zoom-in; }
.image-viewer-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.image-viewer {
  position: fixed; inset: 0; box-sizing: border-box; width: 100vw; max-width: none;
  height: 100vh; height: 100dvh; max-height: none; margin: 0; padding: 0; border: 0;
  background: var(--paper); color: var(--ink); overflow: hidden; overscroll-behavior: contain;
  font: 400 calc(14px * var(--text-factor,var(--text-zoom-scale,1)))/1.4 var(--blog-font);
}
.image-viewer:not([open]) { display: none; }
.image-viewer::backdrop { background: var(--paper); }
.image-viewer-image {
  position: absolute; inset: max(80px, calc(64px + env(safe-area-inset-top, 0px))) 84px max(150px, calc(134px + env(safe-area-inset-bottom, 0px))) 16px;
  display: block; width: calc(100% - 100px); height: calc(100% - max(80px, calc(64px + env(safe-area-inset-top, 0px))) - max(150px, calc(134px + env(safe-area-inset-bottom, 0px))));
  max-width: none; max-height: none; margin: 0; padding: 0; object-fit: contain; cursor: zoom-out;
  touch-action: auto;
}
.image-viewer-button {
  appearance: none; display: grid; place-items: center; flex: none; box-sizing: border-box;
  width: 52px; height: 52px; min-width: 44px; min-height: 44px; margin: 0; padding: 0;
  border: 1px solid var(--line); border-radius: 50%; background: var(--soft); color: var(--ink);
  text-decoration: none; cursor: pointer;
}
.image-viewer-button:hover { background: var(--ink); color: var(--paper); }
.image-viewer-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.image-viewer-button svg { display: block; width: 24px; height: 24px; }
.image-viewer-back { position: absolute; top: max(16px, env(safe-area-inset-top, 0px)); left: max(16px, env(safe-area-inset-left, 0px)); }
.image-viewer-actions { position: absolute; right: max(16px, env(safe-area-inset-right, 0px)); bottom: max(20px, env(safe-area-inset-bottom, 0px)); display: grid; gap: 12px; }
.image-viewer-caption { position: absolute; left: max(16px, env(safe-area-inset-left, 0px)); right: 84px; bottom: max(20px, env(safe-area-inset-bottom, 0px)); max-height: 110px; overflow: auto; overflow-wrap: anywhere; margin: 0; color: var(--muted); }
.image-viewer-caption[hidden] { display: none; }
/* 11/10: phones. Full-width picture; a very tall figure scrolls at full width and the buttons stay put. */
@media (max-width: 699px) {
  .image-viewer-image { right: 16px; width: calc(100% - 32px); }
  .image-viewer.is-tall { overflow-y: auto; }
  .image-viewer.is-tall .image-viewer-image { position: static; display: block; width: calc(100% - 32px); height: auto; margin: max(80px, calc(64px + env(safe-area-inset-top, 0px))) 16px 16px; object-fit: fill; }
  .image-viewer.is-tall .image-viewer-caption { position: static; max-height: none; overflow: visible; margin: 0 84px calc(40px + env(safe-area-inset-bottom, 0px)) 16px; }
  .image-viewer.is-tall .image-viewer-back, .image-viewer.is-tall .image-viewer-actions { position: fixed; }
}
.image-viewer .image-viewer-toast { bottom: calc(150px + env(safe-area-inset-bottom, 0px)); }
@media (prefers-reduced-motion: reduce) {
  .image-viewer, .image-viewer *, .image-viewer::backdrop { animation: none; transition: none; scroll-behavior: auto; }
}
/* 11/10: desktop header (from 1280px): mark at the far left, nav and tools at the far right, always on top, never compact */
/* 追加到 reader-v11.css 末尾；必须配套替换 js/rail-position.js。
   桌面脚本保持展开状态，不添加 header-stuck，沿用原来的高度、字号和图标。
   所有规则仅在 1280px 起生效；未使用 !important。 */
@media (min-width: 1280px) {
  /* 覆盖居中列与隐藏位移；header-slot 仍由脚本按实测高度占位。
     第二个选择器也覆盖 header-stuck.header-hidden 的旧 transform 规则。 */
  :root .blog-header,
  :root.header-stuck .blog-header {
    position: fixed;
    inset: 0 0 auto;
    box-sizing: border-box;
    width: 100%;
    max-width: none;
    margin: 0;
    padding-inline: 28px;
    transform: translateY(0);
  }

  /* 不让站名拉伸、压缩或省略；余量交给导航左侧的 auto margin。 */
  :root .blog-header .blog-name {
    flex: 0 0 auto;
    overflow: visible;
    white-space: nowrap;
  }

  :root .blog-header .blog-name-text {
    overflow: visible;
    white-space: nowrap;
  }

  :root .blog-header .site-nav {
    margin-left: auto;
  }

  /* 保留封面下缘的避让，同时确保目录始终在常驻页头下方。
     明确可用高度，继续让 rail-list 自己滚动。 */
  :root .rail {
    --desktop-rail-top: max(var(--sticky-header-height, 105px), var(--rail-top, 0px));
    box-sizing: border-box;
    top: var(--desktop-rail-top);
    height: calc(100dvh - var(--desktop-rail-top));
    max-height: calc(100dvh - var(--desktop-rail-top));
  }

  /* 原来的标题 scroll-margin-top 保持有效；补上文章本身的锚点。 */
  :root .prose[id] {
    scroll-margin-top: calc(var(--sticky-header-height, 105px) + 24px);
  }

  /* 阅读、语言、颜色和订阅面板都使用 reader-panel，随工具贴右。 */
  :root .reader-panel {
    inset: calc(var(--sticky-header-height, 105px) + 12px) 28px auto auto;
  }

  /* 从窄屏带过来的已打开菜单，也给常驻页头留出空间。 */
  :root .site-menu {
    top: var(--sticky-header-height, 105px);
    height: calc(100dvh - var(--sticky-header-height, 105px));
    max-height: calc(100dvh - var(--sticky-header-height, 105px));
  }
}
/* 11/10: tags also at the top of an article, after the date: small, no chip, weaker than the category */
/* Article top only; the parent meta row supplies the date's type, colour and spacing. */
.post-meta:has(>.post-tags-top){flex-wrap:wrap;row-gap:8px}
.post-meta>.post-tags-top{display:inline-flex;flex:0 1 auto;flex-wrap:wrap;align-items:baseline;max-width:100%;min-width:0;column-gap:inherit;row-gap:8px;color:inherit;font:inherit}
.post-tags-top>a.post-tag-top{display:inline-flex;flex:none;align-items:center;box-sizing:border-box;min-height:44px;padding:14px 0;margin:-14px 0;border:0;background:none;color:var(--muted);font:inherit;letter-spacing:inherit;text-decoration:none;white-space:nowrap}
.post-tags-top>a.post-tag-top:hover{text-decoration:underline;text-underline-offset:.3em}

/* End mark (山山 11/6; 11/11 he picked the mountain from the header mark instead of the M): right after an article's last sentence, as tall as the text, in the
   accent colour. build_blog.add_end_mark puts has-end-mark on that paragraph. The mark hangs on the no-break tail the
   widont script makes, so it never drops to a line of its own; without that tail it follows the paragraph. */
:root{--end-mark:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='2.4 5.8 19.2 13.8'%3E%3Cpath d='M3 19 9.4 6.4 13.1 13.5 15.4 9.8 21 19Z'/%3E%3C/svg%3E")}
.prose p.has-end-mark .blog-tail:last-child::after{content:"";display:inline-block;width:.94em;height:.68em;margin-left:.3em;vertical-align:-.02em;background:var(--accent);-webkit-mask:var(--end-mark) center/contain no-repeat;mask:var(--end-mark) center/contain no-repeat;-webkit-print-color-adjust:exact;print-color-adjust:exact}
.prose p.has-end-mark:not(:has(.blog-tail))::after{content:"";display:inline-block;width:.94em;height:.68em;margin-left:.3em;vertical-align:-.02em;background:var(--accent);-webkit-mask:var(--end-mark) center/contain no-repeat;mask:var(--end-mark) center/contain no-repeat;-webkit-print-color-adjust:exact;print-color-adjust:exact}
html:lang(zh) .prose p.has-end-mark .blog-tail:last-child::after{margin-left:.12em}
html:lang(zh) .prose p.has-end-mark:not(:has(.blog-tail))::after{margin-left:.12em}
/* Home shows the newest four; the way to the rest is a button like the ones under an article (山山 11/10). */
.post-more{margin:28px 0 0}
.post-more .post-action{width:100%}
.post-more .post-action:hover{background:var(--soft);text-decoration:none}
@media(min-width:700px){.post-more .post-action{display:inline-flex;width:auto;min-width:220px}}

/* 11/11: share at the top right too (the menu keeps share and refresh). Wide screens: after the colour mode, the look of
   the header tools. Under 1280px, where the menu button shows: an icon beside it, the label for screen readers only. */
.page-share{position:relative;display:inline-flex;align-items:center;justify-content:center;flex:none;gap:.35em;margin:0;padding:0;border:0;border-radius:0;min-width:30px;min-height:30px;height:30px;background:none;color:var(--ink);font:inherit;cursor:pointer;}
.page-share svg{width:18px;height:18px;flex:none;}
.page-share:hover{color:var(--ink-2);}
.page-share:focus-visible{outline:2px solid var(--accent);outline-offset:4px;}
@media(width < 1280px){
 .blog-header .page-share{width:44px;height:44px;min-height:44px;margin:-10px 0 -10px auto;border-radius:50%;}
 .blog-header .page-share svg{width:22px;height:22px;}
 .header-stuck .blog-header .page-share svg{width:26px;height:26px;}
 .blog-header .page-share .ps-label{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}
 .blog-header .page-share + .menu-toggle{margin-left:2px;}
}

/* 11/11: the share label follows the reading typeface, as the header tools beside it do */
.blog-header .page-share{font-family:var(--reader-body-font,var(--blog-font));font-weight:400}
