/* THE GUILD HALL — page styles. Fonts are the site's own, self-hosted. */
@font-face{font-family:'Inter';font-style:normal;font-weight:100 900;font-display:swap;src:url('../assets/fonts/inter-400-500-latin.woff2') format('woff2')}
@font-face{font-family:'Jacquard 24';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/jacquard-24-latin-400.woff2') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400 500;font-display:swap;src:url('../assets/fonts/jetbrains-mono-400-latin.woff2') format('woff2')}
/* Layout: one 16:9 stage, contained in the window, black around it. The Figma frames are the scenes; tap areas sit on top in % of the 2560×1440 canvas. */
:root{--key:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='24' viewBox='0 0 32 16' shape-rendering='crispEdges'%3E%3Cg fill='%23F2F0EA'%3E%3Crect x='2' y='4' width='8' height='8'/%3E%3Crect x='10' y='7' width='18' height='3'/%3E%3Crect x='20' y='10' width='3' height='4'/%3E%3Crect x='25' y='10' width='3' height='3'/%3E%3C/g%3E%3Crect x='5' y='7' width='2' height='2' fill='%230B0B0A'/%3E%3C/svg%3E") 6 12;
  --night:#0B0B0A; --stone:#1D1C1B; --keyline:#3A3733; --hint:#6A6762;
  --orange:#FF3D00; --orange-text:#FF7A45; --hint-text:#9A968F; --paper:#F2F0EA; --spell:#7CFF4F;
  --mono:"JetBrains Mono",ui-monospace,Menlo,monospace;
  --body:"Inter",system-ui,-apple-system,sans-serif;
  color-scheme:dark;
}
html,body{height:100%}
body{background:var(--night);color:var(--paper);font-family:var(--body);overflow:hidden;
  padding-left:max(0px,env(safe-area-inset-left,0px));padding-right:max(0px,env(safe-area-inset-right,0px))}
#wrap{position:fixed;inset:0;display:grid;place-items:center}
#stage{position:relative;width:min(var(--fw,100vw),calc(var(--fh,100vh) * 16 / 9));aspect-ratio:16/9;overflow:hidden;background:var(--night);
  container-type:inline-size;cursor:default;user-select:none;-webkit-user-select:none}
/* the shop is all pixel sprites: keep the steps crisp when you pull something close (5 Nov) */
#stage[data-view="shop"] .layer{image-rendering:pixelated}
/* walked up to the incense or the old hall: the room's image goes mono (blended onto grey) */
#scene.mono{background-color:#808080;background-blend-mode:luminosity}
.layer{position:absolute;inset:0;background-size:100% 100%;background-repeat:no-repeat;will-change:transform,opacity,filter}
#scene{transition:filter .3s ease}
#scene.stepback{filter:brightness(.75) blur(var(--sb,5px)) grayscale(1)}
#tapped{opacity:0;pointer-events:none;transition:opacity .3s ease}
#tapped.on{opacity:1;pointer-events:auto;cursor:pointer}
#ghost{opacity:0;pointer-events:none}
.hot{position:absolute;background:transparent;border:0;padding:0;margin:0;cursor:pointer;border-radius:2px;outline:none}
.hot:focus-visible{box-shadow:0 0 0 2px var(--orange)}
body.show-hot .hot{box-shadow:inset 0 0 0 1px var(--spell);background:rgba(124,255,79,.08)}
body.show-hot .hot.walk{box-shadow:inset 0 0 0 1px var(--orange);background:rgba(255,61,0,.08)}
.hint{position:absolute;font:500 max(9px,.82cqw)/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--hint);
  background:none;border:0;cursor:pointer;padding:.6cqw .4cqw;white-space:nowrap;transition:color .2s}
.hint:hover,.hint:focus-visible{color:var(--paper);outline:none}
#nudge{position:absolute;left:50%;bottom:calc(3.6cqw + 6.6cqw + 3.2cqw);transform:translate(-50%,8px);font:400 max(11px,1.1cqw)/1.3 var(--body);color:var(--paper);
  opacity:0;transition:opacity .6s ease,transform .6s ease;pointer-events:none;white-space:nowrap}
#nudge.on{opacity:.9;transform:translate(-50%,0)}
#daylight{position:absolute;inset:0;background:var(--paper);opacity:0;pointer-events:none;transition:opacity .5s ease;
  display:grid;place-items:center;color:#121211}
#daylight.on{opacity:1;pointer-events:auto}
#daylight .card{display:grid;gap:1.4cqw;justify-items:center;text-align:center;opacity:0;transition:opacity .4s ease .5s}
#daylight.on .card{opacity:1}
#daylight .eyebrow{font:500 max(9px,.82cqw)/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:#6A6762}
#daylight .line{font:400 max(14px,1.8cqw)/1.3 var(--body);max-width:34ch}
#daylight button{font:500 max(10px,.9cqw)/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--orange);
  background:none;border:1px solid var(--orange);padding:1cqw 1.6cqw;cursor:pointer}
