/* 做一本手帐 — the photo-first editor. Panel on the left (photos, options), the 3-D flip-book on the right.
   Phones: the book on top, the panel below. No site nav on this page: a small mark links home. */
body.app { overflow: hidden; }
.studio { display: grid; grid-template-columns: 420px 1fr; height: 100svh; }
.panel { position: relative; z-index: 2; display: flex; flex-direction: column; gap: 18px; padding: 18px 26px 26px; background: var(--paper); border-right: 1px solid rgb(42 37 33 / .08); overflow-y: auto; }
.panel-head { display: flex; align-items: center; justify-content: space-between; }
.home { display: inline-flex; align-items: center; gap: 8px; text-decoration: none; color: var(--ink-2); font: 700 15px/1 var(--serif); opacity: .8; }
.home img { width: 22px; height: 22px; }
.home:hover { opacity: 1; }
.link-btn { display: inline-flex; align-items: center; gap: 6px; border: 0; background: none; padding: 6px 8px; margin-right: -8px; border-radius: 8px; font: 500 13px/1 var(--sans); color: var(--ink); cursor: pointer; }
.link-btn i { width: 17px; height: 17px; display: inline-flex; color: var(--accent); }
.link-btn:hover { background: rgb(42 37 33 / .06); }
#admin-link[hidden], #billing-manage[hidden], #billing-checkout[hidden] { display: none; }
.head-r { display: flex; align-items: center; gap: 4px; }
.link-btn.quiet { color: var(--muted); max-width: 9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.saved .linkish { border: 0; background: none; padding: 0; font: inherit; color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.intro .eyebrow { margin-bottom: 8px; }
.panel-title { font: 500 30px/1.3 var(--serif); color: var(--ink-2); }
.field { display: flex; flex-direction: column; gap: 8px; border: 0; padding: 0; margin: 0; min-width: 0; position: relative; }

/* drop zone: big when empty, a slim bar once photos are in */
.drop { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; min-height: 200px; padding: 22px; border-radius: 16px; border: 1.5px dashed rgb(42 37 33 / .24);
  background: #FFFCF6; text-align: center; cursor: pointer; transition: border-color .25s var(--ease), background .25s var(--ease), min-height .35s var(--ease); }
.drop i { width: 38px; height: 38px; display: inline-flex; color: var(--accent); }
.drop b { font: 500 17px/1.4 var(--sans); color: var(--ink); }
.drop:hover, .drop:focus-visible, .drop.over { border-color: var(--accent); background: #FFF8EE; outline: none; }
.drop.over { box-shadow: 0 0 0 4px rgb(158 59 59 / .1); }
.drop.slim { min-height: 0; flex-direction: row; justify-content: flex-start; gap: 10px; padding: 12px 16px; }
.drop.slim i { width: 22px; height: 22px; }
.drop.slim b { font-size: 14px; }
.drop.slim .mono { margin-left: auto; }
.drop.full { opacity: .5; pointer-events: none; }

/* photos grouped by day */
.days { display: flex; flex-direction: column; gap: 12px; }
.days:empty { display: none; }
.day { display: grid; grid-template-columns: 56px 1fr; gap: 10px; padding-top: 12px; border-top: 1px solid rgb(42 37 33 / .07); }
.day:first-child { border-top: 0; padding-top: 0; }
.day-head { display: flex; flex-direction: column; gap: 2px; padding-top: 2px; }
.day-head b { font: 500 15px/1.25 var(--serif); color: var(--ink-2); }
.day-head b + b { font-size: 13px; color: var(--muted); }
.day-head .mono { font-size: 10.5px; line-height: 1.4; }
.day-main { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.add-note { align-self: flex-start; border: 0; background: none; padding: 2px 0; font: 400 12.5px/1.2 var(--sans); color: var(--muted); cursor: pointer; text-decoration: underline dotted rgb(42 37 33 / .3); text-underline-offset: 3px; }
.add-note:hover { color: var(--accent); }
.day-note { width: 100%; padding: 9px 12px; border-radius: 10px; border: 1px solid rgb(42 37 33 / .14); background: #FFFCF6; font: 400 16px/1.5 var(--hand); color: var(--ink); outline: none; }
.day-note:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgb(158 59 59 / .12); }
.thumbs { display: grid; grid-template-columns: repeat(auto-fill, 74px); gap: 8px; }
.thumb { position: relative; aspect-ratio: 1; margin: 0; border-radius: 8px; overflow: hidden; background: var(--paper-2); box-shadow: 0 8px 18px -12px rgb(60 40 20 / .5); cursor: grab; touch-action: pan-y; user-select: none; -webkit-user-select: none; outline: none; }
.thumb img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; -webkit-user-drag: none; }
.thumb:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
.thumb .t { position: absolute; left: 4px; bottom: 4px; padding: 1px 5px; border-radius: 4px; background: rgb(42 37 33 / .66); color: #fff; font: 500 10.5px/1.5 var(--mono); }
.thumb .t.file { background: rgb(158 59 59 / .8); }
.thumb .x { position: absolute; top: 4px; right: 4px; width: 22px; height: 22px; border-radius: 50%; border: 0; background: rgb(42 37 33 / .72); color: #fff; font: 500 14px/22px var(--sans); cursor: pointer; padding: 0; }
.thumb.dragging { opacity: .9; z-index: 5; box-shadow: 0 16px 30px -12px rgb(60 40 20 / .6); cursor: grabbing; transition: none; }
.thumb.target { box-shadow: 0 0 0 2px var(--accent); }
.thumb.loading { display: grid; place-items: center; }
.thumb.loading::after { content: ''; width: 18px; height: 18px; border-radius: 50%; border: 2px solid rgb(42 37 33 / .15); border-top-color: var(--accent); animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(1turn); } }
.note { color: var(--accent); }

.chips-row { display: flex; gap: 8px; flex-wrap: wrap; }
.chips-row input { position: absolute; opacity: 0; pointer-events: none; }
.chips-row span { display: inline-block; padding: 8px 14px; border-radius: 999px; border: 1px solid rgb(42 37 33 / .16); font: 500 14px/1 var(--sans); cursor: pointer; transition: all .25s var(--ease); }
.chips-row input:checked + span { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.chips-row input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
.adv { border: 0; padding: 0; }
.adv summary { cursor: pointer; width: max-content; list-style: none; font: 400 12px/1.5 var(--mono); display: block; }
.adv summary::after { content: none; }
.adv summary::-webkit-details-marker { display: none; }
.adv summary::before { content: '＋ '; }
.adv[open] summary::before { content: '－ '; }
.adv[open] summary { margin-bottom: 10px; }
.select { appearance: none; padding: 11px 38px 11px 14px; border-radius: 10px; border: 1px solid rgb(42 37 33 / .16); background: #FFFCF6 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%232A2521' stroke-width='1.5'/%3E%3C/svg%3E") right 14px center no-repeat; font: 500 14px var(--sans); color: var(--ink); }

.go-wrap { position: sticky; bottom: -26px; margin: auto -26px -26px; padding: 14px 26px 20px; background: linear-gradient(to bottom, rgb(247 241 230 / 0), var(--paper) 14px); display: flex; flex-direction: column; gap: 10px; }
.btn-go { justify-content: center; padding: 15px 20px; font-size: 16px; cursor: pointer; border: 0; }
.btn-go[disabled] { opacity: .45; cursor: default; transform: none; }
.btn-go.busy { opacity: .7; cursor: progress; }
.progress { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.progress li { display: grid; grid-template-columns: 56px 1fr; grid-template-rows: auto 4px; column-gap: 10px; row-gap: 3px; align-items: center; font: 400 12.5px/1.3 var(--sans); color: var(--muted); }
.progress li span { grid-row: 1 / 3; }
.progress li b { font: 400 11.5px/1.3 var(--mono); color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.progress li i { display: block; height: 4px; border-radius: 2px; background: rgb(42 37 33 / .08); overflow: hidden; }
.progress li s { display: block; height: 100%; width: 0; background: var(--ink-2); border-radius: 2px; transition: width .4s var(--ease); }
.progress li.on span { color: var(--ink); }
.progress li.done s { background: #6E8A4E; }
.progress[hidden], .progress li[hidden] { display: none; }
.hint { text-align: center; min-height: 1.5em; }

/* cover */
.cover-panel { display: flex; flex-direction: column; gap: 12px; padding: 14px; border-radius: 14px; background: #FFFCF6; border: 1px solid rgb(42 37 33 / .08); }
.cover-panel[hidden] { display: none; }
.cover-head { display: flex; align-items: baseline; gap: 10px; }
.cover-head b { font: 500 16px/1.2 var(--serif); color: var(--ink-2); }
.cover-body { display: grid; grid-template-columns: 124px 1fr; gap: 14px; align-items: start; }
.cover-prev { width: 124px; height: auto; aspect-ratio: 148 / 210; border-radius: 3px 6px 6px 3px; box-shadow: 0 14px 24px -14px rgb(40 20 10 / .7), inset 0 0 0 1px rgb(0 0 0 / .1); background: #6A1F25; }
.cover-form { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.text-in { width: 100%; min-width: 0; padding: 8px 10px; border-radius: 9px; border: 1px solid rgb(42 37 33 / .14); background: var(--paper); font: 500 15px/1.4 var(--serif); color: var(--ink); outline: none; }
.text-in.hand { font: 400 16px/1.4 var(--hand); }
.text-in:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgb(158 59 59 / .12); }
.tints { display: flex; gap: 8px; }
.tints input, .heroes input { position: absolute; opacity: 0; pointer-events: none; }
.tints span { display: block; width: 26px; height: 26px; border-radius: 50%; background: var(--c); cursor: pointer; box-shadow: inset 0 0 0 1px rgb(0 0 0 / .15); }
.tints input:checked + span { box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--c); }
.tints input:focus-visible + span, .heroes input:focus-visible + img { outline: 2px solid var(--accent); outline-offset: 2px; }
.heroes { display: flex; gap: 6px; overflow-x: auto; padding: 3px 3px 6px; margin: -3px; scrollbar-width: thin; }
.heroes label { flex: none; cursor: pointer; }
.heroes img { display: block; width: 46px; height: 46px; object-fit: cover; border-radius: 6px; opacity: .72; transition: opacity .2s; }
.heroes input:checked + img { opacity: 1; box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--accent); }

/* stage */
.stage { position: relative; min-width: 0; }
.stage-scene { position: absolute; inset: 0 0 68px; }
.stage-empty { position: absolute; inset: 0 0 68px; display: grid; place-items: end center; padding-bottom: 7%; pointer-events: none; transition: opacity .6s var(--ease); }
.stage-empty p { font-size: 22px; line-height: 1.6; color: var(--ink-2); text-align: center; background: rgb(247 241 230 / .78); padding: 10px 22px; border-radius: 14px; }
.stage-empty.gone { opacity: 0; }
.stage-pill { position: absolute; left: 50%; top: 18px; transform: translateX(-50%); z-index: 3; margin: 0; padding: 7px 16px; border-radius: 999px; background: rgb(247 241 230 / .9); color: var(--ink); box-shadow: 0 10px 30px -18px rgb(60 40 20 / .6); white-space: nowrap; max-width: calc(100% - 32px); overflow: hidden; text-overflow: ellipsis; }
.stage-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 68px; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 0 20px; background: rgb(238 228 210 / .94); border-top: 1px solid rgb(42 37 33 / .08); }
.pager { display: flex; align-items: center; gap: 6px; min-width: 0; }
.pager .mono { color: var(--ink); min-width: 9em; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ic { width: 38px; height: 38px; flex: none; border: 0; border-radius: 50%; background: none; color: var(--ink); cursor: pointer; display: grid; place-items: center; font: 400 22px/1 var(--sans); }
.ic i { width: 20px; height: 20px; display: inline-flex; }
.ic.prev i { transform: scaleX(-1); }
.ic:hover:not([disabled]) { background: rgb(42 37 33 / .07); }
.ic[disabled] { opacity: .3; cursor: default; }
.stage-actions { display: flex; align-items: center; gap: 8px; }
.stage-actions .btn { padding: 10px 14px; cursor: pointer; font-size: 14px; background-color: transparent; }
.stage-actions .btn-ink { background: var(--ink); }
.stage-actions .btn[disabled] { opacity: .4; cursor: default; transform: none; }
.saved { white-space: nowrap; }
.stage iframe { position: absolute; inset: 0 0 68px; width: 100%; height: calc(100% - 68px); border: 0; }

.toast { position: fixed; left: 50%; bottom: 88px; transform: translateX(-50%); background: var(--ink); color: var(--paper); padding: 10px 18px; border-radius: 999px; font: 500 14px var(--sans); z-index: 30; opacity: 0; transition: opacity .3s; pointer-events: none; max-width: calc(100% - 32px); text-align: center; }
.toast.on { opacity: 1; }

.daynight { position: absolute; right: 16px; top: 16px; z-index: 3; width: 40px; height: 40px; display: grid; place-items: center; padding: 0; border-radius: 50%; border: 1px solid rgb(42 37 33 / .1); background: rgb(247 241 230 / .94); color: var(--ink); cursor: pointer; box-shadow: 0 4px 14px rgb(42 37 33 / .1); transition: background .2s, transform .2s; }
.daynight[hidden] { display: none; }
.daynight:hover { background: #fffaf0; transform: translateY(-1px); }
.daynight:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.daynight .mode-icon { display: none; width: 21px; height: 21px; }
.daynight[data-t="auto"] .mode-auto, .daynight[data-t="day"] .mode-day, .daynight[data-t="night"] .mode-night { display: block; }

/* /app 的顶层布局：舞台铺满，面板是浮层且默认收起，动作全部收在右上角。
   为什么这么改：房间就绪在线上要二十多秒（three.js + TOS 素材），而这之前 has-room 还没加上，
   于是顶栏整条是 display:none、面板却完整显示——用户进入看到的是生成表单而不是房间。
   现在顶栏与面板都不依赖 has-room：进入先看到顶栏 + 房间（未就绪时是「新建」），点新建才滑出面板。 */
.room-only, .room-top, .room-home-bar { display: none; }
.has-room .room-only { display: inline-flex; }
.has-room.creating #panel-open { display: none; }
body.has-room:not(.room-desk) #shelf-back, body.has-room:not(.room-desk) #panel-open { display: none; }
.pill-btn { align-items: center; border: 0; border-radius: 999px; padding: 9px 14px; background: none; font: 500 14px/1 var(--sans); color: var(--ink); cursor: pointer; white-space: nowrap; }
.pill-btn:hover { background: rgb(42 37 33 / .07); }
.pill-btn > i { width: 17px; height: 17px; display: inline-flex; margin-right: 7px; color: var(--accent); }
body.app .studio { display: block; height: 100svh; }
body.app .stage, body.app:not(.has-book) .stage, body.app:not(.has-book):not(.has-room) .stage { position: fixed; inset: 0; height: auto; min-height: 0; }
body.app .stage-scene { inset: 0; transition: left .5s var(--ease); }
.has-room .stage-empty { display: none; }
/* 面板：任何状态下都默认收起；只有 creating（新建一本 / 编辑照片）才滑出 */
body.app .panel { position: fixed; left: 16px; top: 74px; bottom: 16px; width: 400px; z-index: 6; border-radius: 18px; border: 1px solid rgb(42 37 33 / .08); background: rgb(247 241 230 / .96);
  box-shadow: 0 30px 60px -30px rgb(40 25 10 / .5); transform: translateX(calc(-100% - 24px)); transition: transform .5s var(--ease); }
body.app.creating .panel { transform: none; }
.has-room .go-wrap { bottom: -26px; }
/* desktop: while the panel is out, the room frames itself in the space right of it (the panel covers the rest) */
@media (min-width: 901px) { body.app.creating .stage-scene { left: 432px; } .has-room .panel-title { font-size: 26px; } }
/* 顶栏：logo 常在左，动作全在右侧一枚胶囊里（面板关着时也能用） */
body.app .room-top { display: flex; position: fixed; left: 16px; right: 16px; top: 14px; z-index: 8; align-items: center; justify-content: space-between; gap: 10px; pointer-events: none; }
body.app .room-top > * { pointer-events: auto; }
body.app .room-top .home { padding: 8px 14px 8px 10px; border-radius: 999px; background: rgb(250 247 242 / .86); box-shadow: 0 10px 30px -18px rgb(60 40 20 / .5); }
/* min-width:0 是关键：作为 flex 项目，默认 min-width:auto 会让它拒绝收缩到内容宽度以下，
   长邮箱时整个动作簇会撑到 466px、把顶栏挤爆。允许收缩后由各按钮的 min-width:44px 兜底，
   文字用省略号截断。 */
.room-actions { display: flex; align-items: center; gap: 2px; padding: 4px 6px; border-radius: 999px; background: rgb(250 247 242 / .86); box-shadow: 0 10px 30px -18px rgb(60 40 20 / .5); min-width: 0; }
.room-actions .pill-btn { padding: 8px 11px; }
.room-actions .daynight { position: static; width: 34px; height: 34px; padding: 0; border: 0; background: none; box-shadow: none; }
.room-actions .daynight:hover { background: rgb(42 37 33 / .07); transform: none; }
.room-actions .room-tool { width: 34px; height: 34px; padding: 7px; }
/* 订阅 / 后台 / 登录：桌面端用文字，图标留到手机上用（手机只有 390px，文字会被挤爆） */
.room-actions .ico { display: none; width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
body.app:not(.creating) .room-home-bar { display: flex; position: fixed; left: 50%; bottom: max(22px, env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 5; }
body.app.room-desk .room-home-bar, body.app.creating .room-home-bar { display: none; }
.room-home-bar .btn { cursor: pointer; border: 0; box-shadow: 0 14px 30px -14px rgb(40 25 10 / .6); padding: 14px 22px; }
.has-room .stage-bar { left: 50%; right: auto; bottom: max(16px, env(safe-area-inset-bottom)); transform: translateX(-50%); height: auto; width: max-content; max-width: calc(100% - 24px); padding: 6px 8px; gap: 8px;
  border-radius: 999px; border: 1px solid rgb(42 37 33 / .08); background: rgb(250 247 242 / .9); box-shadow: 0 10px 30px -18px rgb(60 40 20 / .5); backdrop-filter: blur(6px); }
body.has-room:not(.room-desk) .stage-bar { display: none; }
@media (min-width: 901px) { body.app.creating .stage-bar { left: calc(50% + 216px); } body.app.creating .stage-pill { left: calc(50% + 216px); } }
.has-room .pager .mono { min-width: 0; }
.has-room .saved { display: none; }
@media (max-width: 900px) {
  body.app .panel { left: 0; right: 0; top: auto; bottom: 0; width: auto; max-height: 76svh; border-radius: 18px 18px 0 0; transform: translateY(105%); }
  body.app.creating .panel { transform: none; }
  .has-room .stage-bar { flex-direction: row; flex-wrap: wrap; justify-content: center; border-radius: 18px; }
  .has-room .stage-actions .btn { padding: 8px 10px; }
  .has-room .pager .mono { max-width: 9em; }
  /* 手机窄：顶栏靠「允许收缩 + 省略号」而不是藏文字——6 个动作的硬下限是 6×44=264px，
     容器有 ~304px，永远放得下；长邮箱（#login 单独就 223px）会被截成省略号。
     另外把点子落在 44px 以上，满足移动端点击区要求。 */
  body.app .room-top { gap: 6px; }
  body.app .room-top .home { padding: 8px 10px; min-width: 44px; justify-content: center; }
  body.app .room-top .home span { display: none; }
  .room-actions { gap: 0; padding: 3px 5px; }
  .room-actions .pill-btn { padding: 8px 8px; }
  .room-actions .pill-btn > i { margin-right: 0; }
  .room-actions .daynight, .room-actions .room-tool { width: 44px; height: 44px; }
  .room-actions #billing, .room-actions #login { overflow: hidden; }
  /* 给登录名一个上限：不然长邮箱会独占收缩量，把我手帐/额度挤成「…」「剩…」 */
  .room-actions #login { max-width: 4.6em; }
  .room-actions #billing .label, .room-actions #login .label { display: block; overflow: hidden; text-overflow: ellipsis; }
  .room-actions #admin-link { display: none; }
}

/* 我的手帐 */
.drawer { position: fixed; inset: 0; z-index: 40; background: rgb(29 25 22 / .38); display: flex; justify-content: flex-start; }
.drawer[hidden] { display: none; }
.drawer-card { width: min(570px, 100%); height: 100%; background: #f8f2e8; border-right: 1px solid #dcc9aa; padding: 20px 22px; overflow-y: auto; box-shadow: 20px 0 60px -30px rgb(0 0 0 / .5); }
.drawer-card header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 14px; padding-bottom: 20px; border-bottom: 1px solid var(--dot); }
.drawer-card h2 { font: 500 31px/1.3 var(--serif); margin: 3px 0; color: var(--ink-2); }
.drawer-sub { font: 400 13px/1.5 var(--sans); color: var(--muted); }
.books { list-style: none; margin: 0; padding: 10px 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.books li { position: relative; display: flex; flex-direction: column; align-items: stretch; gap: 8px; padding: 12px; border-radius: 12px; background: #FFFCF6; border: 1px solid #e5d8c5; box-shadow: 0 8px 18px -17px #362619; }
.books img { width: 100%; height: 205px; object-fit: contain; border-radius: 6px; background: #eee4d2; }
.books button.open { width: 100%; min-height: 54px; text-align: left; border: 0; background: none; padding: 0; cursor: pointer; color: var(--ink); font: 500 15px/1.4 var(--sans); }
.books button.open .mono { display: block; margin-top: 3px; }
.books button.del { align-self: flex-end; border: 0; background: none; color: var(--muted); cursor: pointer; font: 400 12px var(--sans); padding: 6px; }
.books button.del:hover { color: var(--accent); }
.modal { justify-content: center; align-items: center; padding: 16px; }
.modal-card { width: min(400px, 100%); background: var(--paper); border-radius: 18px; padding: 20px 22px 18px; display: flex; flex-direction: column; gap: 14px; box-shadow: 0 30px 80px -30px rgb(0 0 0 / .55); }
.modal-card header { display: flex; align-items: center; justify-content: space-between; }
.modal-card h2 { font: 500 21px/1.3 var(--serif); color: var(--ink-2); }
.modal-card > .mono { line-height: 1.7; }
.lg-code { display: flex; flex-direction: column; gap: 12px; }
.code-row { display: flex; gap: 8px; }
.code-row .text-in { flex: 1; letter-spacing: .2em; font-family: var(--mono); }
.code-row .btn { padding: 8px 14px; font-size: 14px; cursor: pointer; background: none; }
.code-row .btn[disabled] { opacity: .5; cursor: default; transform: none; }
.books .empty { grid-column: 1 / -1; display: block; background: none; border: 0; color: var(--muted); font-size: 14px; padding: 12px 0; }

@media (max-width: 900px) {
  body.app { overflow: auto; }
  /* 舞台在 /app 一律铺满（面板是浮层，不再占布局）——原来那套「舞台 60svh + 面板在下面」
     的规则已经不适用了，留着会把舞台压成半屏。 */
  .stage-scene, .stage-empty { inset: 0 0 104px; }
  .stage iframe { inset: 0 0 104px; height: calc(100% - 104px); }
  .stage-empty p { font-size: 18px; }
  .stage-bar { height: 104px; flex-direction: column; justify-content: center; align-items: stretch; gap: 6px; padding: 6px 12px 10px; }
  .pager { justify-content: center; }
  .stage-actions { justify-content: center; flex-wrap: wrap; gap: 6px; }
  .stage-actions .btn { padding: 9px 12px; font-size: 13px; }
  .saved { display: none; }
  body:not(.has-book):not(.has-room) .stage-bar { display: none; }
  body:not(.has-book):not(.has-room) .stage-scene, body:not(.has-book):not(.has-room) .stage-empty { inset: 0; }
  .panel { padding: 16px 16px 24px; border-right: 0; }
  .panel-title { font-size: 24px; }
  .drop { min-height: 150px; }
  .go-wrap { bottom: 0; margin: auto -16px -24px; padding: 12px 16px calc(16px + env(safe-area-inset-bottom)); }
}
/* room: nothing to page through or export until the desk book has pages */
.has-room:not(.has-book) .stage-actions, .has-room:not(.has-book) .pager { display: none; }

/* ---------------------------------------------------------------- account, login, billing, toast (React: src/app/app/_studio/account.js) */
.panel-head { gap: 10px; }
.panel-head .home, .head-r .link-btn { flex: none; white-space: nowrap; }
.head-r { min-width: 0; gap: 2px; }
.head-r .link-btn { margin-right: 0; }
.head-r .link-btn:last-child { margin-right: -8px; }
.head-r .link-btn.quiet { flex: 0 1 auto; min-width: 0; max-width: 6.5em; }
.head-r .link-btn.quiet > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.head-r .link-btn.out { color: var(--accent); max-width: none; flex: none; }
.room-top .pill-btn:focus-visible, .head-r .link-btn:focus-visible, .panel-head .home:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.room-top .pill-btn { max-width: 16em; overflow: hidden; text-overflow: ellipsis; }
.modal-card :focus-visible, .modal-card .ic:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.modal-card .btn { justify-content: center; }
.modal-card .btn[disabled] { opacity: .55; cursor: default; }
.modal-card .hint.err { color: var(--accent); font: 500 13px/1.5 var(--sans); text-align: left; min-height: 0; margin-top: -4px; }
.modal-card .hint.err small { display: block; font-weight: 400; color: var(--muted); }
.modal-card .text-in[aria-invalid="true"] { border: 1.5px solid var(--accent); }
.modal-card .usage { font: 500 15px/1.5 var(--sans); color: var(--ink); }
.modal-card .usage.err { color: var(--accent); }
.modal-card .usage .linkish { margin-left: 10px; border: 0; background: none; padding: 0; font: inherit; color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.modal-card .terms { font: 400 13px/1.7 var(--sans); color: var(--muted); }
.modal-card .legal-links { font: 400 12px/1.6 var(--sans); color: var(--muted); }
.modal-card .legal-links a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.billing-card { width: min(570px, 100%); max-height: min(90vh, 760px); overflow-y: auto; }
.billing-period { display: flex; gap: 6px; padding: 4px; border-radius: 12px; background: var(--paper-2); }
.billing-period button { flex: 1; border: 0; border-radius: 9px; padding: 9px; background: transparent; color: var(--muted); cursor: pointer; font: 500 14px var(--sans); }
.billing-period button[aria-pressed="true"] { background: var(--paper); color: var(--ink); box-shadow: 0 2px 8px rgb(42 37 33 / .09); }
.billing-plans { display: grid; gap: 8px; }
.billing-plan { display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 12px; padding: 12px; border: 1px solid var(--dot); border-radius: 12px; }
.billing-plan.selected { border-color: var(--accent); background: var(--paper-2); }
.billing-plan div { display: flex; flex-direction: column; gap: 2px; }
.billing-plan strong { font: 500 17px var(--serif); }
.billing-plan span, .billing-plan p { color: var(--muted); font: 400 13px var(--sans); }
.billing-plan p { white-space: nowrap; }
.billing-plan b { font: 500 21px var(--serif); color: var(--ink); }
.billing-plan .btn { font-size: 13px; padding: 8px 12px; white-space: nowrap; }
@media (max-width: 540px) { .billing-plan { grid-template-columns: 1fr auto; } .billing-plan .btn { grid-column: 1 / -1; } }
.lg-sent { font: 400 13px/1.5 var(--sans); color: var(--muted); margin-top: -4px; overflow-wrap: anywhere; }
.code-row .text-in:placeholder-shown { letter-spacing: 0; font-family: var(--sans); }
.toast { left: 16px; right: 16px; margin: 0 auto; width: fit-content; transform: none; max-width: min(480px, calc(100% - 32px)); line-height: 1.45; }
.toast.err { border-radius: 12px; padding-left: 22px; }
.toast.err::before { content: ''; position: absolute; left: 9px; top: 8px; bottom: 8px; width: 3px; border-radius: 2px; background: var(--accent); filter: brightness(1.6); }
@media (max-width: 900px), (pointer: coarse) {
  .panel-head .home, .room-top .home { min-height: 44px; }
  .daynight { width: 44px; height: 44px; }
  .thumb .x { top: 0; right: 0; width: 44px; height: 44px; font: 500 14px/44px var(--sans); background: radial-gradient(circle, rgb(42 37 33 / .72) 0 11px, transparent 12px); }
  .add-note { min-height: 44px; padding: 12px 0; }
  .drop.slim { min-height: 44px; }
  .head-r .link-btn, .head-r .link-btn.quiet, .room-top .pill-btn { min-height: 44px; min-width: 44px; justify-content: center; }
  .modal-card .ic { width: 44px; height: 44px; }
  .modal-card .usage .linkish { min-height: 44px; min-width: 44px; }
  .modal-card .text-in, .modal-card .btn { min-height: 48px; }
}

/* A clear 2D reader alongside the room's 3D flip book. */
.view-choice { border: 0; padding: 0; margin: 0; }
.view-options { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 7px; }
.view-options label { position: relative; min-width: 0; cursor: pointer; }
/* 让隐藏的单选覆盖整张卡片：点击区就是卡片本身（移动端 lint 也会把 13×13 的
   原始 radio 判为点击区不足） */
.view-options input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
/* 两张卡片文字行数不同会让它们看起来「大小不一致」：描述用 margin-top:auto 贴底对齐，
   并把文案改成等长，行数就一致了。 */
.view-options span { display: flex; flex-direction: column; gap: 4px; min-height: 86px; padding: 13px 14px; border: 1px solid var(--dot); border-radius: 12px; background: #fffcf6; }
.view-options strong { font: 500 14px/1.35 var(--sans); }
.view-options small { margin-top: auto; color: var(--muted); font: 400 11.5px/1.45 var(--sans); }
.view-options input:checked + span { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); background: #fff7f1; }
.view-options input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 风格：带缩略图的下拉选择器（React: _studio/theme-select.js）。底层仍是
   input[name=theme] 单选——js/app/ui.js 生成时读的是它，别改成自绘状态。
   列表做成「就地展开」（不是绝对定位浮层）：面板本身是 overflow-y:auto 的滚动容器，
   浮层会被裁掉。 */
.theme-select { margin-top: 7px; }
.theme-trigger { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px 9px 9px; border: 1px solid var(--dot); border-radius: 12px; background: #fffcf6; color: var(--ink); text-align: left; cursor: pointer; }
.theme-trigger:hover { border-color: rgb(42 37 33 / .3); }
.theme-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-thumb { width: 52px; height: 34px; flex: none; border-radius: 6px; object-fit: cover; box-shadow: 0 0 0 1px rgb(42 37 33 / .12); }
.theme-pick { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.theme-pick b { font: 500 14px/1.25 var(--sans); }
.theme-pick small { color: var(--muted); font: 400 11.5px/1.35 var(--sans); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.theme-caret { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--muted); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: transform .2s var(--ease); }
.theme-trigger[aria-expanded="true"] .theme-caret { transform: rotate(180deg); }
/* 底部「做成手帐」是 position:sticky 的吸底按钮，会盖住菜单下半截——这两个
   scroll-margin 让展开时把它滚到按钮上方（theme-select.js 展开后会调 scrollIntoView）。 */
.theme-menu { margin: 6px 0 0; padding: 6px; list-style: none; border-radius: 14px; border: 1px solid var(--dot); background: #fffaf2; box-shadow: inset 0 0 0 1px #fffdf9; display: flex; flex-direction: column; gap: 2px; scroll-margin: 10px 0 104px; }
.theme-menu button { display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 8px; border: 0; border-radius: 10px; background: none; color: var(--ink); text-align: left; cursor: pointer; }
.theme-menu button:hover { background: rgb(42 37 33 / .06); }
.theme-menu button.on { background: #f6ece0; }
.theme-tick { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--accent); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.panel-hint { color: var(--muted); font: 400 12px/1 var(--mono); }
.flat-reader { position: absolute; inset: 0 0 68px; z-index: 2; display: grid; place-items: center; overflow: auto; padding: 32px; background: radial-gradient(circle at 50% 20%, #fffaf1, #e9dfcd); }
.flat-reader[hidden] { display: none; }
.flat-pages { display: flex; justify-content: center; align-items: center; gap: 3px; max-width: 100%; max-height: 100%; filter: drop-shadow(0 18px 22px rgb(67 46 26 / .23)); }
.flat-pages img { display: block; width: auto; max-width: min(46%, 550px); max-height: calc(100svh - 170px); object-fit: contain; background: white; }
body.flat-view .stage { position: fixed; inset: 0; z-index: 4; height: auto; min-height: 0; }
body.flat-view .flat-reader { position: fixed; inset: 0; padding: 75px 24px 100px; }
body.flat-view .room-top { opacity: 1; pointer-events: auto; }
body.flat-view .stage-bar { display: flex; z-index: 5; }
body.flat-view #shelf-back { display: inline-flex; }
body.flat-view:not(.has-room) #panel-open { display: none; }
body.flat-view.has-room .flat-reader { position: fixed; inset: 0; padding: 72px 24px 100px; }
body.flat-view.has-room .stage-bar { display: flex; z-index: 5; }
body.flat-view.has-room .room-home-bar { display: none; }
body.flat-view.has-room .room-top { opacity: 1; pointer-events: auto; }
body.flat-view.has-room .panel { transform: translateX(calc(-100% - 24px)); }
body.flat-view.has-room #shelf-back, body.flat-view.has-room #panel-open { display: inline-flex; }
.room-tool { display: grid; place-items: center; width: 36px; height: 36px; padding: 8px; }
.room-tool svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.room-tool[aria-pressed="true"] { background: #f4e3db; color: var(--accent); }
#login-form { width: min(510px, 100%); max-height: min(92svh, 820px); overflow-y: auto; gap: 16px; padding: 25px 32px 28px; background: #fffaf0; border: 1px solid #e5d1ad; box-shadow: 0 32px 90px -30px #231811, inset 0 0 0 5px #fffaf0, inset 0 0 0 6px #eadabf; }
#login-form header { margin-bottom: 0; }
.login-mark { font: 700 19px/1 var(--serif); color: var(--ink-2); }
.login-mark span { font: 400 11px/1 var(--mono); letter-spacing: .08em; color: var(--accent); }
.login-intro { text-align: center; }
.login-seal { width: 68px; height: 68px; display: grid; place-items: center; margin: 0 auto 13px; color: var(--accent); background: #f5e8d9; border: 2px solid #dec8a8; border-radius: 50%; box-shadow: 0 5px 12px #7a56342e; font: 700 30px var(--serif); }
.login-intro .mono { color: var(--accent); letter-spacing: .14em; }
.login-intro h2 { font: 500 clamp(24px, 4vw, 32px)/1.35 var(--serif); margin: 8px 0; }
.login-intro > p:last-child { color: var(--muted); font-size: 14px; line-height: 1.7; }
.login-benefits { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; padding: 13px 0; border-top: 1px solid #e9dac1; border-bottom: 1px solid #e9dac1; color: var(--ink-2); font: 400 12px/1.4 var(--sans); }
#login-form .lg-code { gap: 12px; }
#login-form .lg-code .field .mono { display: block; margin-bottom: 5px; color: var(--ink-2); }
#login-form .text-in { min-height: 45px; background: #fffdf8; }
#login-form #lg-go { background: var(--accent); min-height: 48px; }
#login-form .legal-links { text-align: center; }
@media (max-width: 540px) { .books { grid-template-columns: 1fr 1fr; gap: 9px; } .books img { height: 150px; } #login-form { padding: 19px; } .flat-reader { padding: 12px; } .flat-pages { display: block; max-height: none; } .flat-pages img { max-width: 100%; max-height: none; width: min(100%, 420px); } body.flat-view.has-room .flat-reader { padding: 75px 14px 125px; display: block; } }
