/* Layout and neutral structure only. Colours, fonts and ornaments live in skins/b.css; results screens get skins/stage.css. */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; min-height: 100vh; line-height: 1.5; overflow-x: hidden; }
h2, h3, h4 { margin: .2em 0 .5em; }
button { font: inherit; font-weight: bold; cursor: pointer; border: 0; padding: .55em 1.4em; transition: transform .12s, box-shadow .12s, filter .12s; }
button:hover { transform: translateY(-1px); }
button:active { transform: translateY(2px); }
button:disabled { opacity: .5; cursor: not-allowed; transform: none; }
button:focus-visible { outline: 3px solid var(--focus, #6b4cff); outline-offset: 3px; }
button.small { font-size: .82em; padding: .3em .9em; }
.neg { font-weight: bold; }
/* sprites and mascots are stored 4x (tools/copy_assets.py), so smooth downscaling keeps the pixel art sharp */
img.sprite { height: 72px; width: auto; }
img.mascot { height: 34px; width: auto; }
img.mascot[src$=".gif"] { image-rendering: pixelated; }

/* ── 頂欄 HUD ── */
.topbar { position: relative; z-index: 6; display: flex; flex-wrap: wrap; align-items: center; gap: .5em .7em; padding: .7em 1.2em; }
.topbar .logo { font-size: 1.25em; margin-right: .3em; white-space: nowrap; }
.topbar .pill { display: inline-flex; align-items: center; gap: .35em; padding: .22em .9em; white-space: nowrap; }
.topbar .pill > i { font-style: normal; display: inline-grid; place-items: center; width: 1.7em; height: 1.7em; margin: -.3em .05em -.3em -.75em; border-radius: 50%; font-size: .95em; }
.topbar .help { margin-left: auto; }
/* 聲音控制（頂欄與標題畫面）：🎵／🔊 開關＋音量滑桿 */
.audio-ctl { display: inline-flex; align-items: center; gap: .3em; white-space: nowrap; }
.audio-ctl button.small { padding: .2em .5em; }
.audio-ctl button.off { opacity: .55; }
.audio-ctl input[type=range] { width: 4.5em; accent-color: var(--pink-deep, #c7456a); }
.topbar .audio-ctl { margin-left: auto; }
.topbar .audio-ctl ~ .help { margin-left: 0; }
.title-audio { margin-top: .6em; }
.title-credit { margin: .2em 0 0; }
.title-credit small { padding: .1em .7em; border-radius: 8px; background: rgba(255, 253, 249, .8); color: #6b5a6e; }
.seed-box { margin: .8em auto 0; max-width: 420px; padding: .4em 1em; border-radius: 12px; background: rgba(255, 253, 249, .88); }
.seed-box summary { cursor: pointer; font-weight: bold; }
.seed-box p { margin: .4em 0; }
.seed-box input { font: inherit; width: 11em; max-width: 60vw; padding: .35em .6em; border-radius: 8px; border: 2px solid #c9b8d8; text-transform: uppercase; letter-spacing: .05em; }
.seed-row { margin: .8em 0 .2em; }
.seed-row b { letter-spacing: .06em; }
.seed-row small { display: block; }
.card-preview img { display: block; width: min(100%, 320px); margin: .4em auto .2em; border-radius: 12px; box-shadow: 0 4px 14px rgba(0, 0, 0, .35); }
@media (max-width: 700px) {
  .audio-ctl input[type=range] { width: 3.2em; }
  .topbar { gap: .35em .3em; padding: .5em .5em .55em; font-size: .78em; }
  .topbar .logo { display: none; }
  .topbar .pill { padding: .15em .55em; }
  .topbar .pill > i { width: 1.55em; height: 1.55em; margin-left: -.5em; }
  .topbar .help { padding: .25em .6em; }
  .topbar .goal-pill { white-space: normal; max-width: 100%; }
  .topbar .pill { white-space: normal; max-width: 100%; }   /* Batch M1: big text wraps instead of widening the page */
}

/* ── 休息室：lounge.jpg 當背景，小人走在地板上；每人一條自己的走道（--i / --n），不會擠在一起 ── */
.office {
  position: relative; height: calc(200px + 5em); max-width: 1068px; margin: 1em auto 0; overflow: hidden;
  --base: 18px; --step: 22px; --head: 50px;   /* the em part of the height is room for name tags and the bubble line at any text size; floor of the front row, back-row lift, her head's x in the walker (name tag and bubble) */
  background: url(assets/bg/lounge.jpg) center 78% / cover no-repeat;
}
.walker { position: absolute; bottom: calc(var(--base) + var(--row) * var(--step)); z-index: calc(2 - var(--row)); animation: stroll var(--d) ease-in-out var(--delay) infinite alternate; }
.walker .flip { display: flex; align-items: flex-end; gap: 2px; }
.walker .flip img { animation: face calc(var(--d) * 2) steps(1) var(--delay) infinite; }
.walker img.sprite { height: 112px; }
.walker img.mascot { height: 52px; }
.walker .name { position: absolute; top: -1.6em; left: var(--head); transform: translateX(-50%); font-size: .72em; padding: 0 .6em; white-space: nowrap; }
.walker.resting, .walker.resting .flip img { animation-play-state: paused; }
@keyframes stroll { from { left: calc(var(--i) * 100% / var(--n) + 1%); transform: translateX(0); } to { left: calc((var(--i) + 1) * 100% / var(--n) - 1%); transform: translateX(-100%); } }
/* 原圖朝右的：往右走（前半）用原圖，往左走時鏡像 */
@keyframes face { 0% { transform: scaleX(1); } 50% { transform: scaleX(-1); } }
/* 原圖朝左的（Okami、小烏鴉、Kuu、松鼠）反過來翻：往右走時鏡像，往左走時用原圖 */
.walker .flip img:is([src*="okami_"], [src*="crow_"], [src*="kuu_"], [src*="squirrel_"]) { animation-name: face-left; }
@keyframes face-left { 0% { transform: scaleX(-1); } 50% { transform: scaleX(1); } }
@media (max-width: 700px) {
  /* Lanes are only ~85px here, so walkers may overlap: alternate floor depths (back row higher, behind) make it read as depth. */
  .office { height: calc(140px + 4.4em); margin: .7em .6em 0; --base: 10px; --step: 30px; --head: 34px; }
  .walker img.sprite { height: 80px; }
  /* Mascots tag along at the owner's feet instead of beside her, so each walker stays about one sprite wide. */
  .walker .flip { position: relative; }
  .walker img.mascot { height: 34px; position: absolute; bottom: -4px; left: 58%; }
  .walker img.mascot + img.mascot { left: 72%; bottom: 0; }
  .walker img.mascot + img.mascot + img.mascot { left: 44%; bottom: -8px; }
}
/* Short desktop windows (e.g. 1280×720): shrink the lounge so the first member card + activity stickers clear the sticky footer without scrolling. */
@media (min-width: 701px) and (max-height: 800px) {
  .office { height: calc(130px + 4.4em); --base: 13px; --step: 16px; --head: 36px; }
  .walker img.sprite { height: 80px; }
  .walker img.mascot { height: 38px; }
}

/* ── 地圖／清單切換與探班列 ── */
/* 粉絲應援任務（批次 J） */
.fan-tasks { display: flex; flex-wrap: wrap; align-items: center; gap: .3em .6em; max-width: 1100px; margin: .8em auto 0; padding: .35em 1em; box-sizing: border-box; }
.fan-tasks > b { color: #5b3d22; background: rgba(255, 253, 249, .85); padding: .05em .7em; border-radius: 999px; font-size: .9em; }
.fan-tasks ul { display: flex; flex-wrap: wrap; gap: .4em; margin: 0; padding: 0; list-style: none; min-width: 0; }
.fan-task { display: flex; align-items: center; gap: .45em; padding: .25em .7em .25em .35em; border-radius: 14px; background: rgba(255, 253, 249, .92); border: 2px dashed #f0b3c6; font-size: .82em; line-height: 1.35; min-width: 0; }
.fan-task.ok { border-style: solid; border-color: #6fbf9b; background: #eefaf2; }
.fan-task small { display: block; color: #7a6a5a; }
.fan-task .fan-face { width: 28px; height: 28px; object-fit: contain; flex: none; }
@media (max-width: 700px) { .fan-tasks { padding: .3em .6em; margin-top: .6em; } .fan-task { font-size: .76em; } }
.plan-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5em 1em; max-width: 1100px; margin: 1em auto 0; padding: 0 1em; }
.visit-row { display: flex; flex-wrap: wrap; align-items: center; gap: .35em .45em; }
.view-toggle { display: flex; gap: .3em; margin-left: auto; }
.plan-bar button.small { padding: .25em .8em; }
@media (max-width: 700px) { .plan-bar { padding: 0 .6em; margin-top: .7em; margin-bottom: 1.4em; } .view-toggle { display: none; } }   /* phones: list only; Fix O-5: room for the first card's washi tape */
.plan-bar { position: relative; z-index: 2; }   /* Fix O-5: the 探班 row stays above a member card's tape */

/* Map mode: the lounge is a slim strip under the top bar so it stays visible above the map. */
.office.compact { height: calc(86px + 4em); margin-top: .5em; --base: 8px; --step: 14px; --head: 30px; }
.office.compact .walker img.sprite { height: 64px; }
.office.compact .walker img.mascot { height: 30px; }
.office.compact .walker .bubble { translate: 0 8px; }   /* fix S-8: the map view's short lounge cut the bubbles' top edge (they still clear the back row's name tags) */

/* ── 城鎮地圖（排程主畫面，寬螢幕預設）── */
.mapmode { max-width: 1400px; margin: 0 auto; padding: .6em 1em .5em; }
.who-row { display: flex; flex-wrap: wrap; gap: .5em; margin-bottom: .6em; }
.who { display: inline-flex; align-items: center; gap: .35em; padding: .2em .9em .2em .3em; }
.who img.mini { height: 34px; width: auto; }
.who .wp { min-width: 1.3em; text-align: center; }
.who[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }
.who.bumped { animation: bumped .5s ease-in-out; }
.map-grid { display: grid; grid-template-columns: minmax(0, 2.3fr) minmax(300px, 1fr); gap: 1em; align-items: start; }
@media (max-width: 1000px) { .map-grid { grid-template-columns: minmax(0, 1fr); } }
/* fix V-3: two columns — the member chips and the map stay in view while the side panel (便條, her card, the job board) scrolls past,
   instead of leaving an empty column beside the board. Only when they fit above the footer (tall enough windows). */
@media (min-width: 1001px) and (min-height: 700px) { .map-main { position: sticky; top: .5em; z-index: 1; } }
.town { position: relative; aspect-ratio: 1680 / 944; background: url(assets/bg/map.jpg) center / 100% 100% no-repeat; }
.plot { position: absolute; transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, 0px))); display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 0; background: none; border: 0; box-shadow: none; text-shadow: none; }
.plot:hover { transform: translate(calc(-50% + var(--dx, 0px)), calc(-52% + var(--dy, 0px))); }
.plot:active { transform: translate(calc(-50% + var(--dx, 0px)), calc(-48% + var(--dy, 0px))); }
.plot .tag { display: flex; flex-direction: column; align-items: center; padding: .1em .7em; font-size: .82em; line-height: 1.25; white-space: nowrap; }
.plot .tag small { font-size: .78em; font-weight: normal; }
.plot .tag .tn { white-space: nowrap; }   /* fix U-N7: marks + icon + name on one row */
.plot .here { display: flex; }
.plot .here img.mini { height: 40px; width: auto; margin: 0 -4px; filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .35)); }
.plot .eye { font-size: .72em; padding: 0 .55em; white-space: nowrap; }
.plot.locked { cursor: not-allowed; opacity: .85; }
.plot.locked:hover { transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, 0px))); }
.plot.locked::after { content: attr(data-tip); position: absolute; top: 100%; margin-top: 4px; padding: .1em .6em; font-size: .72em; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity .15s; }
.plot.locked:hover::after, .plot.locked:focus-visible::after { opacity: 1; }
.plot.work:hover { transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, 0px))); }
.pins { display: flex; flex-direction: column; align-items: stretch; gap: 3px; max-width: 13em; max-height: 8.5em; overflow-y: auto; }
.pin { display: flex; align-items: center; gap: .35em; padding: .15em .55em; font-size: .72em; text-align: left; line-height: 1.25; }
.pin .pt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pin .pn { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pin .pc { font-size: .88em; line-height: 1.15; }
.pin img.mini { height: 22px; width: auto; }
.map-side .all-set { text-align: center; }
@media (max-width: 1000px) { .plot .tag { font-size: .7em; } .plot .here img.mini { height: 28px; } .pin { font-size: .62em; } }

/* 休息室的小對話泡泡（偶爾冒出來；被點的時候固定顯示幾秒）。Batch M1: one line (…), all at the same height just above the
   back row's name tags (the front row's bubble is lifted by --step), so a bubble never covers another member or her name tag
   and never runs out of the lounge. One shared lounge clock (src/ui/office.js, Codex review) gives walker i the i-th 3.5s slot
   (.peek, about 2.5s), so two never show at once — assigning someone or clicking never restarts anyone's phase;
   while one is clicked (.said) the others stay hidden. The full line goes to the strip under the lounge (.lounge-say).
   Left-half walkers hang their bubble to the right, right-half ones (.r) to the left, so it stays inside the lounge. */
.walker { cursor: pointer; }
.walker .bubble { position: absolute; bottom: calc(100% + 2.4em + (1 - var(--row)) * var(--step)); left: var(--head); transform: translateX(-10%); --tail: 10%; width: max-content; max-width: min(210px, 50vw); padding: .3em .75em; font-size: .74em; line-height: 1.35; opacity: 0; pointer-events: none; z-index: 3; }
.walker.r .bubble { transform: translateX(-90%); --tail: 90%; }
.walker .bubble .bt { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.walker .bubble:has(.bt:empty) { display: none; }
.walker .bubble { transition: opacity .35s ease-in-out; }
.walker:not(.peek):not(.said) .bubble { transition: none; }   /* Codex review of L: a click-held bubble that expires vanishes at once, never fading out over the next one */
.walker.chatty.peek .bubble, .walker.said .bubble { opacity: 1; }
.office:has(.walker.said) .walker:not(.said) .bubble { visibility: hidden; }
.lounge-say { max-width: 1068px; margin: .45em auto 0; padding: .3em .9em; font-size: .85em; line-height: 1.45; border-radius: 12px; }
@media (max-width: 700px) { .lounge-say { margin: .45em .6em 0; font-size: .78em; } }
.walker:focus-visible { outline: 3px solid var(--focus, #6b4cff); outline-offset: 2px; border-radius: 8px; }

/* 週結算的同地點閒聊、探班選人、信賴 */
.duo-list { display: flex; flex-wrap: wrap; justify-content: center; gap: .6em; margin: .6em 0 .2em; }
.duo { flex: 0 1 420px; text-align: left; padding: .5em .9em .6em; }
.duo p { margin: .15em 0; font-size: .9em; }
.duo .chip { display: inline-block; margin-top: .2em; }
.duo.seen { padding: .3em .8em; opacity: .85; }   /* 看過的閒聊：一行小字（OPF P10） */
.duo.seen small { font-size: .8em; line-height: 1.5; }
#toasts { position: fixed; left: 50%; bottom: calc(1.2em + env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: 40; display: flex; flex-direction: column; gap: .4em; width: min(92vw, 560px); pointer-events: none; }
#toasts:empty { display: none; }
#toasts.in-footer { position: static; transform: none; margin: 0 auto .35em; }   /* Batch M1: a slot in the schedule's footer, in the flow */
.toast { padding: .45em .9em; border-radius: 12px; background: rgba(40, 28, 52, .92); color: #fff; font-size: .85em; line-height: 1.45; box-shadow: 0 4px 14px rgba(0, 0, 0, .3); animation: toast 5s ease forwards; }
.toast .hit { color: #ffc75f; }
.toast .chips { display: inline-flex; flex-wrap: wrap; gap: .25em; margin-left: .3em; vertical-align: middle; }
@keyframes toast { 0% { opacity: 0; transform: translateY(8px); } 6%, 85% { opacity: 1; transform: none; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; } }
/* 探班 on the week summary (src/ui/scenes.js visitHtml) */
.visit-inline { display: flex; gap: .8em; align-items: flex-start; max-width: 640px; margin: .7em auto .2em; padding: .6em .9em; text-align: left; border-radius: 16px; }
.visit-inline .vi-face { width: 72px; height: 72px; object-fit: cover; object-position: 50% 12%; border-radius: 50%; flex: none; }
.visit-inline .vi-body { flex: 1; min-width: 0; }
.visit-inline .vi-body p { margin: .2em 0; }
.visit-inline .choices { margin-top: .4em; }
@media (max-width: 500px) { .visit-inline { gap: .5em; padding: .5em .6em; } .visit-inline .vi-face { width: 48px; height: 48px; } }
.who-pick { display: flex; flex-wrap: wrap; justify-content: center; gap: .6em; }
.name-row .trust { font-size: .75em; padding: .05em .7em; white-space: nowrap; }
/* 篇章提示：信賴到了、篇章還沒發生（她自己說想去哪裡） */
.ch-hint { margin: .45em 0 0; padding: .2em .75em; font-size: .8em; line-height: 1.4; border-radius: 10px; color: #5b4a8a; background: #f1ecff; }
/* 今年的願望（批次 J）：進度；這週的行程算得上（step）時亮一點 */
.wish-line { margin: .35em 0 0; padding: .15em .75em; font-size: .78em; line-height: 1.4; border-radius: 10px; color: #3f6b3a; background: #ecf7e6; }
.wish-line.step { background: #d6f0c8; font-weight: bold; }
.wish-line.done { color: #6b5a2a; background: #fff4c8; }

/* ── 排程主畫面 ── */
.main { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 1.2em; padding: 1.2em 1em .5em; max-width: 1100px; margin: 0 auto; }
@media (max-width: 700px) { .main { grid-template-columns: minmax(0, 1fr); padding: 1em .6em .5em; gap: .6em; } }
.card { position: relative; padding: .9em 1.1em; margin-bottom: 1em; }
.tip { max-width: 1068px; margin: 1.2em auto 0; }
.tip .close { position: absolute; top: .6em; right: .6em; }
.tip p { margin: .3em 2em 0 0; }
@media (max-width: 700px) { .tip { margin: 1em .6em 0; } }

.member { display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: .5em 1em; align-items: center; }
.member .avatar { display: grid; place-items: center; width: 84px; height: 92px; }
.member .avatar img.sprite { height: 76px; }
.member .control { grid-column: 1 / -1; }
.member .control p { margin: .2em 0; }
.name-row { display: flex; flex-wrap: wrap; align-items: center; gap: .3em .6em; margin-bottom: .35em; }
.name-row .mname { font-size: 1.2em; }
.name-row .avg { font-size: .75em; padding: .05em .7em; }
.stats { display: flex; flex-wrap: wrap; gap: .45em; }
.stat { display: inline-grid; grid-template-columns: auto auto; grid-template-rows: auto auto; align-items: center; column-gap: .25em; padding: .2em .7em .2em .3em; min-width: 4.6em; }
.stat > i { grid-row: 1 / 3; font-style: normal; display: grid; place-items: center; width: 1.9em; height: 1.9em; border-radius: 50%; font-size: .95em; }
.stat > b { font-size: 1.1em; line-height: 1.05; }
.stat > small { font-size: .66em; line-height: 1; }
.gauges { display: grid; grid-template-columns: 1fr 1fr; gap: .4em 1em; margin-top: .55em; }
.gauge { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: .45em; font-size: .8em; }
.gauge > b { min-width: 1.8em; text-align: right; }
.gauge .bar { height: 12px; overflow: hidden; }
.gauge .bar > i { display: block; height: 100%; transition: width .4s; }
@media (max-width: 700px) {
  .member { grid-template-columns: 64px minmax(0, 1fr); gap: .4em .7em; padding: .8em .8em; }
  .member .avatar { width: 64px; height: 76px; }
  .member .avatar img.sprite { height: 62px; }
  .stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .25em; }
  .stat { min-width: 0; padding: .15em .3em .15em .15em; column-gap: .15em; }
  .stat > i { width: 1.45em; height: 1.45em; font-size: .78em; }
  .stat > b { font-size: 1em; }
  .gauges { grid-template-columns: 1fr; gap: .25em; }
}

.activities { display: grid; grid-template-columns: repeat(var(--n, 6), minmax(0, 1fr)); gap: .5em; margin-top: .3em; }   /* minmax(0, …): big text wraps the labels instead of widening the page (Codex review of M1-20) */
.sticker { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .05em; min-width: 0; min-height: 58px; padding: .35em .2em; font-size: .85em; line-height: 1.15; position: relative; }
.sticker .lbl { max-width: 100%; overflow-wrap: anywhere; }
.sticker .ico { font-size: 1.45em; line-height: 1.1; }
.sticker.on::after { content: '✔'; position: absolute; top: -.55em; right: -.45em; width: 1.5em; height: 1.5em; display: grid; place-items: center; border-radius: 50%; font-size: .8em; }
@media (max-width: 700px) { .activities { grid-template-columns: repeat(var(--pn, 3), minmax(0, 1fr)); gap: .5em .45em; } .sticker { min-height: 54px; font-size: .9em; } }
.member .reminder { display: inline-block; padding: .2em .9em; font-size: .82em; font-weight: bold; margin: .3em 0; }

.board-title { margin: 0 0 .7em; display: inline-block; }
.job h4 { margin: .1em 0 .45em; font-size: 1.05em; }
.terms { display: flex; flex-wrap: wrap; gap: .3em; font-size: .78em; }
.terms span { padding: .05em .6em; }
.job .assign { display: flex; flex-wrap: wrap; gap: .4em; margin-top: .65em; }
.pick { font-size: .82em; padding: .3em .85em; }
.pick .swap { display: block; font-size: .82em; font-weight: normal; opacity: .8; }
.job .ok { display: block; margin-top: .45em; font-size: .85em; }

.member.bumped { animation: bumped .5s ease-in-out; }
@keyframes bumped { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-6px); } 40% { transform: translateX(5px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(2px); } }

.sticky-footer { position: sticky; bottom: 0; z-index: 5; padding-top: .45em; padding-bottom: env(safe-area-inset-bottom); }
.footer { display: flex; justify-content: center; gap: 1em; padding: 0 1em .8em; }
.footer button { font-size: 1.05em; padding: .6em 1.6em; }
.errors { min-height: 1.4em; padding: 0 1em .4em; text-align: center; font-size: .88em; }
.warns { padding: 0 1em .4em; text-align: center; font-size: .85em; font-weight: bold; color: #c2410c; }   /* Batch I: 這週會倒下 */
.member .risk { margin: .35em 0 0; padding: .2em .7em; border-radius: 10px; font-size: .8em; font-weight: bold; color: #b42318; background: #fff0ec; }
.sticker.risk { outline: 2px dashed #e8590c; outline-offset: -3px; }
.pick .fall { color: #b42318; font-weight: bold; opacity: 1; }
.hint { text-align: center; font-size: .8em; margin: .6em 1em 1.5em; }
.footer .short { display: none; }
/* Phones: one compact row (shorter label on the rest button), so the footer stays a thin strip. */
@media (max-width: 700px) {
  .sticky-footer { padding-top: .3em; }
  .errors { min-height: 0; padding: 0 .6em .25em; font-size: .76em; line-height: 1.3; }
  .warns { padding: 0 .6em .25em; font-size: .76em; line-height: 1.3; }
  .footer { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: .45em; padding: 0 .6em .5em; }
  .footer button { font-size: .9em; padding: .5em .3em; line-height: 1.25; min-height: 44px; }   /* Batch M1: wraps at big text instead of widening the page */
  .footer .long { display: none; }
  .footer .short { display: inline; }
}

/* ── 疊加畫面（z-index 高於 sticky footer）── */
#scene { position: fixed; inset: 0; z-index: 20; display: flex; align-items: flex-start; justify-content: center; overflow: hidden auto; }   /* x hidden: wide portraits may spill past the screen edge */
#scene[hidden] { display: none; }
#scene > * { margin: auto; }
#scene.talk::before, #scene.title::before, #scene.ending::before { content: ''; position: fixed; inset: 0; z-index: -1; background: center / cover no-repeat; }
#scene.talk::before { background-image: var(--bg, none), url(assets/bg/office.jpg); inset: -12px; filter: blur(3px); }   /* --bg: an outing's place (src/ui/scenes.js playScene) */
/* fix V-2: a colour wash over a scene's picture — the camp's lounge at night, the TV studio after the lights go down */
#scene.talk.tint-night::before { background-image: linear-gradient(rgba(22, 26, 74, .55), rgba(40, 30, 90, .45)), var(--bg, none), url(assets/bg/office.jpg); }
#scene.talk.tint-dim::before { background-image: linear-gradient(rgba(30, 20, 50, .32), rgba(30, 20, 50, .32)), var(--bg, none), url(assets/bg/office.jpg); }
#scene.title::before { background-image: url(assets/bg/title.jpg); }
#scene.ending::before { background-image: url(assets/bg/stage.jpg); }

/* Batch M1: a dialogue scene is zones that never overlap — the character area, then the dialog: speaker row, text (a long
   line scrolls inside .say), and the choices / 繼續 row (.acts). The 4:5 face box (.pbox) is sized so the whole wide sheet
   (1.3x its height, tools/copy_assets.py WIDE_TOP) fits the character area: hair, ears and halos are never cut and the
   dialog sits under her, never on her face or chest (立繪使用指南 §4.1). */
.stage { position: relative; width: min(920px, 100%); height: 100%; display: flex; flex-direction: column; }
.stage .actor { flex: 1 1 0; min-height: 8rem; padding-top: .4em; display: flex; justify-content: center; align-items: flex-end; pointer-events: none; }
.stage .frame { position: relative; height: 100%; display: flex; justify-content: center; align-items: flex-end; }
/* .pbox = the old 4:5 face box; the wide sheet is 2.7x its width and 1.3x its height with the box bottom-centred, so it
   spills up and sideways inside the character area. */
.stage .actor:not(.boss) .frame { width: 100%; }
.stage .pbox { position: relative; height: calc(100% / 1.3); aspect-ratio: 4 / 5; max-width: 100%; container-type: size; }
/* The sheet's cut bottom edge is never faded (user: no see-through belly) and never floats: it reaches down past the name-tag gap
   and --tuck into the dialog box, which covers only that already-cut strip (more than the 5px breathe, so no gap ever shows). */
.stage { --tuck: 16px; }
.stage .pbox img.portrait { position: absolute; bottom: calc(-1.38em - var(--tuck)); left: 50%; translate: -50% 0; height: calc(1.3 * min(100cqh, 125cqw)); width: auto; max-width: none; animation: breathe 4.5s ease-in-out infinite; }
.stage .actor.boss { align-items: center; padding: 1.2em 0 .4em; }
.stage .actor.boss .frame { height: min(100%, 420px); }   /* the frame hugs the sticker, so the tape (skins/b.css) stays on its top edge */
.stage img.portrait.boss { height: 100%; width: auto; max-width: 68vw; object-fit: contain; padding: 14px; animation: none; }
.dialog { position: relative; z-index: 1; margin: 0 1em 1em; padding: 1.5em 1.5em 1em; min-height: 8.5em; font-size: 1.06em; }
.dialog p { margin: .2em 0 .5em; }
.dialog .who { position: absolute; top: -1.05em; left: 1.2em; padding: .15em 1.2em; font-weight: bold; }
/* The dialog box has one fixed height per screen size (user: the portrait must not shrink when the text, the choices or a reward
   box get long), so every scene's portrait is the same size and her cut edge always meets the box top. What doesn't fit scrolls
   inside. Batch K-c: with large text only (src/ui/scenes.js fitDialog: root text > 18px) the box grows by what its text and
   choices still need (--extra), so the choices stay on screen; it rises over her (--lift) instead of shrinking her, but never
   above the bottom 20% of the character area (below her chin: the face is never covered). Past that the portrait gives way. */
.stage { --base: 30vh; }
@supports (height: 1dvh) { .stage { --base: 30dvh; } }
.stage .dialog {
  flex: none; display: flex; flex-direction: column; height: calc(var(--base) + var(--extra, 0px)); max-height: calc(100% - 8rem - 2.3em + var(--lift, 0px)); min-height: 0;
  margin-top: calc(1.3em - var(--lift, 0px)); padding-top: .9em; box-sizing: border-box;
}
.stage .dialog .who { position: relative; top: auto; left: auto; align-self: flex-start; margin: -2.05em 0 .3em -.3em; }
/* A long line scrolls inside .say (up to 40% of the screen); .dbody (text + choices) scrolls only as a last resort
   (huge text on a phone), so the choices are never pushed off the screen. */
.stage .dialog .dbody { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; overscroll-behavior: contain; }
.stage .dialog .say { flex: 0 1 auto; min-height: 2.6em; overflow-y: auto; overscroll-behavior: contain; }
.stage .dialog .acts { flex: none; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: .4em .8em; }
.stage .dialog .acts .choices { flex: 1 1 100%; margin-top: .4em; }
.stage .dialog .choices button { padding-left: .9em; padding-right: .9em; }
/* Wide screens: short choices side by side (a shorter dialog leaves the portrait more room); phones stack them. */
@media (min-width: 701px) { .stage .dialog .acts .choices { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(15em, 40%), 1fr)); } }   /* K-c: 2 a row even with large text */
.stage .dialog .acts .ff { margin-right: auto; }
#scene .stage button { min-height: 44px; }
.dialog .next { display: block; text-align: right; font-size: .8em; }
.dialog .next::after { content: ' ▼'; display: inline-block; animation: nudge .8s ease-in-out infinite alternate; }
.choices { display: flex; flex-direction: column; gap: .55em; margin-top: .8em; }
.choices button { text-align: left; }
@keyframes breathe { 50% { transform: translateY(-5px); } }
@keyframes nudge { from { transform: translateY(-3px); } to { transform: none; } }   /* 批次 L: never pokes past the dialog body (a 2px overflow showed a scrollbar on every 繼續 line) */
@media (max-width: 700px) { .dialog { margin: 0 .6em .8em; padding: 1.4em 1.1em .9em; } .stage .dialog { margin-top: calc(1.3em - var(--lift, 0px)); padding-top: .9em; }
  .stage { --base: 26vh; } @supports (height: 1dvh) { .stage { --base: 26dvh; } }   /* Fix O-9: 38vh left ~40% of the box empty for a usual line; taller content rises over her (fitDialog) */
  /* fix S-4: with choices the question never shrinks under the first button (its 2nd line was covered); the box scrolls as one instead */
  .stage .dialog .dbody:has(.choices) > .say { flex: none; overflow: visible; } }
/* fix S-4: more choices below the box's edge → a cue on the bottom edge (scenes.js scrollCue), gone once the last one is in view */
.stage .dialog.more { padding-bottom: 2em; }   /* fix U-N8: a strip of its own for the cue, under the scrolling choices */
.stage .dialog.more::after { content: '▼ 往下還有選項'; position: absolute; left: 50%; bottom: .25em; translate: -50% 0; z-index: 2; pointer-events: none;
  padding: .15em .9em; border-radius: 1em; font-size: .78em; font-weight: bold; color: #fff; background: rgba(150, 45, 80, .88); box-shadow: 0 1px 4px rgba(60, 20, 30, .35); animation: nudge .8s ease-in-out infinite alternate; }

.chips { display: flex; flex-wrap: wrap; gap: .3em; margin: .4em 0; justify-content: center; }
.chip { padding: .1em .65em; font-size: .82em; font-weight: bold; }
.center { width: min(640px, calc(100% - 2em)); margin: auto; text-align: center; }
.center.wide { width: min(1000px, calc(100% - 2em)); }
#scene .center.card { margin: 2em auto; padding: 1.3em 1.4em; }
@media (max-width: 700px) { .center, .center.wide { width: calc(100% - 1.2em); } #scene .center.card { margin: 1em auto; padding: 1.1em .8em; } }

/* 週結算：拍立得 + 印章 */
.summary { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.2em; margin: .8em 0 .4em; }
.result-card { position: relative; flex: 0 1 216px; min-width: 0; padding: .6em .6em .7em; }
.result-card .photo { position: relative; aspect-ratio: 4 / 4.2; overflow: hidden; }
.result-card .photo img { width: 100%; height: 100%; object-fit: cover; object-position: center 12%; display: block; }
.result-card .rname { display: block; margin-top: .45em; font-size: 1.1em; }
.result-card p { margin: .15em 0; font-size: .86em; }
.result-card .drift { display: block; margin-top: .3em; font-size: .75em; opacity: .8; }
.stamp { position: absolute; right: 6%; bottom: 8%; padding: .25em .7em; font-weight: 900; font-size: 1.05em; white-space: nowrap; transform: rotate(-12deg); animation: stamp-in .45s cubic-bezier(.2, 1.4, .4, 1) both; animation-delay: var(--stamp-delay, .25s); }
@keyframes stamp-in { from { opacity: 0; transform: scale(2.6) rotate(-30deg); } to { opacity: 1; transform: scale(1) rotate(-12deg); } }
@media (max-width: 700px) {
  .summary { gap: .7em; }
  .result-card { flex-basis: calc(50% - .35em); padding: .4em .4em .5em; }
  .result-card p { font-size: .8em; }
  .result-card .chips { gap: .2em; }
  .result-card .chip { font-size: .72em; padding: .05em .45em; }
  .stamp { font-size: .85em; }
}

/* 星座卡 */
.zodiac { display: grid; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: .65em; margin: 1em 0; }
.sign { position: relative; display: flex; flex-direction: column; align-items: center; gap: .1em; padding: .6em .4em .7em; }
.sign .glyph { font-family: "Segoe UI Symbol", "Apple Symbols", "Noto Sans Symbols", sans-serif; font-size: 1.7em; line-height: 1.2; font-weight: normal; }
.sign b { font-size: .95em; }
.sign small { display: flex; flex-wrap: wrap; justify-content: center; gap: .2em; font-size: .72em; font-weight: normal; }
.sign small span { padding: 0 .4em; }
@media (max-width: 700px) { .zodiac { grid-template-columns: repeat(3, 1fr); gap: .45em; } .sign { padding: .45em .2em .55em; } .sign small { font-size: .68em; } }

/* 帳本 */
table.ledger { width: 100%; border-collapse: collapse; margin: .6em 0; }
.ledger td { padding: .5em .8em; text-align: left; }
.ledger td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.help-list { text-align: left; line-height: 1.7; padding-left: 0; list-style: none; counter-reset: tip; }
.help-list li { counter-increment: tip; position: relative; padding: .5em .8em .5em 2.8em; margin-bottom: .5em; }
.help-list li::before { content: counter(tip); position: absolute; left: .7em; top: .55em; width: 1.6em; height: 1.6em; display: grid; place-items: center; border-radius: 50%; font-weight: bold; font-size: .9em; }

/* 標題 */
.title { padding: 1.5em 1em; }
.title h1 { font-size: clamp(1.9em, 8vw, 3.6em); margin: .2em 0 0; line-height: 1.2; white-space: nowrap; }
.title .sub { font-weight: bold; margin: .3em 0 .8em; display: inline-block; padding: .2em 1.6em; }
.title .walkers { display: flex; justify-content: center; align-items: flex-end; gap: 1em; margin: 1em auto; padding: .8em 1.5em .5em; width: fit-content; }
.title-buttons { display: flex; justify-content: center; gap: 1em; }
.title-buttons button { font-size: 1.15em; padding: .65em 2.2em; }
@media (max-width: 700px) { .title .walkers { gap: .4em; padding: .6em .8em .4em; } .title .walkers img.sprite { height: 58px; } }

/* 結局：大舞台。寬螢幕（使用者 2026-10-03「畫面夠大四個人可以一字排開吧」）：四個人一字排開、一樣大（臉框一樣高），
   左到右 史黛菈・歐咖咪・庫路路・艾提；切口在對話框後面（--tuck：跨過 .8em 的間距再塞進對話框 16px），沒有淡出、沒有人被擋。
   手機：Okami 在前排正中間，Kuu 在她正後方的高台上，Stella、Aity 在左右兩側（四個人擠一個窄螢幕，只有後排的身體可以淡出）。
   每個人用 --cx（水平中心）、--top、--h（4:5 臉框的位置和高度，都是 lineup 的比例）定位；寬版立繪在臉框上面多 30%、左右溢出，不切。 */
.lineup { position: relative; z-index: 0; height: min(60vh, 500px); }   /* z-index 0: the dialog under it (z 1) covers the tucked bottoms */
.lineup img {
  position: absolute; left: var(--cx); top: calc(var(--top) - var(--h) * .3 + var(--tuck)); height: calc(var(--h) * 1.3); width: auto; max-width: none;
  transform: translateX(-50%);
  --top: 38%; --h: 62%; --tuck: calc(.8em + 16px);
}
.lineup img.stella { --cx: 12.5%; }
.lineup img.okami { --cx: 37.5%; }
.lineup img.kuu { --cx: 62.5%; }
.lineup img.aity { --cx: 87.5%; }
/* fix V-1: the lineup is wider than the box (wide sheets spill sideways), so the box under it is a band across the whole screen:
   every tucked bottom edge is behind it. The text keeps its old width (padding). */
#scene.ending .lineup + .dialog { margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); border-radius: 0; padding-left: max(1.5em, calc(50vw - 30em)); padding-right: max(1.5em, calc(50vw - 30em)); }
#scene.ending > .center.wide { min-height: 100%; display: flex; flex-direction: column; justify-content: center; gap: .8em; margin-top: 0; margin-bottom: 0; }
@media (max-width: 700px) {
  .lineup { height: min(58vh, 480px); }
  .lineup img { --tuck: 0px; }
  .lineup img.kuu { --cx: 50%; --top: 3%; --h: 34%; }
  .lineup img.stella { --cx: 22%; --top: 17%; --h: 38%; }
  .lineup img.aity { --cx: 78%; --top: 17%; --h: 38%; }
  .lineup img.okami { --cx: 50%; --top: 46%; --h: 54%; --tuck: calc(.8em + 16px); z-index: 1; }   /* front row: no fade, tucked under the dialog */
  .lineup img:not(.okami) { -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 97%); mask-image: linear-gradient(to bottom, #000 70%, transparent 97%); }   /* back row only (allowed on phones) */
}

/* 年底 S：溫和的彩帶（人物後面、不擋臉） */
.confetti { position: fixed; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
.confetti i { position: absolute; top: -24px; left: var(--x); width: 8px; height: 14px; border-radius: 2px; opacity: .85; background: hsl(var(--h) 90% 72%); animation: confetti-fall var(--t) linear var(--d) infinite; }
.confetti i:nth-child(3n) { width: 10px; height: 10px; border-radius: 50%; }
@keyframes confetti-fall { from { transform: translateY(0) rotate(0); } to { transform: translateY(calc(100vh + 40px)) rotate(540deg); } }

/* 公司結局卡 */
.ending-card .kind { display: inline-block; padding: .1em 1em; border-radius: 999px; font-weight: bold; font-size: .85em; }
.ending-card .big-icon { font-size: 2.6em; line-height: 1.2; margin: .3em 0 0; }

/* 去向卡：桌機四張並排；手機一張一列、照片在左 */
.careers { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1em; margin: .8em 0 .4em; }
.career-card { position: relative; display: flex; flex-direction: column; min-height: 340px; border-radius: 16px; overflow: hidden; text-align: left; }
.career-card.back { align-items: center; justify-content: center; gap: .3em; text-align: center; }
.career-card.back .q { font-size: 3.4em; font-weight: 900; line-height: 1; }
.career-card .photo { position: relative; aspect-ratio: 4 / 4.2; overflow: hidden; }
.career-card .photo img { width: 100%; height: 100%; object-fit: cover; object-position: center 12%; display: block; }
/* 職業背景圖（assets/careers，Canva 生成）；結局氣氛低落時（倒閉、隱藏結局）調暗褪色 */
.career-card .photo[style*="background-image"] { background-size: cover !important; background-position: center !important; }
.career-card .photo.low::before { content: ''; position: absolute; inset: 0; background: rgba(30, 22, 40, .45); backdrop-filter: grayscale(.6); }
.career-card .photo img { position: relative; }
.career-card .prop { position: absolute; font-size: 1.5em; line-height: 1; }
.career-card .prop.p0 { top: 6px; left: 8px; transform: rotate(-12deg); }
.career-card .prop.p1 { right: 8px; bottom: 6px; transform: rotate(10deg); }
.career-card .ctext { padding: .55em .75em .8em; }
.career-card .cname { display: block; font-size: 1.08em; line-height: 1.3; }
.career-card .cicon { margin-right: .25em; }
.career-card .cwho { display: block; font-size: .8em; }
.career-card p { margin: .35em 0 0; font-size: .86em; line-height: 1.55; }
.career-card.new { animation: flip-in .55s ease-out both; }
@keyframes flip-in { from { transform: perspective(900px) rotateY(90deg); opacity: .3; } to { transform: none; opacity: 1; } }
.flip-hint { margin: .2em 0 0; font-size: .85em; }
/* 年底演出（節目單）：還沒唱的歌是卡背；節目單按鈕下的小字 */
.result-card.song-back { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 12em; text-align: center; }
.result-card.song-back .q { font-size: 3em; font-weight: 900; line-height: 1; }
.sl-note { display: block; margin-top: .15em; font-size: .8em; font-weight: normal; opacity: .85; }
.setlist-pick { text-align: center; }
.stars { color: #f2b544; letter-spacing: 1px; white-space: nowrap; }
.stars i { font-style: normal; color: #fff4dc; text-shadow: 0 0 1px rgba(80, 20, 40, .6); }   /* 批次 L-a: was gold at 30% (read as dark red on the pink button) */
.setlist-pick .choices { max-width: 30em; margin: 0 auto; }
.setlist-pick .keep-switch { margin: .2em auto .5em; font-size: .85em; border-collapse: collapse; }   /* fix S-16 */
.setlist-pick .keep-switch th, .setlist-pick .keep-switch td { padding: .15em .7em; border-bottom: 1px dashed rgba(120, 90, 60, .3); }
.setlist-pick .who-pick { display: flex; flex-wrap: wrap; justify-content: center; gap: .5em; }
@media (max-width: 700px) {
  .careers { grid-template-columns: minmax(0, 1fr); gap: .55em; }
  .career-card { flex-direction: row; min-height: 0; }
  .career-card .photo { flex: 0 0 92px; height: 120px; aspect-ratio: auto; align-self: flex-start; }   /* fix S-5: a fixed photo box (a long text used to stretch it and re-crop her) */
  .career-card .prop { font-size: 1.15em; }
  .career-card .ctext { padding: .45em .6em .55em; }
  .career-card p { font-size: .8em; line-height: 1.45; }
  .career-card.back { min-height: 64px; flex-direction: row; gap: .6em; }
  .career-card.back .q { font-size: 2em; }
  .result-card.song-back { min-height: 8em; }
}

/* 結局收藏冊 */
.album h4 { margin: 1em 0 .3em; }
.album h4 .count { display: inline-block; margin-left: .4em; padding: 0 .75em; font-size: .85em; }
/* 一排三格：公司結局一個等級一排（S／A／B／C），最後一排倒閉兩種＋隱藏；去向也是三格一排 */
.album-grid { list-style: none; padding: 0; margin: .4em 0 .8em; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6em; }
.album-grid li { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .1em; min-height: 88px; padding: .5em .4em; line-height: 1.3; }
.album-grid .ico { font-size: 1.7em; line-height: 1.2; }
.album-grid b { font-size: .92em; }
.album-grid small { font-size: .72em; }
.album-btn { margin-top: .2em; }
.album-grid li.unseen small { font-size: .7em; line-height: 1.3; }
@media (max-width: 700px) { .album-grid { gap: .4em; } .album-grid li { min-height: 78px; padding: .4em .2em; } .album-grid b { font-size: .8em; } }
.album-note .note-list { list-style: none; padding: 0; margin: .6em 0 1em; display: flex; flex-wrap: wrap; justify-content: center; gap: .5em; }
.album-note .note-list li { padding: .3em .9em; font-weight: bold; }
.album-note .note-list .ico { margin-right: .3em; }

/* 地圖第二期：季節郊遊、NPC 對話框、回憶相簿 */
.plot.outing .tag { font-size: .86em; }
.dialog .who .npc-ico { display: inline-grid; place-items: center; margin-right: .35em; font-size: 1.05em; }
.dialog .who .npc-ico img { height: 1.6em; width: auto; vertical-align: middle; }
/* 黑羽的便條、菸猴：休息室下方一排（不蓋住走動的成員和名牌） */
.lounge-notes { display: flex; flex-wrap: wrap; align-items: flex-start; gap: .5em 1em; max-width: 1068px; margin: .6em auto 0; }
.boss-note, .monkey-say { display: flex; flex-wrap: wrap; align-items: baseline; gap: .1em .6em; padding: .35em .9em .4em; font-size: .82em; line-height: 1.4; }
.boss-note { flex: 1 1 360px; transform: rotate(-.6deg); }
.boss-note small { font-weight: bold; }
.monkey-say { flex: 0 1 380px; }
.monkey-say .npc-ico { margin-right: .3em; }
@media (max-width: 700px) { .lounge-notes { margin: .5em .6em 0; } .boss-note, .monkey-say { font-size: .76em; } }
/* Phones: folded to one line (a 44px tap target); open, the summary keeps only the title and the full text follows. */
.fold { display: block; flex: 1 1 100%; min-width: 0; }
.fold > summary { display: flex; align-items: center; gap: .5em; min-height: 44px; margin: -.35em 0; cursor: pointer; list-style: none; }
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::after { content: '▾'; margin-left: auto; flex: none; }
.fold[open] > summary::after { content: '▴'; }
.fold > summary > b { flex: none; }
.fold .peek { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: normal; }
.fold[open] .peek { display: none; }
.fold > span, .fold > small { display: block; }
.fold[open] > summary { margin-bottom: 0; }
.scene-card, .goal-card { text-align: center; }
.scene-card { display: flex; flex-direction: column; align-items: center; gap: .2em; padding-top: 1.6em; padding-bottom: 1.2em; }
.goal-reward { margin: .5em auto; padding: .3em .8em; border-radius: 14px; background: #fff4c8; border: 2px dashed #f2c94c; max-width: 22em; }
.goal-reward .chips { font-size: 1.1em; }
.gift { margin: .35em 0 .1em; font-weight: bold; color: #7a5cc7; }   /* 🎫 限定通告的獎勵說明 */
.dialog .hit { margin: 0 0 .2em; font-weight: bold; color: #c26a12; }   /* 探班「💡 說中了！」 */
.goal-card .who-pick { display: flex; flex-wrap: wrap; justify-content: center; gap: .5em; }
.scene-card h3 { font-size: 1.4em; margin: .3em 0 .5em; }
.album-tabs { display: flex; justify-content: center; gap: .5em; }
/* 事務所升級（OPF P6）：月結算後的投資畫面；休息室角落的小擺設 */
.upgrades-pick { text-align: center; }
.up-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .6em; margin: .6em 0; }
.up-card { display: flex; flex-direction: column; align-items: center; gap: .3em; padding: .7em .5em; border-radius: 16px; background: #fff; border: 2px solid #eadcf5; }
.up-card.owned { background: #f3fff8; border-color: #a8e6c4; }
.up-name { font-size: 1.05em; }
.up-lv { display: inline-block; margin-left: .2em; padding: 0 .5em; border-radius: 999px; background: #f1e9ff; font-size: .75em; }
.up-now { margin: 0; font-size: .88em; }
.up-next { color: #7a5cc7; font-weight: bold; }
.up-pay { color: #6b7a5c; font-size: .78em; text-align: center; }
.up-card button { margin-top: auto; }
.up-boss { font-size: .9em; }
.policy-pick { text-align: center; }
.policy-pick .choices { max-width: 30em; margin: 0 auto; }
.up-warn { color: #c0392b; font-size: .78em; font-weight: bold; }
.up-card.cant { opacity: .62; filter: grayscale(.5); }   /* Batch I：買不起也列出來 */
.up-short { color: #8a6d9e; font-size: .78em; font-weight: bold; }
.office .deco { position: absolute; top: 10px; left: 12px; z-index: 0; padding: .1em .5em; border-radius: 12px; background: rgba(255, 255, 255, .8); font-size: 1.3em; letter-spacing: .1em; }
@media (max-width: 700px) { .up-grid { grid-template-columns: minmax(0, 1fr); } .office .deco { font-size: 1em; top: 6px; left: 8px; } }

@media (prefers-reduced-motion: reduce) {
  .confetti { display: none; }
  .career-card.new { animation: none; }
  .stamp { animation: none; }
  .stage img.portrait, .dialog .next::after { animation: none; }
  button, .gauge .bar > i { transition: none; }
  .member.bumped { animation: none; outline: 3px solid var(--focus, #6b4cff); outline-offset: 2px; }
  .who.bumped { animation: none; outline: 3px solid var(--focus, #6b4cff); }
  .walker .bubble { transition: none; }   /* still one at a time (the lounge clock), just no fade */
  .plot:hover, .plot:active { transform: translate(calc(-50% + var(--dx, 0px)), calc(-50% + var(--dy, 0px))); }
}

/* 下一局挑戰（Batch I）：標題、結局之後、收藏冊 */
.challenge-box { max-width: 30em; margin: .5em auto; padding: .6em .9em; border-radius: 14px; background: rgba(255, 253, 249, .92); text-align: left; box-shadow: 0 3px 10px rgba(93, 70, 50, .15); }
.challenge-box > b, .challenge-box > small { display: block; text-align: center; }
.challenge-box > small { font-size: .75em; }
.challenge-list { list-style: none; margin: .45em auto 0; padding: 0; display: grid; gap: .4em; max-width: 30em; text-align: left; }
.challenge-list li { display: grid; grid-template-columns: 1.7em 1fr; column-gap: .45em; }
.challenge-list .ico { grid-row: span 2; font-size: 1.25em; line-height: 1.2; }
.challenge-list b { font-size: .9em; }
.challenge-list small { font-size: .78em; opacity: .8; }
.album-grid li.unseen.challenge b { color: inherit; }

/* 避險沿用（批次 L）：「沿用上週」改排休息的人，在排版流裡寫出來，按鈕一下改回去 */
.reuse-guard { max-width: 1068px; margin: .8em auto 0; padding: .45em 1em; box-sizing: border-box; font-size: .9em; }
.reuse-guard p { margin: .2em 0; display: flex; flex-wrap: wrap; align-items: center; gap: .3em .6em; }
.reuse-guard button { min-height: 44px; }
@media (max-width: 700px) { .reuse-guard { margin: .6em .5em 0; font-size: .8em; padding: .35em .6em; } }

/* 手帳印章（批次 L）：照片下面一列（在排版流裡，不蓋人），章「啪」一下蓋上，她的粉絲小圖跟著跳出來 */
.stamps { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: .25em .4em; min-height: 2.3em; margin-top: .45em; overflow: hidden; }   /* overflow: the stamp's scale(2.6) pop never reaches up onto the photo (Codex review of L) */
.stamps .stamp { position: static; font-size: .92em; padding: .12em .55em; }
.stamps .stamp.steady { animation-delay: calc(var(--stamp-delay, .25s) + .2s); transform: rotate(6deg); animation-name: stamp-in2; }   /* not a --stamp-delay self-reference (invalid, Codex review of L) */
@keyframes stamp-in2 { from { opacity: 0; transform: scale(2.6) rotate(30deg); } to { opacity: 1; transform: scale(1) rotate(6deg); } }
.stamps .doodle { height: 2.6em; width: auto; image-rendering: auto; transform: rotate(8deg); animation: doodle-pop .5s cubic-bezier(.2, 1.6, .4, 1) both; animation-delay: calc(var(--stamp-delay, .25s) + .25s); }
@keyframes doodle-pop { from { opacity: 0; transform: translateY(.6em) scale(.4) rotate(-10deg); } to { opacity: 1; transform: rotate(8deg); } }
@media (max-width: 700px) { .stamps .stamp { font-size: .8em; } .stamps .doodle { height: 2.2em; } }
@media (prefers-reduced-motion: reduce) { .stamps .stamp, .stamps .doodle { animation: none; } }
/* 搭檔手記（批次 L）：週結算上的一頁，比閒聊寬一點 */
.duo.duo-memory { flex-basis: 560px; }
.duo.duo-memory .narr { font-style: italic; opacity: .85; }
.duo.duo-memory .muted { display: block; margin-top: .2em; font-size: .78em; }
/* 排程：跟誰一起（搭檔手記的進度），地圖上同地點兩人以上的 🌸 */
.duo-line { margin: .25em 0 0; font-size: .8em; }
.plot .pair { font-size: .9em; pointer-events: none; }

/* 批次 L-c：手機頂欄變矮——標籤用短字（.short），聲音收成一顆 🔊（點開在頂欄最下面多一列，往下推、不蓋東西） */
.topbar .short { display: none; }
.audio-fold > summary { list-style: none; cursor: pointer; display: inline-grid; place-items: center; min-width: 2.6em; min-height: 2.2em; padding: 0 .4em; border-radius: 999px; }
.audio-fold > summary::-webkit-details-marker { display: none; }
.audio-fold[open] { flex-basis: 100%; order: 99; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: .3em .6em; }
.audio-fold .audio-ctl { margin-left: 0; }
@media (max-width: 700px) {
  .topbar .long { display: none; }
  .topbar .short { display: inline; }
  .topbar .audio-fold { margin-left: auto; }
  .topbar .audio-fold ~ .help { margin-left: 0; }
  .topbar { gap: .3em .3em; padding: .4em .45em .45em; }
  .topbar .pill { padding: .1em .5em; display: inline-block; }   /* the short/long spans are separate flex items: wrapped text must flow as one line box */
  .topbar .pill > i { display: inline-grid; vertical-align: middle; }
}
/* Wide screens: the goal result's reward box sits beside her line (the fixed-height dialog then fits it without scrolling). */
@media (min-width: 701px) {
  .stage .say:has(> .goal-reward) { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 24em); column-gap: 1em; align-items: start; }
  .stage .say:has(> .goal-reward) > p { grid-column: 1; }
  .stage .say > .goal-reward { grid-column: 2; grid-row: 1 / span 4; margin: 0; max-width: none; }
}
/* 批次 M2 多人行程：場景裡一起的人（對話框裡一排小臉，說話的人亮起來）；多人企劃的角色列。 */
.dialog .party { display: flex; flex-wrap: wrap; gap: .35em; margin: 0 0 .3em; }
.dialog .pface { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; object-position: 50% 12%; opacity: .55; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(60, 35, 10, .3); }
.dialog .pface.on { opacity: 1; box-shadow: 0 0 0 2px var(--pink-deep, #d44a6c); }
.job.crew .crew-role { margin-top: .55em; }
.job.crew .crew-role > b { font-size: .86em; }
.job.crew .assign { margin-top: .3em; }
.job.crew .crew-note { display: block; margin-top: .5em; font-size: .78em; line-height: 1.5; }
.crew-short { color: #b42318; margin-left: .3em; }
.camp-card { max-width: 1068px; margin: .8em auto 0; padding: .45em 1em; box-sizing: border-box; font-size: .88em; line-height: 1.5; }
.camp-card p { margin: .15em 0; }
@media (max-width: 700px) { .camp-card { margin: .6em .5em 0; font-size: .78em; padding: .35em .6em; } }
.duo.city .narr { font-style: italic; opacity: .85; }
.duo.city .muted { display: block; margin-top: .2em; font-size: .78em; }
/* 城市小機會（批次 K）：排程上方一張小卡，在排版流裡 */
.city-card { max-width: 1068px; margin: .8em auto 0; padding: .45em 1em; box-sizing: border-box; font-size: .88em; line-height: 1.5; }
.city-card p { margin: .15em 0; }
.city-card small { display: block; font-size: .88em; }
@media (max-width: 700px) { .city-card { margin: .6em .5em 0; font-size: .78em; padding: .35em .6em; } }
.city-card .new { display: inline-block; margin-left: .4em; padding: 0 .45em; border-radius: 99px; background: var(--pink-deep); color: #fff; font-size: .75em; vertical-align: middle; }
.city-card.ok small.go { color: var(--good); font-weight: bold; }
.city-card.done { opacity: .8; }
.city-mark { font-style: normal; margin-right: .15em; }
.duo.city .chip { margin-right: .3em; }
/* 標題前的「點一下開始」（批次 K-a） */
.gate .gate-btn { margin-top: 1.5em; min-height: 52px; padding: .6em 2.2em; font-size: 1.15em; animation: gate-pulse 1.8s ease-in-out infinite; }
@keyframes gate-pulse { 50% { transform: scale(1.05); } }
@media (prefers-reduced-motion: reduce) { .gate .gate-btn { animation: none; } }
.concert .stamps { min-height: 2.9em; margin-top: .2em; }   /* Fix O-6: the 🌟 stamp sits under the photo (not on her chin); room for its tilt */
/* Fix O-8: the week summary's 繼續 stays on screen on busy weeks (sticky to the bottom of the scrolling overlay) */
#scene .scene-go { position: sticky; bottom: 0; z-index: 3; margin: .6em -1.4em -1.3em; padding: .6em 0 .8em; background: linear-gradient(transparent, rgba(30, 18, 60, .85) 35%); border-radius: 0 0 18px 18px; }
@media (max-width: 700px) { #scene .scene-go { margin: .5em -.8em -1.1em; } }
.job.crew .crew-legend { display: block; margin-top: .4em; font-size: .74em; opacity: .8; }

/* 本週便條（第三輪 P12）：粉絲應援、合宿、城市小機會、願望、篇章併成一張（沿用 .city-card 的大小）；桌機前三件排成一列，其他收進 details。手機收成一行。 */
.agenda { max-width: 1068px; margin: .8em auto 0; padding: .4em .8em; box-sizing: border-box; font-size: .86em; line-height: 1.35; display: flex; flex-wrap: wrap; align-items: center; gap: .3em .6em; }
.agenda ul { display: flex; flex-wrap: wrap; gap: .4em; margin: 0; padding: 0; list-style: none; min-width: 0; flex: 1 1 0; }
.agenda .ag-title { color: #5b3d22; white-space: nowrap; }
.agenda .ag { flex: 1 1 15em; min-width: 0; }
.agenda .ag-row { display: flex; align-items: center; gap: .45em; width: 100%; min-height: 44px; box-sizing: border-box; padding: .25em .6em .25em .4em; border-radius: 14px; background: rgba(255, 253, 249, .92); border: 2px dashed #f0b3c6; color: inherit; font: inherit; text-align: left; box-shadow: none; margin: 0; }
button.ag-row { cursor: pointer; }
button.ag-row:hover { border-color: var(--pink-deep); transform: none; }
.agenda .ag.ok .ag-row { border-style: solid; border-color: #6fbf9b; background: #eefaf2; }
.agenda .ag.done .ag-row { opacity: .7; border-style: dotted; }
.agenda .ag-t { flex: 1; min-width: 0; }
.agenda .ag-t small { display: block; color: #7a6a5a; font-size: .9em; }
.agenda .ag-ico { font-style: normal; flex: none; }
.agenda .ag-ok { color: var(--good); flex: none; }
.agenda .fan-face { width: 28px; height: 28px; object-fit: contain; flex: none; }
.agenda .ag-more { flex-basis: 100%; }
.agenda .ag-more summary { cursor: pointer; color: #7a6a5a; font-size: .92em; padding: .2em 0; min-height: 24px; }
.agenda .ag-more ul { margin-top: .3em; }
.agenda.fold { display: block; }
.agenda.fold > summary { cursor: pointer; font-weight: bold; color: #5b3d22; min-height: 32px; display: flex; align-items: center; }
.agenda.fold ul { flex-direction: column; margin-top: .3em; }
@media (max-width: 700px) { .agenda { margin: .6em .5em 0; font-size: .78em; padding: .3em .6em; } .agenda .ag { flex-basis: 100%; } }
.topbar .audio-fold { margin-left: auto; }
.topbar .audio-fold ~ .help { margin-left: 0; }
.map-side .agenda { margin: 0 0 .6em; }
.map-side .agenda .ag { flex-basis: 100%; }
.map-side .agenda .ag-title { flex-basis: 100%; }
.setlist-pick .boss-quote { font-size: .9em; color: #8a4a62; margin: .2em 0 .4em; }   /* 第三輪 P14 舞台製作：黑羽的一句 */
/* fix P：📣 宣傳企劃（第 41 週起，本週便條下面） */
.card.promo { max-width: 1068px; margin: .5em auto 0; padding: .35em .8em; box-sizing: border-box; display: flex; flex-wrap: wrap; align-items: center; gap: .3em .8em; font-size: .86em; }
.card.promo button { margin: 0; }
.card.promo .owe { color: #c2410c; font-size: .95em; }   /* fix Q: the month-end bill; stays on short phones */
.map-side .card.promo { margin: 0 0 1.4em; }   /* fix S-8: room for the member card's washi tape (it covered 「付完剩」) */
/* fix S-8: the side panel is narrow — its member card wraps the stickers like a phone (8 in one row were thin vertical strips) */
.map-side .activities { grid-template-columns: repeat(var(--pn, 3), minmax(0, 1fr)); gap: .5em .45em; }
@media (max-width: 700px) { .card.promo { margin: .5em .5em 0; font-size: .8em; } }
.job .mandatory-note { display: block; margin: .2em 0 .3em; font-size: .8em; color: #a0472a; }   /* fix P B1 */
/* fix P：看板最下面的「高門檻案子」 */
.board .far-jobs { margin-top: .6em; }
.board .far-jobs > summary { cursor: pointer; font-size: .85em; color: #5b3d22; background: rgba(255, 253, 249, .92); border-radius: 12px; padding: .3em .7em; min-height: 32px; display: flex; align-items: center; gap: .3em; }
/* fix P：週結算的閒聊、共學、粉絲應援收成一列晶片，點開看台詞 */
.talk-row { display: flex; flex-wrap: wrap; justify-content: center; gap: .4em; margin: .6em 0 .2em; }
.talk-chip { flex: 0 1 auto; max-width: 100%; text-align: left; background: rgba(255, 253, 249, .94); border: 2px solid #f0c9d6; border-radius: 16px; color: #4a3626; }
.talk-chip[open] { flex-basis: 100%; }
.talk-chip > summary { cursor: pointer; list-style: none; padding: .25em .7em; min-height: 32px; display: flex; align-items: center; flex-wrap: wrap; gap: .3em; font-size: .85em; }
.talk-chip > summary::-webkit-details-marker { display: none; }
.talk-chip > summary::after { content: '▾'; opacity: .6; }
.talk-chip[open] > summary::after { content: '▴'; }
.talk-chip .chip { margin: 0; font-size: .9em; }
.talk-chip .new-dot { font-style: normal; font-size: .75em; background: var(--pink-deep, #d6457a); color: #fff; border-radius: 8px; padding: 0 .35em; }
.talk-chip .talk-body { padding: 0 .9em .5em; }
.talk-chip .talk-body p { margin: .15em 0; font-size: .9em; }
.topbar.crowded .logo { display: none; }   /* fix P: race + policy + goal pills: the logo gives its room so the bar stays two rows at 1280 */
/* fix P：360×640 這種矮手機，第一張成員卡要在底部按鈕上面看得到：休息室變矮、人氣榜開打後的 🎁 收進 🎯 的說明、宣傳企劃的小字收起來 */
@media (max-width: 700px) and (max-height: 700px) {
  .office { height: calc(84px + 4em); --base: 8px; --step: 14px; --head: 30px; }
  .walker img.sprite { height: 60px; }
  .walker img.mascot { height: 26px; }
  .topbar .goal-gift[title] { display: none; }
  .card.promo small { display: none; }
  .plan-bar { margin-bottom: 1.1em; }
}
/* Codex 第四輪 Q1：看板最上面的「👥 下週：雙人企劃」預告（一行，點開才是版本和試算） */
.job.crew-preview { border-style: dashed; }
.job.crew-preview > summary { cursor: pointer; font-size: .86em; font-weight: bold; color: #5b3d22; min-height: 32px; display: flex; align-items: center; flex-wrap: wrap; gap: .3em; }
.job.crew-preview .pv-open { margin-left: auto; font-weight: normal; font-size: .9em; color: var(--pink-deep, #d44a6c); }
.job.crew-preview[open] .pv-open { display: none; }
.job.crew-preview p { margin: .4em 0 .2em; font-size: .84em; line-height: 1.5; }
.job.crew-preview small { display: block; margin-top: .35em; font-size: .78em; }
/* Codex 第四輪 Q2：成員卡最下面的「📒 投入履歷」（預設收起） */
.card.member .card-folds { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 0 1.2em; margin-top: .2em; }   /* under the stickers: opening one never moves them */
.card.member .card-folds > details[open] { flex-basis: 100%; }
.card.member .guide, .card.member .compare { font-size: .8em; }
.card.member .compare > summary { cursor: pointer; color: #5b3d22; min-height: 28px; display: flex; align-items: center; }
.card.member .compare small { display: block; margin: .25em 0; line-height: 1.5; }
.card.member .cmp-cols { display: grid; grid-template-columns: 1fr 1fr; gap: .6em; margin: .3em 0; }
.card.member .cmp-col { background: rgba(255, 253, 249, .7); border-radius: 10px; padding: .35em .5em; min-width: 0; }
.card.member .cmp-pick { display: flex; flex-wrap: wrap; gap: .2em; margin: .25em 0; }
.card.member .cmp-pick button { padding: .1em .35em; min-width: 30px; }
.card.member .cmp-pick .on { background: var(--pink-deep, #d44a6c); color: #fff; }
.card.member .cmp-vals { display: flex; flex-direction: column; gap: .05em; margin: .2em 0; }
.card.member .guide > summary, .card.member .guide-rules > summary { cursor: pointer; color: #5b3d22; min-height: 28px; display: flex; align-items: center; }
.card.member .guide small { display: block; margin: .25em 0; line-height: 1.5; }
.card.member .guide .g-practice { display: flex; flex-wrap: wrap; gap: .2em .9em; margin: .2em 0; }
.card.member .guide .g-pins { display: flex; flex-wrap: wrap; gap: .3em; margin: .2em 0 .3em; }
.card.member .guide .g-pins .on { background: var(--pink-deep, #d44a6c); color: #fff; }
.card.member .guide .checks { list-style: none; margin: .2em 0; padding: 0; }
.card.member .guide .checks li { margin: .1em 0; }
.card.member .guide .checks li.ok { color: #2f7a4d; }
.card.member .guide .warn { color: #a0472a; }
.career-why { max-width: 46em; margin: .6em auto 0; text-align: left; font-size: .85em; }
.career-why > summary { cursor: pointer; text-align: center; min-height: 32px; }
.career-why ul { margin: .3em 0; padding-left: 1.2em; line-height: 1.6; }
.career-why small { display: block; }
.sticker .maxed-note { display: block; font-size: .72em; font-weight: normal; opacity: .8; }   /* fix U-5: a lesson for a stat already at 100 */
.sticker.maxed .ico { opacity: .55; }
/* fix U-6：360×640 第 48 週頂欄折成 5 行（約 150px），第一張成員卡的能力被底部按鈕蓋住。窄手機的頂欄再縮：字小一點、人氣榜開打後的「名氣滿」
   不另外佔一格（有人氣榜就表示名氣滿了，名氣沒滿時照樣顯示數字）、攻略只留「？」。 */
@media (max-width: 420px) {
  .topbar { font-size: .72em; gap: .25em .25em; padding: .35em .4em .4em; }
  .topbar .fame-full { display: none; }
  .topbar .help-t { display: none; }
  .topbar .audio-fold > summary { min-width: 2.2em; min-height: 2em; }
}