#daylight button:focus-visible{outline:2px solid var(--orange);outline-offset:3px}
#pad{position:absolute;left:50%;bottom:3.6cqw;width:6.6cqw;min-width:76px;transform:translateX(-50%);transition:opacity .3s}
#pad.off{opacity:0;pointer-events:none}
#pad svg{display:block;width:100%;height:auto;shape-rendering:crispEdges;overflow:visible}
#pad .arm{cursor:pointer;outline:none}
#pad .arm rect.body{fill:var(--stone)}
#pad .arm .ar{fill:var(--hint);transition:fill .15s}
#pad .arm:hover rect.body,#pad .arm:focus-visible rect.body{fill:#26241F}
#pad .arm.hov .ar,#pad .arm:hover .ar,#pad .arm:focus-visible .ar,#pad .arm.press .ar{fill:var(--orange)}
#pad .arm.press{transform:translateY(.35px)}
#pad .arm.dead{pointer-events:none}
#pad .arm.dead .ar{fill:var(--keyline);opacity:.5}
#pad .rim{fill:none;stroke:var(--keyline);stroke-width:.22}
#pad .you{fill:var(--paper)}
#pad .lab{position:absolute;font:500 max(10px,.68cqw)/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--hint-text);white-space:nowrap;pointer-events:auto;cursor:pointer;padding:.4em .3em;margin:-.4em -.3em;transition:color .15s;text-shadow:0 0 3px #0B0B0A,0 0 8px #0B0B0A,0 0 14px #0B0B0A}
#pad .lab.lit{color:var(--paper)}
#pad .lab[data-d=up]{left:50%;bottom:calc(100% + .7cqw);transform:translateX(-50%);padding-left:calc(.3em + .12em)}
#pad .lab[data-d=down]{left:50%;top:calc(100% + .7cqw);transform:translateX(-50%);padding-left:calc(.3em + .12em)}
#pad .lab[data-d=left]{right:calc(100% + .9cqw);top:50%;transform:translateY(-50%);margin-top:0;margin-bottom:0}  /* no vertical pull, so the words sit on the arrow's centre line */
#pad .lab[data-d=right]{left:calc(100% + .9cqw);top:50%;transform:translateY(-50%);margin-top:0;margin-bottom:0}
#toast{position:absolute;left:50%;top:4%;transform:translateX(-50%);font:500 max(9px,.78cqw)/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;
  color:var(--paper);background:rgba(11,11,10,.9);border-top:1px solid var(--orange);padding:.9cqw 1.4cqw;opacity:0;transition:opacity .3s;pointer-events:none;white-space:nowrap}
#toast.on{opacity:1}
#help{position:fixed;left:50%;transform:translateX(-50%);top:max(10px,env(safe-area-inset-top,0px));transition:opacity 1s;font:400 11px/1.5 var(--mono);letter-spacing:.06em;color:#B4B0A6;
  background:none;border:0;cursor:pointer;padding:4px 0;opacity:1}
#help.gone{opacity:0}
#help:hover,#help:focus-visible{opacity:1;color:var(--paper);outline:none}
#wxCredit{position:fixed;right:max(8px,env(safe-area-inset-right,0px));bottom:max(6px,env(safe-area-inset-bottom,0px));z-index:10;margin:0;
  font:400 8px/1.35 var(--mono);letter-spacing:.02em;color:var(--hint);opacity:.52;white-space:nowrap}
#wxCredit a{color:inherit;text-underline-offset:.2em}
#wxCredit a:hover,#wxCredit a:focus-visible{color:var(--paper);opacity:1;outline:none}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@media (prefers-reduced-motion:reduce){#scene,#tapped,#nudge,#daylight,#daylight .card{transition-duration:.15s!important}}
#doorPane{position:absolute;width:12%;background:rgba(52,18,6,.92);border-top:1px solid var(--orange);padding:1.2cqw 1.2cqw 1cqw;display:grid;gap:.8cqw;
  opacity:0;transform:translateY(10px);transition:opacity .3s ease .15s,transform .3s ease .15s;pointer-events:none}
