/* The eight fonts a book may use, all SIL Open Font License 1.1, all local (demo/static/fonts, see SOURCES.json).
   They are only fetched when a page actually uses them, and the PDF stage embeds the same files. */
@font-face{font-family:"Noto Sans SC";src:url(/static/fonts/NotoSansSC-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"Noto Serif SC";src:url(/static/fonts/NotoSerifSC-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"Ma Shan Zheng";src:url(/static/fonts/MaShanZheng-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"ZCOOL XiaoWei";src:url(/static/fonts/ZCOOLXiaoWei-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"Inter";src:url(/static/fonts/Inter-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"Playfair Display";src:url(/static/fonts/PlayfairDisplay-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"Great Vibes";src:url(/static/fonts/GreatVibes-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
@font-face{font-family:"Bebas Neue";src:url(/static/fonts/BebasNeue-Regular.ttf) format("truetype");font-weight:400;font-display:swap}
/* Motion: transform and opacity only, one easing, durations defined once here. Reduced motion sets them all to 0. */
:root{--ease:cubic-bezier(.2,.7,.2,1);--t-fast:120ms;--t-hover:200ms;--t-drop:260ms;--t-flip:320ms;--t-deal:360ms;--t-dot:400ms;--t-slot:240ms;--t-book:240ms;--t-pick:360ms;--t-turn:420ms}
@media (prefers-reduced-motion:reduce){:root{--t-fast:0ms;--t-hover:0ms;--t-drop:0ms;--t-flip:0ms;--t-deal:0ms;--t-dot:0ms;--t-slot:0ms;--t-book:0ms;--t-pick:0ms;--t-turn:0ms}}
*{box-sizing:border-box;margin:0;padding:0}
html,body{background:#FFFFFF}
/* D18-FIX-SMALL (audit 31): html takes the cream palette.css gives body, so no white band shows under a short page; a page without the palette (no --site-page), a print and a preview stay white */
@media screen{html:has(> body:not(.printing):not(.preview)){background-color:var(--site-page,#FFFFFF)}}
body{color:#000000;font:400 13px/1.5 "Helvetica Neue",Arial,"Noto Sans SC",sans-serif}
[hidden]{display:none!important}
a{color:#000000;text-decoration:none;text-underline-offset:4px;cursor:pointer}
a:hover{text-decoration:underline}
a.off{color:#707070;pointer-events:none}
.grey,.grey a{color:#707070}
.u{font-size:12px;letter-spacing:.1em;text-transform:uppercase}
.u11{font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.wrap{max-width:1440px;margin:0 auto;padding:0 48px}
.nav{height:48px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;border-bottom:1px solid #E5E5E5}
.nav .mid{display:flex;column-gap:36px}
.nav .right{text-align:right}
main{margin-top:48px}
section+section{margin-top:96px}
h1{font-size:22px;font-weight:400;line-height:1.25}
.sub{font-size:13px;color:#707070;margin-top:12px}
.sub.black{color:#000000}
.actions{margin-top:20px;display:flex;column-gap:32px}
.content{margin-top:32px}
.between{display:flex;justify-content:space-between;align-items:baseline;column-gap:32px}
.grid{display:grid;grid-template-columns:repeat(6,1fr);gap:16px;margin-top:12px;max-height:calc((min(100vw,1440px) - 176px) / 6 * 1.25 * 2 + 16px);overflow-y:auto;scrollbar-width:thin;scrollbar-gutter:stable}
.ph{position:relative;aspect-ratio:4/5;background:#FFFFFF;transition:opacity var(--t-hover) var(--ease);touch-action:none}
.ph img{width:100%;height:100%;object-fit:contain;display:block;user-select:none;-webkit-user-drag:none}
.ph:hover{opacity:.85}
.ph .rm,.ph .tag{position:absolute;left:0;right:0;bottom:0;text-align:center;padding:6px 0;background:#FFFFFF;opacity:0;transition:opacity var(--t-hover) var(--ease)}
.ph:hover .rm,.ph:hover .tag{opacity:1}
.ph .tag.binrow{display:flex;justify-content:space-between;align-items:baseline;column-gap:8px;padding:6px 8px;text-align:left}
.ph .tag.binrow .why{color:#707070;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.binph img{filter:grayscale(1)}
.shelf{margin-top:40px;text-align:center}
.shelf .cap{font-size:13px;color:#707070;margin-bottom:12px}
.shelf .line{height:1px;background:#000000}
#lastBatch{margin-top:20px}
footer{margin-top:96px;border-top:1px solid #E5E5E5;padding:16px 0;color:#707070}
footer a{color:#707070}
.opt{display:block;padding:24px 0}
.opt+.opt{margin-top:24px}
.opt:hover{text-decoration:none}
.opt:hover h1{text-decoration:underline;text-underline-offset:6px}
.picture{position:relative;height:60vh;min-height:480px;margin-top:24px;overflow:hidden}
.box{position:absolute;transform:translate(-50%,-50%);border:1px solid #000000;background:#FFFFFF;padding:2px 12px;white-space:nowrap;opacity:0;transition:opacity var(--t-hover) var(--ease)}
.box.on{opacity:1}
/* the sorting animation: 20px thumbnails of the actual photos; they fade in (120ms) and fly (400ms) by transform only */
.th{position:absolute;left:0;top:0;width:20px;height:20px;object-fit:cover;display:block;opacity:0;user-select:none;-webkit-user-drag:none;transition:transform var(--t-dot) var(--ease),opacity var(--t-fast) var(--ease)}
.th.on{opacity:1}
.th.gray{filter:grayscale(1)}
body.drag::after{content:"";position:fixed;inset:0;border:1px solid #000000;pointer-events:none}
/* ---- /result: piles, expanded pile, unsorted and bin ---- */
main.result section+section{margin-top:48px}
main.result .top{margin-bottom:32px}
.piles{display:flex;flex-wrap:wrap;gap:32px;align-items:flex-start}
.pile{width:200px;position:relative}
/* a pile since 06-3: real photos, 4:5 crops, no frames; the second and third photo peek out behind the cover and fan out on hover */
.stack{position:relative;width:200px;aspect-ratio:4/5;touch-action:none;cursor:pointer}
.stack .back,.stack .cover{position:absolute;inset:0;background:#FFFFFF;transition:transform var(--t-hover) var(--ease)}
.stack img{width:100%;height:100%;object-fit:cover;display:block;user-select:none;-webkit-user-drag:none}
.stack .back::after,.stack .cover::after{content:"";position:absolute;inset:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.08);pointer-events:none}
.stack .b1{transform:translate(6px,-4px) rotate(2.5deg)}
.stack .b2{transform:translate(-7px,5px) rotate(-3.5deg)}
.pile:hover .b1{transform:translate(10px,-8px) rotate(5.5deg)}
.pile:hover .b2{transform:translate(-11px,9px) rotate(-6.5deg)}
.pile .cap,.pile input.rename{margin-top:12px}
.pile .cap{touch-action:none;cursor:grab}
.pile .cap2{margin-top:4px}
.newpile{align-self:center}
.confirm,.mergeline{margin-top:20px}
#expanded .grid6{margin-top:20px}
.grid6{display:grid;grid-template-columns:repeat(6,1fr);gap:16px}
.cols2{display:grid;grid-template-columns:1fr 1fr;gap:32px}
.cols31{display:grid;grid-template-columns:3fr 1fr;gap:32px}
.col{position:relative}
.col .grid6,.col .rstack{margin-top:12px}
.grid6.drop{position:relative}
[data-drop]::after{content:"";position:absolute;inset:-6px;border:1px solid #000000;opacity:0;pointer-events:none;transition:opacity var(--t-fast) var(--ease)}
[data-drop].over::after{opacity:1}
body.dragging .ph:hover{opacity:1}
body.dragging .ph:hover .tag,body.dragging .ph:hover .rm{opacity:0}
.ghost{position:fixed;left:0;top:0;pointer-events:none;z-index:15;transform-origin:0 0}
.ghost-in{width:100%;height:100%;transform-origin:50% 50%;background:#FFFFFF}
.ghost-in img{width:100%;height:100%;object-fit:contain;display:block}
.ghost-in.u{white-space:nowrap;background:#FFFFFF;padding:2px 8px;width:auto;height:auto}
input.rename{font:inherit;font-size:12px;letter-spacing:.1em;text-transform:uppercase;border:0;border-bottom:1px solid #E5E5E5;outline:0;background:#FFFFFF;color:#000000;width:200px;padding:2px 0;display:block}
.rstack .opened{display:none}
.rstack.open .closed{display:none}
.rstack.open .opened{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.rph .grey{margin-top:6px}
/* ---- lightbox ---- */
#lightbox{position:fixed;inset:0;background:#FFFFFF;z-index:20;display:flex;align-items:center;justify-content:center}
#lightbox .lb-close{position:fixed;top:16px;right:48px}
#lightbox .lb-prev,#lightbox .lb-next{position:fixed;top:50%;transform:translateY(-50%);font-size:16px}
#lightbox .lb-prev{left:48px}
#lightbox .lb-next{right:48px}
#lightbox .lb-cap{position:fixed;left:0;right:0;bottom:16px;text-align:center}
/* ---- result: the two tabs under the headline, face boxes on hover in the people view ---- */
.tabs{margin-top:20px;display:flex;column-gap:28px;font-size:16px;letter-spacing:.1em;text-transform:uppercase;min-width:0}
.tabs a{white-space:nowrap}
[data-key=dateline]{white-space:nowrap;align-self:center}
.fbox{position:absolute;border:1px solid #000000;opacity:0;pointer-events:none;transition:opacity var(--t-hover) var(--ease)}
.ph:hover .fbox{opacity:1}
/* ---- result page since 06 (fixed in 06-2): a left albums sidebar and three bands that never scroll the page; each part scrolls internally ---- */
body.fixed{height:100vh;overflow:hidden}
body.fixed .wrap{height:100vh;display:flex;flex-direction:column}
body.fixed .nav{flex:none}
.shell{flex:1;min-height:0;display:flex}
.sidebar{flex:none;width:200px;min-height:0;display:flex;flex-direction:column;border-right:1px solid #E5E5E5;padding:16px 24px 16px 0}
.sidebar .sbhead{flex:none}
.sidebar .sblist{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;margin-top:16px;padding:2px 8px 2px 2px}
.sidebar .sbfoot{flex:none;padding-top:16px}
.album{width:120px;aspect-ratio:4/5;border:1px solid #E5E5E5;background:#FFFFFF;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;cursor:pointer;position:relative;transition:transform var(--t-hover) var(--ease)}
.album+.album{margin-top:12px}
.album.active{outline:1px solid #000000;outline-offset:-1px}
.album:hover{transform:translateY(-2px)}
.album .aname{padding:0 8px;overflow-wrap:anywhere}
.album .acount{margin-top:6px}
.album input.rename{width:104px;text-align:center}
main.bands{flex:1;min-width:0;min-height:0;margin:0 0 0 32px;display:grid;grid-template-rows:auto minmax(320px,1fr) 240px;overflow:hidden}
main.bands section+section{margin-top:0}
main.bands>section{min-width:0;max-width:100%}
#band1{padding:16px 0 24px;border-bottom:1px solid #E5E5E5}
#band1 .tabs{margin-top:0}
.b1row{display:flex;align-items:flex-start;margin-top:16px;min-width:0}
.b1row .selall{flex:none;width:88px;padding-top:80px}
.b1row .rowarrow{flex:none;margin-left:16px;padding-top:80px}
.pilesrow{flex:1;min-width:0;display:flex;flex-wrap:nowrap;gap:24px;align-items:flex-start;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;padding:2px 2px 2px 6px}
.pilesrow::-webkit-scrollbar{display:none}
.pilesrow .pile,.pilesrow .stack{width:140px;flex:none}
.pilesrow .pile .cap,.pilesrow .pile .cap2{width:140px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pilesrow .pile.open .cover{transform:translateY(-2px)}
.pilesrow .pile.open:hover .cover{transform:translateY(-2px)}
.pilesrow .newpile{flex:none;align-self:center;white-space:nowrap}
#band2{min-height:0;display:flex;flex-direction:column;padding:16px 0 12px;border-bottom:1px solid #E5E5E5}
#band2 #expanded{display:flex;flex-direction:column;min-height:0;flex:1}
#band2 .grid6{flex:1;min-height:0;overflow-y:auto;margin-top:16px;padding:6px 8px 6px 6px;scrollbar-width:thin;align-content:start}
#band2 .empty{margin-top:12px}
#band2 .confirm{margin:0 0 12px}
#band3{display:grid;grid-template-columns:1fr 1fr;gap:32px;padding-top:12px;min-height:0}
#band3 .col{display:flex;flex-direction:column;min-height:0;min-width:0}
#band3 .col .between{white-space:nowrap}
#band3 .rownav{flex:none;margin-left:16px}
#band3 .rownav a{margin-left:10px}
#band3 .rownav .counter{margin-left:12px}
#band3 .row{display:flex;flex-wrap:nowrap;gap:12px;overflow-x:auto;overflow-y:hidden;margin-top:10px;padding:2px 0 2px 6px;flex:1;min-height:0;scrollbar-width:none}
#band3 .row::-webkit-scrollbar{display:none}
#band3 .row .ph{flex:none;height:calc(100% - 4px);width:auto;aspect-ratio:1/1}
body.fixed #note{position:fixed;left:48px;bottom:8px;background:#FFFFFF}
/* album tags on photos and pile covers: white, hairline, 11px uppercase; the x shows on hover */
.atags{position:absolute;left:4px;top:4px;display:flex;flex-direction:column;align-items:flex-start;gap:2px;z-index:2}
.atag{display:inline-flex;align-items:center;gap:6px;background:#FFFFFF;border:1px solid #E5E5E5;padding:1px 6px;white-space:nowrap;line-height:1.4;color:#000000}
.atag.part,.atag.more{color:#707070}
.atag .x{display:none;font-style:normal;cursor:pointer;line-height:1}
.atag:hover .x{display:inline}
.stack .cover .atags{pointer-events:auto}
/* lightbox since 06-2: the current photo slides out while the next slides in (transform only); the caption fades */
#lightbox .lb-stage{position:fixed;inset:0;overflow:hidden}
#lightbox .lb-stage img{position:absolute;left:5vw;top:5vh;width:90vw;height:90vh;object-fit:contain;display:block;transform-origin:0 0;user-select:none;-webkit-user-drag:none;touch-action:pan-y}
/* ---- album preview (work order 07): inside a .page everything is millimetres or per cent of the page, never viewport units;
       the screen only scales the whole spread, so the same DOM prints at 1:1 ---- */
.mmprobe{position:absolute;left:-9999px;top:0;width:100mm;height:1mm}
body.album main{margin-top:24px;padding-bottom:64px}
body.album #head{margin-bottom:24px}
.spreadbox{position:relative;margin:0 auto 48px}
.spread{position:absolute;left:0;top:0;display:flex;transform-origin:top left}
.spread.two::after{content:"";position:absolute;left:50%;top:0;bottom:0;width:1px;background:#E5E5E5}
.page{position:relative;width:var(--pw);height:var(--ph);flex:none;overflow:hidden;background:#FFFFFF;outline:1px solid #E5E5E5;outline-offset:-1px;font-family:"Noto Sans SC",sans-serif}   /* 页面里只用打包字体，PDF 不依赖系统字体 */
.page .slot{position:absolute;overflow:hidden;background:#FFFFFF}
.page .slot img{width:100%;height:100%;display:block;user-select:none;-webkit-user-drag:none}
.page .slot.blank{outline:1px solid #E5E5E5;outline-offset:-1px}
.page .pbg{position:absolute;inset:0;z-index:0}
.page .slot{z-index:1}
/* A text box carries its own font, size, colour and spacing (work order 07-3); the page only positions it. */
.page .deco{position:absolute;z-index:2}
/* the decoration layer (work order 09): ours, never the model's */
.page .deco.perf{background-repeat:repeat-x,repeat-x,repeat-y,repeat-y;background-position:0 -1.1mm,0 100%,-1.1mm 0,100% 0;
                 background-size:var(--perf) 2.2mm,var(--perf) 2.2mm,2.2mm var(--perf),2.2mm var(--perf);z-index:3}
.page .deco.torn{z-index:1}
.page .deco.paper{z-index:0}      /* 纸是照片的底，不能盖在照片上 */
.page .deco.stampmark{background-repeat:no-repeat;background-size:contain;background-position:center;z-index:3}
.page .tx{position:absolute;z-index:3;white-space:pre-wrap;overflow-wrap:break-word;outline:1px solid transparent;outline-offset:2px}
body.editor:not(.preview) .tx:hover{outline-color:#E5E5E5}
body.editor:not(.preview) .tx.sel{outline-color:#000000}
body.editor:not(.preview) .tx.editing{outline-color:#000000;cursor:text;caret-color:#000000}
.txh{position:absolute;z-index:4;width:5px;margin-left:-3px;background:#000000;cursor:ew-resize}
.snapv,.snaph{position:absolute;z-index:5;background:#000000;opacity:0;pointer-events:none}
.snapv{top:0;bottom:0;width:1px;left:-99mm}
.snaph{left:0;right:0;height:1px;top:-99mm}
.snapv.on,.snaph.on{opacity:1}
/* FIT / FILL: only ever on screen, never in a preview and never in the PDF */
.slot .fitfill{position:absolute;left:0;right:0;bottom:0;z-index:3;display:flex;flex-wrap:wrap;justify-content:center;column-gap:12px;row-gap:2px;padding:5px 6px;background:#FFFFFF;opacity:0;transition:opacity var(--t-hover) var(--ease)}
.slot .fitfill b{font-weight:400;color:#707070;margin-left:6px}
.slot:hover .fitfill{opacity:1}
.slot .fitfill a{color:#707070}
.slot .fitfill a.on{color:#000000;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}
body.preview .fitfill,body.preview .txh,body.preview .snapv,body.preview .snaph{display:none}
.page .pnum{position:absolute;bottom:6mm;font-size:2.6mm;letter-spacing:.1em;color:#707070}
.page .pnum.left{left:14mm}
.page .pnum.right{right:14mm}
/* ---- album editor (work order 07-2): top bar, rail, panel, canvas, page overview; pages keep their millimetres ---- */
body.editor{height:100vh;overflow:hidden}
body.editor .ewrap{height:100vh;display:flex;flex-direction:column;max-width:none;padding:0}
.topbar{flex:none;height:48px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;column-gap:24px;padding:0 24px;border-bottom:1px solid #E5E5E5;white-space:nowrap;overflow:hidden}
.topbar .tleft{justify-self:start;display:flex;align-items:baseline;column-gap:16px}
.topbar .tmid{justify-self:center;display:flex;align-items:center;column-gap:12px}
.topbar .tacts{justify-self:end;display:flex;align-items:center;column-gap:16px}
.topbar .ename{cursor:text}
.topbar input.rename{width:180px}
.zoom{display:flex;align-items:center;column-gap:8px}
.zoom input[type=range]{width:90px;accent-color:#000000;color:#000000}
.ebody{flex:1;min-height:0;display:flex}
.rail{flex:none;width:104px;border-right:1px solid #E5E5E5;display:flex;flex-direction:column;row-gap:18px;padding:20px 8px;align-items:center;text-align:center}
.rail a{white-space:nowrap}
.rail a.on{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:4px}
.panel{flex:none;width:300px;border-right:1px solid #E5E5E5;display:flex;flex-direction:column;min-height:0;padding:16px 16px 16px 20px}
.panel .phead{flex:none;margin-bottom:12px}
.panel .pbody{flex:1;min-height:0;overflow-y:auto;scrollbar-width:thin;padding-right:6px;position:relative}
.pgroup+.pgroup{margin-top:16px}
.pgrid,.tgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:8px}
.pphoto{position:relative;aspect-ratio:1/1;background:#FFFFFF;cursor:grab;touch-action:none}
.pphoto img{width:100%;height:100%;object-fit:cover;display:block;user-select:none;-webkit-user-drag:none}
.pphoto.isused img{opacity:.55}
.pphoto .used{position:absolute;left:4px;bottom:4px;font-size:9px;line-height:1.6;letter-spacing:.08em;text-transform:uppercase;color:#707070;background:#FFFFFF;padding:0 3px}
.pbody>.u11{margin-top:16px}
.pbody>.u11:first-child{margin-top:0}
.ctl{display:flex;align-items:center;column-gap:10px;margin-top:10px}
.ctl.col{display:block}
.ctl>span{flex:none;width:52px}
.ctl input[type=range]{flex:1;min-width:0;accent-color:#000000;color:#000000}
.ctl b{font-weight:400;width:36px;text-align:right}
.panel select{flex:1;min-width:0;border:1px solid #E5E5E5;background:#FFFFFF;color:#000000;font:inherit;font-size:12px;padding:4px 6px}
.swatches{display:grid;grid-template-columns:repeat(6,1fr);gap:6px;margin-top:8px}
.sw{height:20px;outline:1px solid #E5E5E5;outline-offset:-1px;cursor:pointer}
.sw.on{outline:1px solid #000000;outline-offset:2px}
.hex{width:100%;margin-top:8px;border:1px solid #E5E5E5;background:#FFFFFF;color:#000000;padding:4px 6px;font:inherit;font-size:11px;letter-spacing:.1em;text-transform:uppercase}
.seg{display:flex;column-gap:14px}
.seg.wide{margin:6px 0 0}
.seg a{color:#707070}
.seg a.on{color:#000000;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:4px}
.bggrid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:8px}
.bgtile{display:block;height:44px;outline:1px solid #E5E5E5;outline-offset:-1px;cursor:pointer}
.bgtile.on{outline:1px solid #000000;outline-offset:2px}
.tline{display:block;margin-top:8px;color:#707070}
.tline:hover{color:#000000}
.tline.on{color:#000000;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:4px}
.theme{cursor:pointer;margin-top:14px}
.theme .strip{display:flex;column-gap:2px;aspect-ratio:3/1;overflow:hidden;outline:1px solid #E5E5E5;outline-offset:-1px;margin-bottom:6px}
.theme .strip i{flex:1;min-width:0;background-size:cover;background-position:center;display:block}
.theme.on .strip{outline:1px solid #000000;outline-offset:2px}
/* the EFFECTS popover (work order 07-4): editor chrome, never part of a page, never printed */
.fxpop{position:fixed;z-index:40;width:256px;background:#FFFFFF;border:1px solid #E5E5E5;padding:12px 14px 10px}
.fxpop .between{margin-bottom:6px}
.fxpop .ctl{margin-top:8px}
.fxpop .ctl>span{width:52px}
.fxpop .seg{flex:1;flex-wrap:wrap;row-gap:2px}
.fxfoot{margin-top:12px}
.exrow{display:block;margin-top:10px}
.exrow .sub{margin-top:2px}
.topbar #exline{margin-left:4px}
/* stickers (work order 07-4): on the page they are millimetres, the handles are editor chrome */
.sgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-top:8px}
.stile{display:block;height:44px;background-repeat:no-repeat;background-position:center;background-size:70% auto;
       outline:1px solid #E5E5E5;outline-offset:-1px;cursor:pointer}
.stile:hover{outline-color:#000000}
.page .stk{position:absolute;z-index:4}
.page .stk img{width:100%;height:100%;display:block;user-select:none;-webkit-user-drag:none}
body.editor:not(.preview) .stk{cursor:move}
body.editor:not(.preview) .stk.sel{outline:1px solid #000000;outline-offset:2px}
.sgrip{position:absolute;width:8px;height:8px;background:#FFFFFF;outline:1px solid #000000;z-index:6}
.sgrip.nw{left:-4px;top:-4px;cursor:nwse-resize}
.sgrip.ne{right:-4px;top:-4px;cursor:nesw-resize}
.sgrip.se{right:-4px;bottom:-4px;cursor:nwse-resize}
.sgrip.sw{left:-4px;bottom:-4px;cursor:nesw-resize}
.sgrip.rot{left:50%;top:-18px;margin-left:-4px;border-radius:50%;cursor:grab}
body.preview .sgrip{display:none}
/* ---- print mode (work order 07-4): one sheet per page at scale 1; only backgrounds and full-bleed photos reach into the bleed ---- */
body.printing{margin:0;background:#FFFFFF}
body.printing .sheet{position:relative;width:var(--sheetw);height:var(--sheeth);overflow:hidden;page-break-after:always;break-after:page}
body.printing .sheet:last-child{page-break-after:auto;break-after:auto}
body.printing .page{position:absolute;left:var(--bleed);top:var(--bleed);width:var(--pw);height:var(--ph);outline:none;transform:none}
body.printing .page .pbg{inset:calc(-1 * var(--bleed))}
body.printing .sheet .page.blank{background:#FFFFFF}
body.printing .fitfill,body.printing .txh,body.printing .sgrip,body.printing .snapv,body.printing .snaph{display:none}
/* WO83b: the editor draws a page number on every page as a screen affordance. It is not a folio: a printed
   page number is a text box the owner controls, and this album style prints none at all. */
body.printing .page .pnum{display:none}
.tacts2{margin-top:24px}
.tacts2 a+a{margin-left:14px}
.tmpl{position:relative;aspect-ratio:1/1;outline:1px solid #E5E5E5;outline-offset:-1px;cursor:pointer;background:#FFFFFF}
.tmpl.on{outline:1px solid #000000}
.tmpl i{position:absolute;background:#E5E5E5}
.canvas{flex:1;min-width:0;min-height:0;overflow:auto;display:flex;flex-direction:column;align-items:safe center;justify-content:safe center;padding:24px}
.canvas .spreadbox{margin:0;flex:none}
body.preview .canvas .spreadbox{margin:0 0 24px}
.overview{flex:none;width:200px;border-left:1px solid #E5E5E5;overflow-y:auto;scrollbar-width:thin;padding:16px}
.overview .phead{margin-bottom:12px}
.ovspread{margin-bottom:14px;cursor:pointer;touch-action:none}
.ovspread.on .ovpages{outline:1px solid #000000;outline-offset:2px}
.ovpages{display:flex;column-gap:2px}
.ovpage{flex:1;aspect-ratio:1/1;position:relative;overflow:hidden;background:#FFFFFF;outline:1px solid #E5E5E5;outline-offset:-1px}
.ovpage img{position:absolute;object-fit:cover;display:block}
.ovpage .ovblank{position:absolute;outline:1px solid #E5E5E5;outline-offset:-1px}
.ovhalf{flex:1}
.ovadd{display:inline-block;margin-top:2px}
.ovspread .between{margin-top:4px}
.slot::after{inset:0}
.page .slot.sel{outline:1px solid #000000;outline-offset:-1px}
body.editor:not(.preview) .page.cur{outline:1px solid #000000;outline-offset:-1px}   /* the page you are working on; never printed */
body.editor #note{position:fixed;left:24px;bottom:8px;background:#FFFFFF}
/* ---- style page (work order 08): nine cards, three per row ---- */
body.stylepage{height:100vh;overflow:hidden}
body.stylepage .ewrap{height:100vh;display:flex;flex-direction:column;max-width:none;padding:0}
body.stylepage #note{position:fixed;left:24px;bottom:56px;background:#FFFFFF}
.tabs{flex:none;display:flex;gap:28px;padding:18px 48px 0;border-bottom:1px solid #E5E5E5}
.tabs a{padding-bottom:12px;border-bottom:1px solid transparent;margin-bottom:-1px;cursor:pointer}
.tabs a.on{border-bottom-color:#000000;color:#000000}
.cards{flex:1;min-height:0;overflow-y:auto;scrollbar-width:thin;display:grid;grid-template-columns:repeat(3,1fr);
       gap:40px 36px;align-content:start;padding:32px 48px 40px}
@media (max-width:1500px){.cards{grid-template-columns:repeat(2,1fr)}}
.card{cursor:pointer}
.card .shot{display:flex;column-gap:1px;background:#E5E5E5;aspect-ratio:2/1;overflow:hidden;
            outline:1px solid #E5E5E5;outline-offset:-1px;margin-bottom:14px;
            transition:outline-color var(--t-hover) var(--ease)}
.card .shot i{flex:1;min-width:0;background-size:cover;background-position:center;display:block}
.card .cname{margin-bottom:6px}
.card .price{margin-top:6px}
.card.on .shot{outline:1px solid #000000;outline-offset:2px}
.card .between{margin-bottom:4px}
.card .sub{margin-top:0;line-height:1.7}
.card.ai{cursor:default}
.card .shot.empty{align-items:center;justify-content:center}
.card.aicard .u11{margin-top:4px}
.slot .ainote{position:absolute;left:0;bottom:0;z-index:3;background:#FFFFFF;color:#707070;padding:2px 5px}
/* 工单 12 C：选中照片后页面底部的工具条 */
.webmode{margin-top:10px;display:flex;gap:20px;align-items:baseline;flex-wrap:wrap}
.webmode a.on{border-bottom:1px solid #000000;color:#000000}
.webmode #webNote{flex-basis:100%;margin-top:4px}
.slotbar{position:fixed;left:0;right:0;bottom:0;z-index:30;height:56px;display:flex;align-items:center;
         gap:26px;padding:0 24px;background:#FFFFFF;border-top:1px solid #E5E5E5}
.slotbar .thumb{width:32px;height:32px;flex:none;background-size:cover;background-position:center;display:block}
.slotbar .pnum{flex:none;margin-left:-14px}
.slotbar .group{display:flex;align-items:center;gap:14px;min-width:0}
.slotbar .group b{font-weight:400}
.slotbar .group.styles{flex:1;min-width:0}
.slotbar .srow{display:flex;gap:16px;overflow-x:auto;scrollbar-width:thin;padding-bottom:2px}
.slotbar .srow a{white-space:nowrap}
.slotbar a.on{border-bottom:1px solid #000000}
.slotbar .done{margin-left:auto}
.slotbar .fxgroup{flex:1;gap:18px;overflow-x:auto;scrollbar-width:thin}
.slotbar .ctl{display:flex;align-items:center;gap:8px;white-space:nowrap}
.slotbar .ctl input[type=range]{width:110px}
body.hasbar #canvas{padding-bottom:56px}
/* 工单 10：还没画好的槽位 —— 原照片 + 灰纱 + RENDERING，画好了原地淡入，位置尺寸都不动 */
.slot .veil{position:absolute;inset:0;z-index:2;background:#FFFFFF;opacity:.62;
            transition:opacity var(--t-slot,240ms) var(--ease)}
.slot .rendering{position:absolute;left:0;top:0;z-index:3;background:#FFFFFF;color:#707070;padding:2px 5px;
                 transition:opacity var(--t-slot,240ms) var(--ease)}
.slot .rline{position:absolute;left:0;right:0;bottom:0;z-index:3;height:1px;background:#E5E5E5;
             transition:opacity var(--t-slot,240ms) var(--ease)}
.slot .rline b{display:block;height:1px;background:#000000}
.slot:not(.waiting) .veil,.slot:not(.waiting) .rendering,.slot:not(.waiting) .rline{opacity:0}
.slot img.landing{position:absolute;inset:0;width:100%;height:100%;z-index:1;opacity:0;
                  transition:opacity var(--t-slot,240ms) var(--ease)}
.slot img.landing.in{opacity:1}
body.preview .veil,body.preview .rendering,body.preview .rline,
body.printing .veil,body.printing .rendering,body.printing .rline{display:none}
body.preview .ainote,body.printing .ainote{display:none}   /* 预览和出 PDF 时不带这个小标 */
.card.ai .shot{filter:none}
.footbar{flex:none;height:56px;display:flex;align-items:center;justify-content:space-between;padding:0 48px;border-top:1px solid #E5E5E5}
#closePreview{position:fixed;top:16px;right:24px;z-index:30;background:#FFFFFF;padding:4px 8px}
body.preview .topbar,body.preview .rail,body.preview .panel,body.preview .overview{display:none}
body.preview .canvas{padding:24px 0}
body.editor [data-drop]::after{inset:0}

/* ---------------- 工单 14-3：主页两列 + 书架上真的书 ---------------- */
.wrap.home{height:100vh;min-height:0;display:flex;flex-direction:column}
.wrap.home footer{margin-top:0;flex:none}
main.home{margin-top:0;flex:1;min-height:0;display:flex;align-items:stretch}
main.home>section{max-width:none;padding:96px 0 40px}
main.home section+section{margin-top:0}
main.home h1{font-size:32px}
main.home #create{flex:none;width:480px;padding-right:48px;overflow-y:auto;scrollbar-width:thin}
main.home #create .sub{margin-top:12px}
main.home .actions{margin-top:28px}
main.home #webNote{margin-top:12px;font-size:12px;line-height:1.7}
main.home .content{margin-top:28px}
main.home .grid{grid-template-columns:repeat(4,1fr);max-height:none;overflow:visible}
main.home #statusText{margin-top:20px}
/* 右边那列不做滚动条：里面是 3D，一开 overflow 就会被切掉 */
main.home #shelf{flex:1;min-width:0;max-width:720px;padding-left:48px;
                 border-left:1px solid #E5E5E5}    /* 工单 14-5：书架不再占半个页面，右边留白 */
main.home .shelf{margin-top:40px}
main.home .shelf .cap{margin-top:12px;color:#707070}

/* ---- 书架 ---- */
.stage{position:relative}
.books{display:flex;align-items:flex-end;gap:4px;perspective:1200px;min-height:220px;
       transform:translateX(calc(var(--sx, 0) * -1px));transition:transform var(--t-hover) var(--ease)}
.stage .line{height:1px;background:#000000;position:relative;z-index:1}
.book{position:relative;flex:none;width:var(--w);height:var(--h);cursor:pointer;
      transform-style:preserve-3d;transform-origin:0 50%;
      transform:translateX(var(--drag, 0px));transition:transform var(--t-book) var(--ease)}
.book .face{position:absolute;left:0;top:0;backface-visibility:hidden}
/* 点击区往两边各让出 2px（正好是书之间那道 4px 的缝，互不重叠） */
.book::after{content:"";position:absolute;top:0;bottom:0;left:-2px;right:-2px}
/* 书脊：一块平的色块，不装弧面、不画假的板边（工单 14-5）。宽高厚都是毫米算出来的 */
.book .spine{width:var(--w);height:var(--h);color:var(--t);background:var(--c);
             display:flex;flex-direction:column;align-items:center;justify-content:space-between;
             padding:8px 0 6px;overflow:hidden}
/* 书名：从下往上竖排（vertical-rl 再转 180°），写不下用省略号，永远不藏（工单 14-6） */
/* 书脊只有 20px 宽了：11px 的竖排行盒 17px，塞不下 —— 字降到 10px（工单 14-7） */
.book .stitle,.book .svol{font-size:10px}
.book .stitle{writing-mode:vertical-rl;transform:rotate(180deg);white-space:nowrap;
              overflow:hidden;text-overflow:ellipsis;max-height:calc(var(--h) - 40px);
              letter-spacing:.12em}
.book .stitle.cjk{transform:none}   /* 中文书脊本来就是从上往下、字正着立的 */
.book .svol{flex:none}
/* 封面平时是侧着的：一条透视缝里会漏出图，所以立着的时候干脆藏起来，转出来时淡入 */
.book .cover{width:var(--cw);height:var(--h);transform-origin:0 50%;transform:rotateY(90deg);
             background:#FFFFFF;opacity:0;transition:opacity var(--t-book) var(--ease)}
.books .book:hover .cover,.pickwrap .book.up .cover{opacity:1}
.book .cover img{width:100%;height:100%;object-fit:cover;display:block}
/* 立着的时候封面是侧着的一条缝，但透视下它照样挡鼠标 —— 书脊只有几个像素宽时，
   旁边那本的封面会把它整个盖住、点不着。所以书架上的封面一律不接鼠标事件，鼠标只认书脊那一条 */
.books .book .cover{pointer-events:none}
/* 鼠标移上去：只有这一本转出封面（-70°，封面几乎正对着看）、抬起 8px，影子只有这里允许。
   右边的书同时让开封面需要的宽度（--shift 由 shelf.js 按那本书的封面算），240ms 一起走 */
.books .book:hover{transform:translateY(-8px) rotateY(-70deg);z-index:3}
.books .book:hover~.book{transform:translateX(var(--shift, 0px))}
.books .book:hover .cover{box-shadow:0 20px 40px rgba(0,0,0,.18),0 2px 6px rgba(0,0,0,.10)}
.books .book.dragging{transition:none;transform:translateX(var(--drag, 0px)) translateY(-8px);z-index:4}
.book.gone{visibility:hidden}
.stage.picking .books{opacity:.6}
.stage.picking .books .book:hover{transform:translateX(var(--drag, 0px))}
.stage.picking .books .book:hover .cover{box-shadow:none}

/* ---- 拿起来 ---- */
.pickwrap{position:absolute;inset:0;perspective:1400px;pointer-events:none;z-index:6}
.pickwrap .book{position:absolute;pointer-events:auto;transition:transform var(--t-pick) var(--ease),
                opacity var(--t-hover) var(--ease)}
/* scale 只缩 x/y，转过 90° 之后宽度那一维在 z 上 —— 必须用 scale3d，否则封面只长高不变宽 */
.pickwrap .book.up{transform:translate(var(--dx), var(--dy)) rotateY(-90deg)
                             scale3d(var(--k), var(--k), var(--k))}
.pickwrap .book.up .cover{box-shadow:0 24px 48px rgba(0,0,0,.18),0 2px 8px rgba(0,0,0,.10)}
.pickwrap .book.open{opacity:0;pointer-events:none}
.picklinks{position:absolute;left:var(--lx, 0);width:var(--lw, 100%);top:var(--ly);text-align:center;
           pointer-events:auto;opacity:0;transition:opacity var(--t-hover) var(--ease)}
.picklinks .sep{margin:0 12px;color:#707070}
.pickwrap .book.up~.picklinks{opacity:1}
.pickwrap .book.open~.picklinks{opacity:0;pointer-events:none}

/* ---- 翻页：一页一页真的翻，翻的那页背面也印着东西 ---- */
/* 翻开之后书架让位：白底盖住书脊，眼睛只看这本书 */
.reader{position:absolute;left:0;right:0;top:-24px;bottom:-32px;background:#FFFFFF;
        display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;
        opacity:0;transition:opacity var(--t-hover) var(--ease);pointer-events:auto}
.reader.on{opacity:1}
.spread{position:relative;display:flex;gap:1px;background:#E5E5E5;perspective:1600px;
        width:calc(var(--pg) * 2 + 1px);height:var(--ph, var(--pg))}
.spread .pg{width:var(--pg);height:var(--ph, var(--pg));background:#FFFFFF;overflow:hidden;cursor:pointer;
            outline:1px solid #E5E5E5;outline-offset:-1px}
.spread .pg img{width:100%;height:100%;object-fit:contain;display:block}
.leaf{position:absolute;left:calc(var(--pg) + 1px);top:0;width:var(--pg);height:var(--ph, var(--pg));
      transform-style:preserve-3d;transform-origin:0 50%;z-index:2}
.leaf.go{transition:transform var(--t-turn) var(--ease)}
.leaf .lf{position:absolute;inset:0;backface-visibility:hidden;background:#FFFFFF;overflow:hidden;
          outline:1px solid #E5E5E5;outline-offset:-1px;
          box-shadow:0 0 24px rgba(0,0,0,.10)}
.leaf .lf.back{transform:rotateY(180deg)}
.leaf .lf img{width:100%;height:100%;object-fit:contain;display:block}
.rnav{display:flex;align-items:baseline;gap:20px}
.rnav .rpos{color:#707070}

@media (max-width:860px){         /* 手机上：两列摞起来，先 CREATE 后书架；列宽 = 屏宽 - 20px */
  .wrap{padding:0 20px}
  .wrap.home{height:auto;min-height:100vh}
  .nav .mid{display:none}
  main.home{flex-direction:column}
  main.home>section{padding:40px 0}
  main.home #create{width:auto;padding-right:0;overflow:visible}
  main.home #shelf{padding-left:0;border-left:0;border-top:1px solid #E5E5E5}
  main.home .grid{grid-template-columns:repeat(4,1fr)}
  .books{overflow-x:auto;scrollbar-width:none}
}

/* ---------------- 工单 14-5：风格页下面的 SIZE 那一行 ---------------- */
.sizerow{display:flex;align-items:baseline;gap:20px;padding:14px 0 0}
.sizerow .lbl{color:#707070}
.sizerow a.on{border-bottom:1px solid #000000}
.sizerow .mm{color:#707070;margin-left:auto}
#sizeRow{display:inline-flex;align-items:baseline;gap:12px;margin-left:16px}
#sizeRow .lbl{color:#707070}
#sizeRow a.on{border-bottom:1px solid #000000}

/* 工单 16：风格卡片上的"这类照片会做不好"提醒 —— 不加第五种颜色，用一条上边线区分 */
.card .sub.warn{border-top:1px solid #E5E5E5;padding-top:8px;margin-top:8px;color:#707070}
/* WO79: a photo shown from its 512px preview says so (never in print) */
.slot .lowres{position:absolute;right:0;bottom:0;z-index:3;background:#FFFFFF;color:#707070;padding:2px 5px;pointer-events:none}
body.printing .lowres{display:none}
#anotherCover,#anotherCoverNote,[data-studio="another-cover"],[data-studio="another-cover"]+.s-hint{display:none} /* WO136 decision 3: Another cover is withdrawn for the first release (config/billing.json another_cover) */
