/* Dungoku player v25 — supplied 390×844 design; fonts and art stay same-origin. */
@font-face{font-family:Copse;src:url('/assets/fonts/copse-regular.ttf') format('truetype');font-style:normal;font-weight:400;font-display:block}
@font-face{font-family:Gaegu;src:url('/assets/fonts/gaegu-regular.ttf') format('truetype');font-style:normal;font-weight:400;font-display:block}
@font-face{font-family:Gaegu;src:url('/assets/fonts/gaegu-bold.ttf') format('truetype');font-style:normal;font-weight:700;font-display:block}
:root{--story-paper:#f3f3f3;--story-pink:#d83258;--story-ink:#090909}
[hidden]{display:none!important}
.tutorial-home,.play-mode,.player-load-error{background:var(--story-paper);color:var(--story-ink);font-family:Gaegu,cursive;font-weight:400}
.tutorial-landing{max-width:720px;margin:auto;min-height:100svh;padding:42px 0 48px;text-align:center}
.screen-title,.play-mode .topline h1{font-family:Copse,Georgia,serif;font-weight:400;background:#fff;font-size:clamp(24px,9.2vw,36px);line-height:1.25;letter-spacing:-.04em;margin:0;padding:14px 12px;overflow-wrap:anywhere}
.welcome-copy{padding:36px 32px 0;font-size:26px;line-height:1.27}
.welcome-copy h2{font-family:Gaegu,cursive;font-size:32px;font-weight:700;margin:0 0 36px;line-height:1.15;letter-spacing:.01em}
#campaignIntro p{margin:0 0 36px;white-space:pre-line}
.story-button,.play-mode .button.primary.story-button,.play-mode #validateBtn{display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:8px 24px;border:2px solid #090909;border-radius:5px;box-shadow:0 4px 4px #0003;background:var(--story-pink);color:#fff;font:400 26px/1.1 Gaegu,cursive;letter-spacing:.01em;text-decoration:none;text-transform:lowercase;cursor:pointer}
.story-button:hover,.play-mode .story-button:hover,.play-mode #validateBtn:hover{background:#bc2448;color:#fff;border-color:#090909}
.story-button:disabled{opacity:.55;cursor:not-allowed}
.story-button:focus-visible,.play-mode button:focus-visible,.play-mode a:focus-visible{outline:3px solid #2257c0;outline-offset:4px}
#publicStatus{font-size:20px;margin:20px 0}
#publicStatus:empty{display:none}
.play-mode .app{position:relative;max-width:720px;padding:42px 0 0;min-height:100svh;margin:auto}
.play-mode .mode-bar{font-family:system-ui,sans-serif;margin:0 16px 16px}
.hosted-player .mode-bar,.hosted-player .mode-description{display:none!important}
.hosted-player-loading .app{visibility:hidden}
.hosted-player-loading:before{content:'Preparing your adventure…';display:block;text-align:center;padding:40px 24px;font:26px Gaegu,cursive}
.play-mode .topline{display:block;margin:0;text-align:center}
.play-mode .topline>div{width:100%}
.play-mode .topline .eyebrow,.play-mode .topline .header-actions,.play-mode .topline .subhead{display:none}
.play-mode .campaign-progress{display:none!important}
.play-mode .story-screen{display:flex;flex-direction:column;align-items:center;position:relative;border:0;border-radius:0;box-shadow:none;background:var(--story-paper);isolation:isolate;margin:0;max-width:none;padding:26px 30px 0;min-height:calc(100svh - 109px);overflow:hidden;text-align:center}
.play-mode .story-screen .eyebrow,.play-mode .story-screen #playerLevelTitle,.play-mode .player-objective{display:none}
.play-mode .story-lead{font:700 30px/1.2 Gaegu,cursive;margin:0 0 36px;letter-spacing:.01em}
.play-mode .player-opening,.play-mode .story-copy{font:400 26px/1.28 Gaegu,cursive;white-space:pre-wrap;margin:0 0 28px;max-width:570px}
.play-mode #beginLevel{align-self:flex-end;z-index:1;margin:24px 0 0;min-width:103px}
.play-mode .story-portrait{display:block;width:calc(100% + 138px);max-width:560px;height:auto;object-fit:contain;align-self:center;margin:-96px -69px -1px;pointer-events:none;user-select:none}
.play-mode .story-portrait.hero-portrait{width:65%;margin:32px 0;max-width:280px}
.play-mode.play-started #playerIntro{display:none!important}
.play-mode:not(.play-started) .workspace{display:none!important}
.play-mode .workspace{display:block;padding:0;margin:0}
.play-mode .workspace>aside,.play-mode .board-top,.play-mode .board-foot,.play-mode .range-status,.play-mode .play-tray-copy,.play-mode .col-labels,.play-mode .row-labels,.play-mode .board-scroll-hint{display:none!important}
.play-mode .layout-panel{border:0;border-radius:0;background:var(--story-paper);padding:0;max-width:none;overflow:visible}
.play-mode.play-started .topline:after{content:attr(data-objective);display:block;max-width:600px;margin:20px auto 0;padding:0 28px;font:400 18px/1.35 Gaegu,cursive;white-space:pre-wrap}
.play-mode .board-controls{position:relative;display:flex;justify-content:center;align-items:center;gap:12px;min-height:100px;margin:0;padding:28px 16px 30px;border:0;background:none}
.play-mode .board-controls>#rangeToggle,.play-mode .board-controls>#effectsToggle,.play-mode .board-controls>#labelToggle{flex:0 0 44px;width:44px;height:44px;padding:0;min-height:44px;border:2px solid #090909;border-radius:5px;background-color:#fff;box-shadow:0 2px 4px #0005;color:transparent;font-size:0;background-position:center;background-size:32px;background-repeat:no-repeat}
.play-mode #rangeToggle{background-image:url('/assets/ui/monster-range.png')}
.play-mode #effectsToggle{background-image:url('/assets/ui/effects-range.png')}
.play-mode #labelToggle{background-image:url('/assets/ui/terrain-labels.png')}
.play-mode .board-controls>button[aria-pressed=true]{background-color:#ffe481;border-color:#918879;box-shadow:none}
.play-mode .hint-open,.play-mode .hint-close{position:absolute;right:18px;bottom:-12px;z-index:6;min-height:44px;padding:5px 12px;font-size:18px}
.play-mode .board-wrap{padding:24px 20px 0;margin:0;overflow:auto;background:#514035 url('/assets/ui/wood-table.png') center top / cover no-repeat;border-top:2px solid #090909}
.play-mode .board-grid-shell{display:block;gap:0;grid-template-columns:none;margin:auto}
.play-mode .board-grid-shell>div:first-child{display:none}
.play-mode .board-artwork-stage{outline:2px solid #090909;outline-offset:0;box-shadow:0 4px 5px #0005}
.play-mode .board-grid-shell:not(.has-puzzle-art) .board-artwork-stage{background:#a69b91;outline-offset:8px;margin:8px}
.play-mode .play-hero-tray{background:#514035 url('/assets/ui/wood-table.png') center 65% / cover no-repeat;border:0;border-radius:0;margin:0;padding:12px 16px 4px;min-height:90px}
.play-mode .play-token-row{justify-content:center;gap:12px;min-height:76px;padding:4px 4px 8px;flex-wrap:wrap;overflow:visible}
.play-mode .play-token-button,.play-mode .play-token-button .token.character-art{width:var(--play-token-size,96px);height:var(--play-token-size,96px)}
.play-mode .empty-play-tray{font:400 18px/1.2 Gaegu,cursive;color:#fff;min-height:64px;display:flex;align-items:center;text-align:center}
.play-mode .player-submit-row{display:flex;justify-content:center;padding:14px 20px 36px;background:#514035 url('/assets/ui/wood-table.png') center bottom / cover no-repeat}
.play-mode #validateBtn{min-width:180px}
.play-mode .validation-result.fail{margin:0;padding:20px 24px;background:#fff0ee;border-width:2px 0 0;border-radius:0;font:400 20px/1.3 Gaegu,cursive;color:#762127}
.play-mode .validation-title{font:700 28px/1.2 Gaegu,cursive}
.play-mode .validation-list{font-size:20px;line-height:1.3}
.play-mode .validation-note{font:400 18px/1.3 Gaegu,cursive}
.play-mode .validation-result.pass,.play-mode .status,.play-mode .campaign-victory-actions{display:none!important}
.play-mode .victory-screen{min-height:calc(100svh - 42px);padding-top:20px}
.play-mode .victory-heading{font:700 48px/1.2 Gaegu,cursive;margin:0 0 32px}
.play-mode .victory-screen .story-copy{margin:0 0 32px}
.play-mode .story-actions{display:flex;justify-content:center;gap:12px;margin:0 0 66px;z-index:1}
.play-mode.play-victory .topline,.play-mode.play-victory .workspace{display:none!important}
.play-mode .hint-panel{position:absolute;top:0;left:0;right:0;height:276px;max-height:46svh;z-index:20;background:var(--story-paper);border-bottom:2px solid #090909;display:grid;grid-template-columns:44% 56%;padding:18px 16px 20px;overflow:visible;isolation:isolate;animation:hint-slide .18s ease-out}
.play-mode .hint-portrait{position:absolute;bottom:0;left:-36px;width:85%;max-height:none;object-fit:contain;object-position:left bottom;z-index:-1;pointer-events:none}
.play-mode .hint-portrait.hero-portrait{width:40%;left:0;bottom:20px}
.play-mode .hint-bubble{grid-column:2;min-height:0;background:#fffd;border:2px solid #090909;border-radius:32px;padding:16px 14px 4px;display:flex;flex-direction:column;align-items:stretch;overflow:auto}
.play-mode .hint-text{font:400 18px/1.15 Gaegu,cursive;text-align:center;white-space:pre-wrap;margin:0;flex:1}
.play-mode .hint-navigation{display:flex;align-items:center;justify-content:space-between;gap:4px;flex-shrink:0;font:400 16px Gaegu,cursive}
.play-mode .hint-nav-button{border:0;background:none;color:#090909;min-width:44px;min-height:44px;font:24px Gaegu,cursive;border-radius:4px}
.play-mode .hint-nav-button:disabled{opacity:.3;cursor:default}
.play-mode .hint-close{bottom:-12px}
.narrative-authoring{border-top:1px solid #e4e6e3;margin-top:20px;padding-top:12px}
.narrative-authoring h3{margin:0 0 8px;font-size:17px}
.narrative-authoring .level-fields{padding-top:12px}
.player-load-error .app{max-width:600px;padding:60px 24px;text-align:center;font:26px Gaegu,cursive}
@keyframes hint-slide{from{transform:translateY(-100%)}to{transform:translateY(0)}}
@media(min-width:700px){.tutorial-landing{padding-top:56px}.welcome-copy{max-width:570px;margin:auto;padding-top:40px}.play-mode .app{max-width:720px}.play-mode .story-screen{min-height:0}.play-mode .story-portrait:not(.hero-portrait){--dm-desktop-size:clamp(680px,calc(100vw - 20px),820px);width:var(--dm-desktop-size);max-width:none;margin-top:calc(var(--dm-desktop-size) * -.2282352941 + 16px)}.play-mode .story-screen{overflow:visible}.play-mode .story-portrait:not(.hero-portrait){transform:translateX(clamp(-32px,calc((700px - 100vw)*.064),0px))}.play-mode .story-actions{margin-bottom:32px}.play-mode .hint-panel{height:300px;grid-template-columns:48% 52%;padding-right:32px}.play-mode .hint-text{font-size:22px}.play-mode .hint-portrait{width:55%;max-height:100%;left:0}.play-mode .board-wrap{padding:28px 32px 0}.play-mode .board-controls{min-height:114px}}
@media(max-width:360px){.welcome-copy{padding-inline:24px;font-size:24px}.welcome-copy h2{font-size:30px}.play-mode .story-screen{padding-inline:24px}.play-mode .player-opening,.play-mode .story-copy{font-size:24px}.play-mode .story-portrait{width:calc(100% + 48px);margin-inline:-24px}.play-mode .story-lead{font-size:27px}.play-mode .board-wrap{padding-inline:16px}.play-mode .hint-panel{grid-template-columns:36% 64%;padding-inline:12px}.play-mode .hint-bubble{padding:12px 10px 0}.play-mode .hint-text{font-size:17px}}
@media(prefers-reduced-motion:reduce){.play-mode .hint-panel{animation:none}.play-mode *{scroll-behavior:auto!important;transition:none!important}}

/* Cloud artwork spans the narrative canvas and stays deliberately faint. */
.play-mode .story-screen:before{content:'';position:absolute;inset:-109px 0 0;background:url('/assets/ui/cloud-bg.png') center top / 100% auto no-repeat;opacity:.13;z-index:-1;pointer-events:none}
/* Crop only the transparent upper part through CSS; the supplied PNG is unchanged.
   One continuous wood surface avoids seams between board, tray and submit. */
.play-mode .player-board-surface{background:#514035 url('/assets/ui/wood-table.png') center bottom / auto 159.28% repeat-x;border-top:2px solid #090909}
.play-mode .board-wrap,.play-mode .play-hero-tray,.play-mode .player-submit-row{background:none;border:0}
.play-mode .board-grid-shell{padding:8px;border:2px solid #090909;border-style:solid;background:#bda16e;box-shadow:inset 2px 2px #d4bb8d,inset -2px -2px #675435,0 3px 4px #0005}
.play-mode .board-grid-shell:not(.has-puzzle-art) .board-artwork-stage{margin:0;outline-offset:0}
.play-mode .board-controls>#rangeToggle{background-image:url('/assets/ui/monster-range.png')}
.play-mode .board-controls>#rangeToggle[aria-pressed=true],.play-mode .board-controls>#effectsToggle[aria-pressed=true],.play-mode .board-controls>#labelToggle[aria-pressed=true]{background-color:#ffe481;border-color:#918879;box-shadow:none}
.play-mode .board-controls>#effectsToggle{background-image:url('/assets/ui/effects-range.png')}
.play-mode .board-controls>#labelToggle{background-image:url('/assets/ui/terrain-labels.png')}
.play-mode #campaignSaveWarning{margin:0;padding:12px 20px;color:#fff;background:#762127;font-size:18px;text-align:center}
.play-mode .status{display:block!important;position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
@media(max-width:360px){.play-mode .story-portrait{width:calc(100% + 122px);margin-inline:-61px}}

/* The objective is real text, not generated pseudo-content. */
.play-mode.play-started .topline:after{display:none}
.play-mode.play-started .topline .subhead{display:block;max-width:600px;margin:20px auto 0;padding:0 28px;color:var(--story-ink);font:400 18px/1.35 Gaegu,cursive;white-space:pre-wrap}
.play-mode .story-portrait,.play-mode .hint-portrait{flex-shrink:0}

.play-mode #boardScrollHint:not([hidden]){display:block!important;margin:0;padding:12px 20px 0;color:#fff!important;font:400 18px/1.2 Gaegu,cursive;text-align:center}
/* Shared button styling must not reveal player-only controls in the editor. */
.story-button.play-only{display:none}
.play-mode .story-button.play-only{display:inline-flex}
.play-mode #boardScrollHint:not([hidden]){font-size:18px!important}
/* v25.1 — one token scale for board, tray and pointer ghost, including stats. */
.play-mode{--play-token-size:calc(var(--play-cell,72px) - 4px)}
.play-mode .play-hero-tray,.play-mode .drag-ghost{--cell:var(--play-cell,72px)}
.play-mode .play-token-button{width:var(--play-token-size);height:var(--play-token-size);min-width:44px;min-height:44px}
.play-mode .play-token-button .token.character-art,.play-mode .drag-ghost .token.character-art{width:var(--play-token-size);height:var(--play-token-size)}
.play-mode .play-token-row{min-height:calc(var(--play-token-size) + 16px)}
.play-mode .drag-ghost{padding:0;border:0;border-radius:0;background:transparent;box-shadow:none}
/* Measure only text, offscreen; neither duplicate IDs nor interactive controls. */
.narrative-measure{position:absolute;left:-10000px;top:0;visibility:hidden;pointer-events:none}
.play-mode .narrative-measure .story-screen{padding-bottom:0}
.play-mode .story-screen>.story-actions{align-self:center;justify-content:center;gap:0;margin:var(--story-action-gap,24px) 0 0;transform:translateY(-49px);z-index:1}
.play-mode #beginLevel{align-self:auto;margin:0}
.play-mode #beginLevel,.play-mode #campaignNext{width:128px;min-width:128px;padding-inline:10px}

.play-mode #publicLevelLoadStatus{font:400 20px/1.25 Gaegu,cursive;margin:16px 0 100px;max-width:570px;position:relative;z-index:2}
.play-mode #publicLevelLoadStatus a{color:inherit;text-decoration:underline;text-underline-offset:3px;display:inline-block;min-height:44px;padding-block:10px}

/* Portrait starts below the centered action or any loading/retry copy. */
@media(min-width:700px){.play-mode #publicLevelLoadStatus{margin-bottom:16px}}

/* v25.6.0: reveal initial story copy only after its exact faces have loaded. */
html:not(.story-fonts-ready) .tutorial-home .tutorial-landing,html:not(.story-fonts-ready) .hosted-player-loading::before,html:not(.story-fonts-ready) .play-mode .topline,html:not(.story-fonts-ready) .play-mode .story-screen{visibility:hidden}
/* 24px extra breathing room above the shared Begin / Go forth baseline. */
.play-mode .story-screen>.story-actions{transform:translateY(-25px)}
/* Each story portrait is 80% of its previous responsive dimensions. */
.play-mode .story-portrait{width:calc(80% + 110.4px);max-width:448px;margin:-76.8px -55.2px -1px}
.play-mode .story-portrait.hero-portrait{width:52%;max-width:224px;margin:25.6px 0}
@media(max-width:360px){.play-mode .story-portrait:not(.hero-portrait){width:calc(80% + 97.6px);margin-inline:-48.8px}}
@media(min-width:700px){.play-mode .story-portrait:not(.hero-portrait){--dm-desktop-size:clamp(544px,calc(80vw - 16px),656px);width:var(--dm-desktop-size);max-width:none;margin-top:calc(var(--dm-desktop-size) * -.2282352941 + 16px);transform:translateX(clamp(-25.6px,calc((700px - 100vw)*.0512),0px))}}
.play-mode.play-started .topline .subhead{font-size:20px}
/* The same button stays outside the animated panel: only its label changes. */
.play-mode .hint-open{z-index:30;min-width:72px}
.play-mode .hint-bubble{position:relative;padding:52px 14px;overflow:hidden}
.play-mode .hint-text{display:flex;align-items:safe center;justify-content:center;min-height:0;overflow:auto;overflow-wrap:anywhere;text-align:center;flex:1}
.play-mode .hint-navigation{position:absolute;left:14px;right:14px;bottom:4px}

/* The same 80% reduction also applies to speakers inside the hint panel. */
.play-mode .hint-portrait{width:68%;left:-28.8px}
.play-mode .hint-portrait.hero-portrait{width:32%;left:0;bottom:16px}
@media(min-width:700px){.play-mode .hint-portrait:not(.hero-portrait){width:44%;max-height:80%;left:0}}

/* v25.7: full-size character portraits, reversible hint drawer and optional nudge. */
.play-mode .hint-panel{animation:none}
.play-mode .hint-portrait,.play-mode .hint-portrait.hero-portrait{width:44%;height:calc(100% - 16px);max-height:none;left:0;bottom:0;object-fit:contain;object-position:center bottom}
@media(min-width:700px){.play-mode .hint-portrait,.play-mode .hint-portrait.hero-portrait{width:48%;max-height:none;left:0}}
.play-mode .story-portrait.hero-portrait{width:calc(80% + 110.4px);max-width:448px;margin:16px -55.2px -1px;transform:none}
@media(max-width:360px){.play-mode .story-portrait.hero-portrait{width:calc(80% + 97.6px);margin-inline:-48.8px}}
@media(min-width:700px){.play-mode .story-portrait.hero-portrait{width:clamp(544px,calc(80vw - 16px),656px);max-width:none;margin:16px 0 -1px}}
.play-mode .victory-heading{font-size:64px;color:var(--story-pink)}
@media(min-width:700px){.play-mode .victory-heading{font-size:72px}}
@keyframes important-hint-pulse{0%,100%{box-shadow:0 2px 4px #0004,0 0 0 0 #d8325800}50%{box-shadow:0 2px 4px #0004,0 0 0 7px #d8325833}}
.play-mode .hint-open.important-hint{animation:important-hint-pulse 2.6s ease-in-out infinite}
@media(prefers-reduced-motion:reduce){.play-mode .hint-open.important-hint{animation:none;box-shadow:0 0 0 3px #d8325866}}
/* DM's source has a large transparent top margin; size its visible artwork,
   not that empty canvas. The opaque bubble keeps all copy unobstructed. */
.play-mode .hint-portrait:not(.hero-portrait){width:66%;height:auto;max-height:none;left:-20px;bottom:0;object-position:left bottom}
.play-mode .hint-bubble{background:#fff}
@media(min-width:700px){.play-mode .hint-portrait:not(.hero-portrait){width:52%;left:0}}

/* v25.8.1: no stale/incorrect portrait while its chosen source is resolving. */
.play-mode .story-portrait,.play-mode .hint-portrait{visibility:hidden}

/* v25.9: the sliding drawer meets the wood edge at every responsive size.
   Its fixed control remains in the normal board-controls layer above it. */
.play-mode .hint-panel{max-height:none;overflow:hidden}

/* v25.9.1: a held counter must not move/scale under its recorded grab point. */
.play-mode .play-token-button:hover,.play-mode .cell:active{transform:none}

/* Persistent music control: reserve a top band so hints never cover it. */
body.has-theme-control{padding-top:calc(60px + env(safe-area-inset-top,0px))}
.music-toggle{position:fixed;z-index:11000;top:calc(8px + env(safe-area-inset-top,0px));right:calc(12px + env(safe-area-inset-right,0px));width:44px;height:44px;padding:9px;display:grid;place-items:center;color:#fff;background:#d83258;border:2px solid #090909;border-radius:5px;box-shadow:0 2px 3px #0003;cursor:pointer;touch-action:manipulation}
.music-toggle svg{width:24px;height:24px;pointer-events:none}
.music-toggle:hover{background:#bc2448}
.music-toggle:focus-visible{outline:3px solid #2459c8;outline-offset:3px}