#doorPane.on{opacity:1;transform:none;pointer-events:auto}
#doorPane .nm{font:500 max(11px,.72cqw)/1.3 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--orange-text)}
#doorPane .ln{font:400 max(12px,1.2cqw)/1.3 var(--body);color:var(--paper)}
#doorPane button{justify-self:start;font:500 max(11px,.72cqw)/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--orange-text);background:none;border:1px solid var(--orange);padding:.8cqw 1.1cqw;cursor:pointer}
#doorPane button.no{color:var(--hint);border-color:var(--keyline);cursor:default}
#doorPane button:focus-visible{outline:2px solid var(--orange);outline-offset:3px}
#doorPane .hn:empty{display:none}
#doorPane .hn{font:400 max(10px,.55cqw)/1.35 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--hint-text)}
#portrait{position:absolute;left:26.93%;top:25%;width:13.7%;height:29.17%;background-size:100% 100%;opacity:0;transition:opacity .35s ease;pointer-events:none}
#portrait.on{opacity:1}
#scene .vx{position:absolute;inset:0;background-size:100% 100%;pointer-events:none;transition:opacity .25s}
/* the hover: floats rise and settle, each on its own beat (timings set per voxel in hall.js) */
#scene .vx.bob{animation:bob var(--bd,2.6s) ease-in-out var(--bdl,0s) infinite alternate}
@keyframes bob{from{translate:0 calc(var(--ba,.2cqw) * -1)}to{translate:0 var(--ba,.2cqw)}}
/* the air: smoke in the wizard's light, mist on the floor, steam off the pot. Texture is drawn by the browser (no image files) */
#stage{--smoke:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='320'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.0047 .0125' numOctaves='4' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .84 0 0 0 0 .68 0 0 0 2.4 -1.15'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");--mistx:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='800' height='200'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.0025 .02' numOctaves='3' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .86 0 0 0 0 .82 0 0 0 0 .78 0 0 0 2 -.8'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");--smoke-a:.24;--mist-a:.09;--steam-a:.3}
#scene .air{position:absolute;inset:0;pointer-events:none;overflow:hidden}
#scene .air .drift{position:absolute;top:0;left:0;width:200%;height:100%;background-repeat:repeat;will-change:transform;animation:drift 90s linear infinite}
#scene .air .drift.two{animation-duration:140s;animation-direction:reverse;background-position:0 50%;opacity:.7}
@keyframes drift{to{transform:translateX(-50%)}}
#scene .air .shaft{position:absolute;inset:0;mix-blend-mode:screen;opacity:var(--smoke-a);
  --cone:conic-gradient(from calc(180deg - var(--ang)) at var(--ax) var(--ay),transparent 0deg,#000 calc(var(--ang) * .7),#000 calc(var(--ang) * 1.3),transparent calc(var(--ang) * 2));
  --fade:linear-gradient(to bottom,transparent var(--f0),#000 var(--f1),#000 var(--f2),transparent var(--f3));
  -webkit-mask:var(--cone),var(--fade);-webkit-mask-composite:source-in;mask:var(--cone),var(--fade);mask-composite:intersect}
#scene .air .shaft .drift{background-image:var(--smoke);background-size:25% 100%}
#scene .air .mist{position:absolute;left:0;right:0;bottom:0;opacity:var(--mist-a);transform-origin:50% 100%;
  -webkit-mask:linear-gradient(to bottom,transparent 0,#000 45%,#000 70%,transparent 100%);mask:linear-gradient(to bottom,transparent 0,#000 45%,#000 70%,transparent 100%)}
#scene .air .mist .drift{background-image:var(--mistx);background-size:25% 100%;animation-duration:120s}
#scene .air .mist .drift.two{animation-duration:200s}
/* the steam: a thin plume of the same smoke, rising off the pot and opening out as it goes */
#scene .air .steam{position:absolute;--k:1;width:calc(4.2cqw * var(--k));height:calc(10cqw * var(--k));transform:translate(-50%,-100%);overflow:hidden;
  mix-blend-mode:screen;opacity:var(--steam-a);
  -webkit-mask:radial-gradient(ellipse 28% 60% at 50% 92%,#000 0,rgba(0,0,0,.45) 45%,transparent 100%);mask:radial-gradient(ellipse 28% 60% at 50% 92%,#000 0,rgba(0,0,0,.45) 45%,transparent 100%)}
#scene .air .steam .rise{position:absolute;left:0;top:0;width:100%;height:200%;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='480'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.055 .011' numOctaves='4' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .86 0 0 0 0 .74 0 0 0 3.4 -1.75'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");background-size:100% 25%;background-repeat:repeat;
  will-change:transform;animation:rise 18s linear infinite}
#scene .air .steam .rise.two{animation-duration:28s;background-position:50% 30%;opacity:.7}
@keyframes rise{to{transform:translateY(-50%)}}
@media (prefers-reduced-motion:reduce){#scene .air .drift{animation:none}#scene .air .steam{display:none}}
/* the wizard window: the real weather over Gothenburg, seen through his glass, always lit as dusk (see WIN in hall.js).
   Everything is masked to the panes, so nothing lands on the leading or the wall. Backlit glass shows weather as shadow. */
#scene .win{position:absolute;pointer-events:none;overflow:hidden;--amt:.65;--slant:0deg;--tile:3.2cqw;--cloud-t:70s;
  --rain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cg stroke='%231a0600' stroke-width='1.1' stroke-linecap='round'%3E%3Cline x1='54.6' y1='93.4' x2='54.6' y2='112.3' stroke-opacity='0.71'/%3E%3Cline x1='60.9' y1='18.6' x2='60.9' y2='38.0' stroke-opacity='0.73'/%3E%3Cline x1='74.8' y1='9.2' x2='74.8' y2='31.8' stroke-opacity='0.62'/%3E%3Cline x1='13.3' y1='67.3' x2='13.3' y2='90.2' stroke-opacity='0.47'/%3E%3Cline x1='115.0' y1='61.8' x2='115.0' y2='87.3' stroke-opacity='0.79'/%3E%3Cline x1='21.0' y1='58.0' x2='21.0' y2='68.2' stroke-opacity='0.48'/%3E%3Cline x1='24.7' y1='3.2' x2='24.7' y2='17.1' stroke-opacity='0.71'/%3E%3Cline x1='53.2' y1='50.1' x2='53.2' y2='73.6' stroke-opacity='0.80'/%3E%3Cline x1='60.0' y1='45.5' x2='60.0' y2='66.1' stroke-opacity='0.60'/%3E%3Cline x1='116.7' y1='79.0' x2='116.7' y2='105.0' stroke-opacity='0.84'/%3E%3Cline x1='38.9' y1='30.7' x2='38.9' y2='44.4' stroke-opacity='0.49'/%3E%3Cline x1='90.4' y1='87.7' x2='90.4' y2='104.1' stroke-opacity='0.66'/%3E%3Cline x1='112.2' y1='0.1' x2='112.2' y2='23.6' stroke-opacity='0.57'/%3E%3Cline x1='106.8' y1='100.5' x2='106.8' y2='118.0' stroke-opacity='0.67'/%3E%3Cline x1='11.3' y1='77.8' x2='11.3' y2='97.9' stroke-opacity='0.60'/%3E%3Cline x1='12.9' y1='100.9' x2='12.9' y2='116.2' stroke-opacity='0.87'/%3E%3C/g%3E%3C/svg%3E");
  --snow:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cg fill='%231a0600'%3E%3Ccircle cx='30.8' cy='14.1' r='1.5' fill-opacity='0.53'/%3E%3Ccircle cx='23.7' cy='66.7' r='2.7' fill-opacity='0.72'/%3E%3Ccircle cx='86.6' cy='17.7' r='1.6' fill-opacity='0.82'/%3E%3Ccircle cx='50.9' cy='27.0' r='1.5' fill-opacity='0.63'/%3E%3Ccircle cx='94.0' cy='38.0' r='3.0' fill-opacity='0.94'/%3E%3Ccircle cx='47.9' cy='100.6' r='1.7' fill-opacity='0.82'/%3E%3Ccircle cx='116.3' cy='27.0' r='1.5' fill-opacity='0.63'/%3E%3Ccircle cx='40.7' cy='37.0' r='2.6' fill-opacity='0.54'/%3E%3Ccircle cx='69.5' cy='30.4' r='1.5' fill-opacity='0.80'/%3E%3Ccircle cx='54.7' cy='112.4' r='1.9' fill-opacity='0.74'/%3E%3Ccircle cx='101.6' cy='24.0' r='2.3' fill-opacity='0.58'/%3E%3Ccircle cx='95.7' cy='31.9' r='2.8' fill-opacity='0.59'/%3E%3C/g%3E%3C/svg%3E");
  -webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
#scene .win>*{position:absolute;inset:0;display:none}
#scene .win .tilt{inset:-25%;transform:rotate(var(--slant))}
#scene .win .fall{position:absolute;left:0;right:0;top:calc(var(--tile) * -2);bottom:0;background-size:var(--tile) var(--tile);will-change:transform;animation:fall 1.5s linear infinite}
#scene .win .fall.two{--tile:4.4cqw;animation-duration:1.1s;background-position:1.3cqw 0}
@keyframes fall{to{transform:translateY(calc(var(--tile) * 2))}}
/* clear: the low sun behind him, a slow warm swell */
#scene .win[data-wx=clear] .sky{display:block;mix-blend-mode:screen;background:radial-gradient(ellipse 70% 60% at 62% 28%,rgba(255,196,120,.55),transparent 70%);
  opacity:calc(.25 + .3 * var(--amt));animation:swell 9s ease-in-out infinite alternate}
@keyframes swell{from{opacity:calc(.15 + .2 * var(--amt))}}
/* cloud: shadows sliding across the glass, quicker in a wind */
#scene .win[data-wx=cloud] .sky,#scene .win[data-wx=rain] .sky,#scene .win[data-wx=thunder] .sky,#scene .win[data-wx=snow] .sky{display:block;right:auto;width:200%;
  background-image:var(--smoke);background-size:50% 100%;filter:brightness(0);opacity:calc(.12 + .3 * var(--amt));will-change:transform;animation:drift var(--cloud-t) linear infinite}
/* fog: the glass goes soft and milky */
#scene .win[data-wx=fog] .sky{display:block;background:rgba(150,138,128,calc(.2 + .25 * var(--amt)));-webkit-backdrop-filter:blur(.12cqw) saturate(.7);backdrop-filter:blur(.12cqw) saturate(.7)}
/* rain and snow: falling shadows; thunder is rain with the odd flash */
#scene .win[data-wx=rain] .tilt,#scene .win[data-wx=thunder] .tilt,#scene .win[data-wx=snow] .tilt{display:block}
#scene .win[data-wx=rain] .fall,#scene .win[data-wx=thunder] .fall{background-image:var(--rain);opacity:calc(.18 + .3 * var(--amt))}
#scene .win[data-wx=snow] .fall{background-image:var(--snow);opacity:calc(.2 + .3 * var(--amt));animation-duration:9s}
#scene .win[data-wx=snow] .fall.two{animation-duration:6.5s}
#scene .win .flash{background:#fff4e0;mix-blend-mode:screen;opacity:0}
#scene .win[data-wx=thunder] .flash{display:block}
#scene .win .flash.bang{animation:bang .7s linear}
@keyframes bang{0%{opacity:0}6%{opacity:.75}14%{opacity:.1}24%{opacity:.55}100%{opacity:0}}
@media (prefers-reduced-motion:reduce){#scene .win *{animation:none!important}#scene .win .flash{display:none}}

/* the tell: frame A at rest; frame B for one beat when hall.js adds .tell */
#scene .vx.blink{background-image:none!important}
#scene .vx.blink::before,#scene .vx.blink::after{content:'';position:absolute;inset:0;background-size:inherit;background-position:inherit;background-repeat:no-repeat}
#scene .vx.blink::before{background-image:var(--va)}
#scene .vx.blink::after{background-image:var(--vb);visibility:hidden}
#scene .vx.blink.tell::before{visibility:hidden}
#scene .vx.blink.tell::after{visibility:visible}
@media (prefers-reduced-motion:reduce){#scene .vx.bob{animation:none}}
#shell{position:absolute;inset:0;background-size:100% 100%;opacity:0;pointer-events:none;transition:opacity .4s ease .15s;
  filter:sepia(1) saturate(8) hue-rotate(-62deg) brightness(.55)}  /* the empty shell: a cooled ember, not a white line */
#shell.on{opacity:.4}
.spark{position:absolute;width:.45cqw;height:.45cqw;background:var(--spell);pointer-events:none}
#veil{position:absolute;inset:0;background:var(--night);opacity:0;pointer-events:none;transition:opacity .45s ease}
#veil.on{opacity:1}
#veil.paper{background:var(--paper)}
.beat #stage{cursor:default}
body.keycur #stage .hot{cursor:pointer}
/* in the lobby the nudge is written on the door itself, conjured letter by letter */
body.keycur #nudge{left:41.9%;top:66.5%;bottom:auto;width:19%;text-align:center;font:400 max(9px,.78cqw)/1.35 var(--mono);letter-spacing:.18em;text-transform:uppercase;color:rgba(242,240,234,.62);transform:translate(-50%,0);transition:none;opacity:0;padding-left:.18em;box-sizing:border-box}
body.keycur #nudge.on{opacity:1}
#nudge span{display:inline-block;white-space:pre;opacity:0;animation:conjL .55s cubic-bezier(.2,.7,.2,1) forwards}
@keyframes conjL{0%{opacity:0;filter:blur(5px);transform:translateY(3px)}100%{opacity:1;filter:blur(0);transform:none}}
@media (prefers-reduced-motion:reduce){#nudge span{animation:none;opacity:1}}
body.keycur #stage{cursor:default}
body.keycur #stage .hot.door{cursor:var(--key),pointer}
body.keydoor #stage,body.keydoor #stage .hot,body.keydoor #doorPane button{cursor:var(--key),pointer}
.hot.door{cursor:var(--key),pointer}

/* LIVE PANE — the words for every tapped thing, drawn as text from copy.js. Sizes are the Figma pane's, in canvas px ÷ 25.6 (cqw). */
#livePane{position:absolute;box-sizing:border-box;background:rgba(52,18,6,.92);border-top:1px solid var(--orange);padding:1.21cqw 1.21cqw 1.1cqw;
  display:flex;flex-direction:column;gap:.78cqw;opacity:0;transform:translateY(12px);transition:opacity .3s ease .12s,transform .3s ease .12s;pointer-events:none;cursor:default;z-index:6}
#livePane.on{opacity:1;transform:none;pointer-events:auto}
/* PANE TYPE, three styles only (3 Nov): LABEL = mono caps, one size; BODY = Inter Light; SMALL = Inter Light, a step down */
#livePane .eb{margin:0;font:500 max(11px,.86cqw)/1.3 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--orange-text);white-space:pre-line;padding-right:2.4cqw}
#livePane .st{display:none;margin-top:.15cqw;font:400 max(10px,.78cqw)/1.3 var(--mono);letter-spacing:.08em;text-transform:none;color:rgba(242,240,234,.75)}
#livePane .bd{margin:0;font:300 max(14px,1.33cqw)/1.3 var(--body);color:var(--paper);white-space:pre-line;text-wrap:pretty}
#livePane .sm{margin:0;font:300 max(12px,1cqw)/1.45 var(--body);color:rgba(242,240,234,.85);white-space:pre-line}
/* "Still brewing": a quiet label, not a button. One slow bubble in the pot. */
#livePane .ss{margin:.2cqw 0 0;display:flex;align-items:center;gap:.6cqw;font:500 max(11px,.86cqw)/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--hint-text)}
#livePane .ss[hidden]{display:none}
#livePane .ss::before{content:'';width:.45cqw;height:.45cqw;min-width:5px;min-height:5px;border-radius:50%;background:var(--orange);opacity:.5;animation:brew 2.8s ease-in-out infinite}
@keyframes brew{0%,100%{opacity:.25;transform:scale(.8)}50%{opacity:.8;transform:scale(1)}}
@media (prefers-reduced-motion:reduce){#livePane .ss::before{animation:none}}
#livePane .nm{position:absolute;top:1.21cqw;right:1.21cqw;font:500 max(11px,.86cqw)/1.3 var(--mono);letter-spacing:.1em;color:var(--hint-text)}
#livePane button{align-self:flex-start;font:500 max(11px,.86cqw)/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--orange-text);background:none;border:1px solid var(--orange);padding:.78cqw 1.1cqw;cursor:pointer;margin-top:.2cqw}
#livePane button:hover{background:rgba(255,61,0,.12)}
#livePane button:focus-visible{outline:2px solid var(--orange);outline-offset:3px}
#livePane .mh{display:none}
/* the cauldron's pane is a menu card: paper, ink, a keyline inset like a printed border, the dish in the tapestries' blackletter */
#livePane.menu{--ink:#1C1612;--ink2:rgba(28,22,18,.72);--rust:#A6300B;background:#EEE8DA;color:var(--ink);border-top:0;text-align:center;align-items:stretch;
  padding:2.4cqw 2.2cqw 2.2cqw;gap:.9cqw;aspect-ratio:210/297;outline:1px solid rgba(28,22,18,.4);outline-offset:-.55cqw;box-shadow:0 .8cqw 2.4cqw rgba(0,0,0,.55)}
#livePane.menu .mh{display:flex;align-items:center;gap:.9cqw;margin:0;font:500 max(10px,.74cqw)/1 var(--mono);letter-spacing:.32em;text-transform:uppercase;color:var(--ink2);padding-left:.32em}
#livePane.menu .mh::before,#livePane.menu .mh::after{content:'';flex:1;border-top:1px solid rgba(28,22,18,.4)}
#livePane.menu .eb{padding:0;color:var(--rust);margin-top:.3cqw}
#livePane.menu .bd{display:flex;align-items:baseline;justify-content:center;gap:.6cqw;text-align:left;color:var(--ink);font:400 max(22px,2.15cqw)/1 'Jacquard 24',serif}
#livePane.menu .dn{font:400 max(22px,2.15cqw)/1 'Jacquard 24',serif;white-space:nowrap}
#livePane.menu .ld{flex:1;min-width:1.5cqw;border-bottom:2px dotted rgba(28,22,18,.45);transform:translateY(-.35cqw)}
#livePane.menu .pr{font:500 max(10px,.74cqw)/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--rust);white-space:nowrap}
#livePane.menu .sm{color:var(--ink2);border-top:1px solid rgba(28,22,18,.25);padding-top:1.4cqw;margin:.6cqw 0 auto;line-height:1.7;font-size:max(12px,.95cqw);text-wrap:balance}
#livePane.menu button{align-self:center;color:var(--ink);border-color:var(--ink);margin-top:.3cqw}
#livePane.menu button:hover{background:rgba(166,48,11,.1)}
#livePane.menu button:focus-visible{outline-color:var(--rust)}
#livePane .hn{display:none;margin:0;font:400 max(10px,.7cqw)/1.35 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--hint-text)}

/* VASTNESS — the vault and the floor run on into the dark, so the hall has no edges.
   Two fades, drawn live over every view (not the front-of-house beats), into the same black as the letterbox.
   --vt / --vb: how far down the top fade and up the bottom fade reach. Press V to tune them live. */
#stage{--vt:33%;--vb:38%;--vd:1}  /* Simon's tuning, 30 Oct */
#vast{position:absolute;inset:0;pointer-events:none;opacity:var(--vd);transition:opacity .6s ease}
#vast::before,#vast::after{content:"";position:absolute;left:0;right:0}
#vast::before{top:0;height:var(--vt);background:linear-gradient(to bottom,#0B0B0A 0%,rgba(11,11,10,.92) 18%,rgba(11,11,10,.55) 52%,rgba(11,11,10,0) 100%);
  /* the mini-map is a fixture: leave a window for it */
  -webkit-mask:linear-gradient(#000,#000),linear-gradient(#000,#000);-webkit-mask-size:100% 100%,10.6cqw 9.7cqw;-webkit-mask-position:0 0,87.66cqw 1.72cqw;-webkit-mask-repeat:no-repeat;-webkit-mask-composite:xor;
  mask:linear-gradient(#000,#000),linear-gradient(#000,#000);mask-size:100% 100%,10.6cqw 9.7cqw;mask-position:0 0,87.66cqw 1.72cqw;mask-repeat:no-repeat;mask-composite:exclude}
#vast::after{bottom:0;height:var(--vb);background:linear-gradient(to top,#0B0B0A 0%,rgba(11,11,10,.9) 16%,rgba(11,11,10,.5) 50%,rgba(11,11,10,0) 100%)}
.outside #vast{opacity:0}
#vrig{position:fixed;left:16px;top:16px;z-index:50;display:none;gap:9px;flex-direction:column;background:rgba(11,11,10,.94);border:1px solid var(--keyline);padding:14px;font:400 11px/1 var(--mono);max-height:calc(100vh - 32px);overflow:auto;color:var(--paper);letter-spacing:.08em;text-transform:uppercase}
#vrig.on{display:flex}#vrig i{font-style:normal;color:var(--orange-text)}#vrig code{display:block;font:inherit;text-transform:none;color:var(--paper);background:#1D1C1B;padding:.5em .6em;user-select:all}#vrig button{font:inherit;letter-spacing:inherit;text-transform:inherit;color:var(--orange-text);background:none;border:1px solid var(--orange);padding:.5em .7em;cursor:pointer;justify-self:start;align-self:flex-start}#vrig .vsec{display:flex;flex-direction:column;gap:9px;border-top:1px solid var(--keyline);padding-top:10px}#vrig .vbtns{display:flex;gap:6px;flex-wrap:wrap}#vrig .vbtns button.on{background:var(--orange);color:#0B0B0A}#vpane{display:none;flex-direction:column;gap:.6em;border-top:1px solid var(--keyline);padding-top:.8em}#vrig.on.paneopen #vpane{display:flex}.tuning #livePane.on{outline:1px dashed var(--orange-text);cursor:move}#vrig label{display:grid;grid-template-columns:7em 12em 3em;align-items:center;gap:.6em}#vrig input{accent-color:#FF3D00}

/* EMBER LIGHT — the wizard's warm glow, drawn live. Origin moves with the view (from the right on the houses, the left on the masters…).
   Strength, reach, warmth and flicker are tuned in the instrument (V). */
#ember{position:absolute;inset:0;pointer-events:none;mix-blend-mode:screen;
  background:radial-gradient(ellipse var(--gr,55%) calc(var(--gr,55%) * 1.15) at var(--gx,50%) var(--gy,30%),rgba(var(--gc,255,92,20),var(--ga,.22)) 0%,rgba(var(--gc,255,92,20),calc(var(--ga,.22) * .45)) 40%,rgba(var(--gc,255,92,20),0) 100%);
  transition:opacity .6s ease}
.outside #ember{opacity:0!important}
/* PHONE FRAME — preview the hall at real iPhone size (Safari's bars taken off) */
body.phone #wrap{inset:auto;left:50%;top:50%;transform:translate(-50%,-50%);width:var(--fw);height:var(--fh);display:block;
  outline:14px solid #1A1918;outline-offset:0;border-radius:4px;box-shadow:0 0 0 15px #3A3733,0 30px 80px rgba(0,0,0,.8)}
body.phone #stage{margin:0 auto}
body.phone.port #stage{margin-top:12%}
body.phone #wrap::after{content:attr(data-dev);position:absolute;left:0;right:0;top:calc(100% + 26px);text-align:center;font:400 11px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--hint-text)}

/* ARRIVAL has no mini-map, so no window in the vault fade there */
#stage[data-view=arrival] #vast::before{-webkit-mask:none;mask:none}
/* PHONES ─ portrait: the wizard asks you to turn round. Landscape: compact controls. (body classes set in JS, so the instrument's preview shows the same) */
#turn{position:absolute;inset:0;z-index:40;display:none;place-items:center;align-content:center;gap:22px;background:var(--night);text-align:center;padding:24px}
body.askturn #turn{display:grid}
#turn .wz{display:grid;grid-template-columns:repeat(16,7px);grid-auto-rows:7px;margin:0 auto;animation:tip 2.4s cubic-bezier(.5,0,.2,1) infinite}
#turn .wz i{background:transparent}#turn .wz i.on{background:var(--orange)}#turn .wz i.sp{background:var(--spell)}
@keyframes tip{0%,30%{transform:rotate(0)}55%,80%{transform:rotate(90deg)}100%{transform:rotate(0)}}
@media (prefers-reduced-motion:reduce){#turn .wz{animation:none;transform:rotate(90deg)}}
#turn h2{margin:0;font:400 24px/1.2 var(--body);color:var(--paper)}
#turn p{margin:0;font:400 11px/1.5 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--hint-text)}
#turn button{justify-self:center;margin-top:6px;font:500 11px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--orange-text);background:none;border:1px solid var(--orange);padding:12px 16px;cursor:pointer}
body.compact #pad{left:auto;right:12px;bottom:10px;transform:none;width:58px;min-width:0}
body.compact #pad .lab{opacity:0;pointer-events:none;transition:opacity .15s}body.compact #pad .lab.lit{opacity:1}
body.compact #pad .lab[data-d=left],body.compact #pad .lab[data-d=right]{display:none}
body.compact #livePane{min-width:min(270px,48%);max-height:94%;overflow:auto;padding:12px}
body.compact #livePane .bd{font-size:14px}
body.compact #doorPane{min-width:min(220px,40%)}
body.compact #help,body.coarse #help{display:none}
body.compact #nudge{bottom:12px;left:40%}

/* THE CONJURING — the wizard draws the door: both jambs rise out of the dark, meet at the apex, the inner line follows, light floods in */
#conjure{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:5;overflow:visible}
#conjure path{fill:none;stroke-linecap:square;stroke-linejoin:miter}  /* stepped door: square corners, no rounding */
#conjure .ol{stroke:#FF3D00;stroke-width:8;filter:drop-shadow(0 0 6px rgba(255,61,0,.55))}  /* the lancet portal: crisp lines, a little light while it's drawn */
#conjure .il{stroke:#FF3D00;stroke-width:4}
#conjure .o2{stroke-width:6;opacity:.7}#conjure .o3{opacity:.48}#conjure .o4{opacity:.32}
#conjure .fill{fill:rgba(255,61,0,.05);stroke:none;opacity:0}  /* fades in once the point closes */
#wizfly{position:absolute;height:auto;aspect-ratio:1/1;pointer-events:none;z-index:6;filter:drop-shadow(0 0 .5cqw rgba(255,61,0,.55))}
#conjure .head{fill:#7CFF4F;filter:drop-shadow(0 0 4px #7CFF4F)}
#pad .lab:empty{pointer-events:none}
body.lobby:not(.compact) #pad{left:41.9%;bottom:2.4cqw}

/* THE KEYHOLE — the key cursor's target. Glows when the key is over the door; on entry the key slides in and turns */
#keyhole{position:absolute;left:46.64%;top:71.67%;width:.78cqw;transform:translateX(-50%);display:none;pointer-events:none;z-index:4}
body.lobby #keyhole{display:block}
#keyhole svg{display:block;width:100%;height:auto;shape-rendering:crispEdges;fill:#8A2400;transition:fill .25s,filter .25s}
body.keyhot #keyhole svg{fill:#FF3D00;filter:drop-shadow(0 0 .25cqw #FF3D00) drop-shadow(0 0 .7cqw rgba(255,61,0,.6))}
#keyin{position:absolute;width:3cqw;pointer-events:none;z-index:5}
#keyin svg{display:block;width:100%;height:auto;shape-rendering:crispEdges}

/* facing the doors, the wizard window's glow pours in from the side it's on and soaks across the wall and floor */
#stage[data-view=houses] #ember,#stage[data-view=masters] #ember{mix-blend-mode:screen;
  background:linear-gradient(var(--gdir),rgba(var(--gc,255,92,20),calc(var(--ga,.22) * 1.9)) 0%,rgba(var(--gc,255,92,20),calc(var(--ga,.22) * 1.1)) 22%,rgba(var(--gc,255,92,20),calc(var(--ga,.22) * .45)) 48%,rgba(var(--gc,255,92,20),0) calc(var(--gr,60%) + 22%)),
    radial-gradient(ellipse 70% 30% at var(--gx) 100%,rgba(var(--gc,255,92,20),calc(var(--ga,.22) * 1.2)) 0%,rgba(var(--gc,255,92,20),0) 70%)}
#stage[data-view=houses]{--gdir:to left}
#stage[data-view=masters]{--gdir:to right}

#ember{-webkit-mask:linear-gradient(#000,#000),linear-gradient(#000,#000);-webkit-mask-size:100% 100%,10.6cqw 9.7cqw;-webkit-mask-position:0 0,87.66cqw 1.72cqw;-webkit-mask-repeat:no-repeat;-webkit-mask-composite:xor;
  mask:linear-gradient(#000,#000),linear-gradient(#000,#000);mask-size:100% 100%,10.6cqw 9.7cqw;mask-position:0 0,87.66cqw 1.72cqw;mask-repeat:no-repeat;mask-composite:exclude}
#stage[data-view=arrival] #ember{-webkit-mask:none;mask:none}

/* THE PLAN — tap the mini-map: it unfolds from its corner; tap a room to go there */
#mapBtn{position:absolute;left:87.8cqw;top:1.9cqw;width:10.3cqw;height:9.4cqw;z-index:7;background:none;border:0;padding:0;cursor:zoom-in;display:none}
#mapBtn:focus-visible{outline:2px solid var(--orange);outline-offset:3px}
body.hasmap #mapBtn{display:block}
#plan{position:absolute;inset:0;z-index:30;display:grid;place-items:center;background:rgba(11,11,10,.88);opacity:0;pointer-events:none;transition:opacity .3s ease}
#plan.on{opacity:1;pointer-events:auto}
#plan .sheet{position:absolute;left:50%;top:47%;height:86%;aspect-ratio:1060/1010;transform-origin:96% 4%;transform:translate(-50%,-50%) translate(40cqw,-18cqw) scale(.12);transition:transform .45s cubic-bezier(.2,.8,.2,1);border:1px solid var(--keyline);background:#0B0B0A}
#plan.on .sheet{transform:translate(-50%,-50%)}
#plan img{display:block;width:100%;height:100%}
#plan .rm{position:absolute;background:transparent;border:1px solid transparent;cursor:pointer;padding:0}
#plan .rm:hover,#plan .rm:focus-visible{border-color:var(--orange);background:rgba(255,61,0,.12);outline:none}
#plan .you{position:absolute;width:1.3%;aspect-ratio:1;background:#F2F0EA;transform:translate(-50%,-50%);box-shadow:0 0 0 .3cqw rgba(242,240,234,.25);animation:youblink 1.1s steps(2) infinite;pointer-events:none}
@keyframes youblink{50%{opacity:.25}}
#plan .cap{position:absolute;left:0;right:0;top:calc(100% + .8cqw);text-align:center;font:400 max(10px,.7cqw)/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--hint-text)}
body.compact #plan .sheet{height:88%}

/* PORTRAIT, UPRIGHT (prototype, 5 Nov) — the room fills the height and you swipe to look round. Panes rise from the bottom as a sheet; the pad sits in the corner of the glass. */
body.pan #wrap{display:block;place-items:normal;justify-items:start;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;scrollbar-width:none;-webkit-overflow-scrolling:touch}
body.pan #wrap::-webkit-scrollbar{display:none}
body.pan #stage{width:calc(var(--pfh,100dvh) * 16 / 9);margin:0!important}
body.pan #pad{position:fixed;left:auto;right:14px;bottom:calc(14px + env(safe-area-inset-bottom,0px));transform:none;width:64px;min-width:0}
body.pan #livePane{position:fixed;left:12px!important;right:12px;top:auto!important;bottom:calc(12px + env(safe-area-inset-bottom,0px));width:auto!important;min-width:0;max-height:46%;overflow:auto;padding:16px 16px 14px;gap:10px;transform:translateY(24px)}
body.pan #livePane.on{transform:none}
body.pan #toast{position:fixed;top:calc(16px + env(safe-area-inset-top,0px))}
body.pan #nudge{position:fixed;left:50%;bottom:calc(100px + env(safe-area-inset-bottom,0px))}
/* thumbs are bigger than cursors: every tap area is at least 44px, without touching the art */
body.pan .hot::after{content:'';position:absolute;left:50%;top:50%;width:max(100%,44px);height:max(100%,44px);transform:translate(-50%,-50%)}
