/* v2 world UI, built on theme.css (Pocket Reserve tokens) */
body.world{height:100vh;height:100dvh;overflow:hidden;position:fixed;inset:0;width:100%;touch-action:none;user-select:none;-webkit-user-select:none}
#stage{position:absolute;inset:0;background:#0a0f15}
#cv{width:100%;height:100%;display:block;outline:none;position:relative;z-index:0}#cv:focus-visible{outline:2px solid var(--gold-hi);outline-offset:2px}
#lqgl{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:1;visibility:hidden}
#hud{position:absolute;inset:0;pointer-events:none;z-index:3}
#hud .panel{pointer-events:auto;margin:0;padding:8px 10px;border-radius:10px;box-shadow:inset 0 0 0 1px #070b10c7,inset 0 0 0 2px #d7b56a4d,0 0 0 1px var(--brass-mid),0 6px 16px #0008}
#hud .panel:before{opacity:.28}
#lt{position:absolute;left:max(8px,env(safe-area-inset-left));top:8px;display:flex;flex-direction:column;gap:6px;max-width:min(440px,62vw)}#party{display:flex;gap:10px;align-items:center}
#party img.hp{width:60px;height:60px;border-radius:50%;border:2px solid var(--brass);box-shadow:0 0 0 1px var(--brass-ink),inset 0 0 0 1px #f3e2b055;flex:none;animation:idlebreath 3.6s ease-in-out infinite}
#party .pi{min-width:0;flex:1}
#party .nm{font:700 18px/1 var(--display);letter-spacing:.06em;color:var(--gold-hi)}
#party .rk{font-size:12px;color:var(--ink-dim)}
#party .bar{height:8px;margin:4px 0}
#party .st{font-size:12px;color:var(--ink-dim);display:flex;gap:10px;flex-wrap:wrap}
#party .st .flame{color:var(--gold);display:inline-flex;align-items:center;gap:3px}
#party .st .flame svg{display:block}
#party .st .flame svg{transform-origin:50% 80%;animation:flame 1.2s ease-in-out infinite}
#pm{display:flex;gap:4px;margin-top:5px;flex-wrap:wrap}#pm .pm{display:block;line-height:0;border-radius:50%;box-shadow:0 0 0 2px var(--ring,#8a6528)}
#pc{display:flex;gap:4px;margin-top:4px}#pc img{width:26px;height:26px;border-radius:6px;border:1px solid var(--gold);background:#0e141c;animation:idlebreath 3.4s ease-in-out infinite}#pc img:nth-child(2){animation-delay:.35s}#pc img:nth-child(3){animation-delay:.7s}#pc img:nth-child(4){animation-delay:1.05s}#pc img.just{animation:arrive .35s ease both,idlebreath 3.4s ease-in-out infinite}
#pm img{width:24px;height:24px;border-radius:50%;border:1px solid var(--brass-mid);filter:grayscale(1) brightness(.55);opacity:.7;transition:filter .25s,opacity .25s,border-color .25s}
#pm img.on{filter:none;opacity:1;border-color:var(--gold)}#pm img.fresh{animation:pop .3s ease}
#quest{width:min(300px,100%);cursor:pointer}
#quest .kicker{font-size:12px;margin:0 0 3px}#quest div{font-size:13px;line-height:1.3;color:var(--ink)}
#tr{position:absolute;right:max(8px,env(safe-area-inset-right));top:8px;display:flex;flex-direction:column;gap:6px;align-items:flex-end}
#mm{width:150px;height:110px;border:1px solid var(--brass);border-radius:10px;background:#0a0f15;box-shadow:0 0 0 1px var(--brass-ink),0 6px 16px #0008;pointer-events:auto;cursor:pointer}
#tr .row{display:flex;gap:6px;flex-wrap:nowrap}#tr .row>*{flex:0 0 auto}
.ib{pointer-events:auto;min-width:48px;min-height:48px;padding:0 10px;font:800 15px var(--font);color:#f4ead8;background:var(--panel);border:1px solid var(--brass-mid);border-radius:10px;cursor:pointer;box-shadow:inset 0 1px #f3e2b01f;transition:border-color .14s,transform .14s,background .14s}
.ib:hover,.ib:focus-visible{border-color:var(--gold-hi)}.ib:active{transform:translateY(1px)}#bsnd.tap .ico{transform-origin:50% 60%;animation:optpop .2s ease}
#area{position:absolute;left:50%;top:14px;transform:translateX(-50%) translateY(-8px);text-align:center;opacity:0;transition:opacity .6s ease,transform .6s ease;pointer-events:none;padding:8px 26px;background:linear-gradient(90deg,transparent,#0a0f15e6 18%,#0a0f15e6 82%,transparent);border-top:1px solid #d7b56a99;border-bottom:1px solid #d7b56a99}
#area.on{opacity:1;transform:translateX(-50%) translateY(0)}#area .kicker{margin:0;font-size:12px}#area b{font:700 24px/1.1 var(--display);color:var(--gold-hi);letter-spacing:.05em}
#pad{position:absolute;left:max(10px,env(safe-area-inset-left));bottom:max(12px,env(safe-area-inset-bottom));display:none;grid-template-columns:repeat(2,58px);gap:6px;pointer-events:auto}
#acts{position:absolute;right:max(10px,env(safe-area-inset-right));bottom:max(14px,env(safe-area-inset-bottom));display:none;gap:10px;pointer-events:auto;flex-direction:column;align-items:flex-end}
#pad button{width:58px;height:58px;font-size:22px;padding:0;opacity:.88}#pad button.hold,#bact.hold{transform:translateY(1px) scale(.96);border-color:var(--gold-hi)}#bact.ready{animation:qping 1.6s ease-out infinite}
#acts .ib{width:76px;height:76px;border-radius:50%;font-size:24px;background:linear-gradient(180deg,#ecd28a,#c9a24f 52%,#b08a38);color:#1a1208;border-color:var(--brass-lo)}
@media (pointer:coarse),(max-width:760px){#pad,#acts{display:grid}#acts{display:flex}}
body.nopad #pad,body.nopad #acts{display:none!important}
/* phone HUD (r2): a clean top stack. Left column = party + objective, right column = mini-map + a 2x2 grid of 48px buttons.
   --lq-hud-b (set by guide.js from the real panel sizes) is the bottom edge of that stack; the region banner sits just under it,
   above the hero (who stays near the middle of the screen), and the guide caption sits above the move pad, so nothing covers the hero or another panel. */
@media (max-width:560px){#lt{top:max(8px,env(safe-area-inset-top));max-width:none;width:calc(100vw - 128px - env(safe-area-inset-left) - env(safe-area-inset-right))}
#tr{top:max(8px,env(safe-area-inset-top));width:102px}
#party{gap:8px}#party img.hp{width:42px;height:42px}#pm img{width:17px;height:17px}#pc img{width:22px;height:22px}
#mm{width:102px;height:76px}#tr .row{display:grid;grid-template-columns:48px 48px;gap:6px;width:102px}
#tr .ib{width:48px;height:48px;min-width:48px;min-height:48px;padding:0}
#party .nm{font-size:16px}#party .rk{font-size:12px}#party .st{font-size:13px;gap:8px}
#quest{width:100%;box-sizing:border-box;min-height:48px}#quest div{font-size:14px}
#area{top:calc(var(--lq-hud-b,206px) + 6px);bottom:auto;width:max-content;max-width:calc(100vw - 24px);box-sizing:border-box;padding:6px 18px}#area .kicker{font-size:12px}#area b{font-size:19px;line-height:1.15}}
#ov{position:fixed;inset:0;z-index:20;overflow:auto;background:#060a0ee6;touch-action:pan-y;user-select:text;-webkit-user-select:text}#ov:not([hidden]){animation:ovfade .18s ease}#ov .rise{animation:pop .22s ease backwards}#ov:not([hidden]) .ovbar .btn{animation:pop .22s ease backwards}
#ov[hidden],#dlg[hidden]{display:none}
.ovbar{position:sticky;top:0;z-index:2;display:flex;justify-content:flex-end;padding:8px 12px;background:linear-gradient(#060a0e,#060a0e00)}
#ovbody .wrap{padding-top:4px}
#dlg{position:fixed;left:50%;bottom:max(12px,env(safe-area-inset-bottom));transform:translateX(-50%);width:min(760px,96vw);z-index:15}
#dlg .panel{display:flex;gap:14px;align-items:flex-start;margin:0;min-height:112px;padding:14px 16px;cursor:pointer}#dlg:not([hidden]) .panel{animation:dlgin .22s ease}
#dlg img{width:84px;height:84px;border-radius:12px;border:2px solid var(--brass);flex:none;box-shadow:0 0 0 1px var(--brass-ink);animation:idlebreath 3.2s ease-in-out infinite}
#dlg img.spot-art{object-fit:cover;background:#0a0f15;border-color:var(--course,var(--brass));box-shadow:0 0 0 1px var(--brass-ink),0 0 14px color-mix(in srgb,var(--course-warm,#d7b56a) 50%,transparent),0 8px 12px #0007}
#dlg img.spot-lit{box-shadow:0 0 0 1px var(--course-warm,#d7b56a),0 0 22px #f3e2b0bb,0 8px 12px #0007}
#dlg img.spot-spent{filter:saturate(.7) brightness(.78)}
#dlg .tx{flex:1;min-width:0}
#dlg .nameplate{display:inline-block;margin:0 0 4px;padding:1px 12px 2px;font:700 18px/1.2 var(--display);letter-spacing:.08em;color:#1a1208;background:linear-gradient(180deg,#ecd28a,#c9a24f 52%,#b08a38);border:1px solid var(--brass-lo);border-radius:6px}
#dlg .ti{font-size:12px;color:var(--ink-dim);margin-left:8px}
#dlg .body{font-size:17px;line-height:1.45;min-height:50px;color:var(--ink)}
#dlg .more{float:right;color:var(--gold);animation:bob 1s infinite;display:inline-flex}#dlg .more .mk{transform:rotate(90deg)}
@keyframes bob{50%{transform:translateY(3px)}}
#dlg .ch{display:flex;flex-direction:column;gap:6px;margin-top:8px}#dlg .ch .opt{margin:0;min-height:44px;animation:pop .22s ease backwards}
#ttl{position:fixed;inset:0;z-index:25;display:none;align-items:center;justify-content:center;padding:14px;background:radial-gradient(ellipse at center,#0a0f15cc,#060a0ef2),var(--world-bg,none) center/160px repeat,#0a0f15;overflow:auto;touch-action:pan-y pinch-zoom}
/* course colour grade on the title wash and the region banner. Same pairs as each world's map palette. Layout is unchanged. */
body[data-world="python-basics"]{--course:#2f6ab0;--course-warm:#d0a020}
body[data-world="ai-foundations"]{--course:#6a4ab0;--course-warm:#2a8ab0}
body[data-world="ai-evals"]{--course:#2a8a7a;--course-warm:#c98a2a}
body[data-world="ai-safety"]{--course:#2f8a6a;--course-warm:#c9902a}
body[data-world="portfolio-guide"]{--course:#2f6a4a;--course-warm:#b08a2a}
body[data-world="python-basics"] #ttl{background:radial-gradient(ellipse at 16% 0,rgba(47,106,176,.46),transparent 50%),radial-gradient(ellipse at 92% 100%,rgba(208,160,32,.18),transparent 42%),radial-gradient(ellipse at center,#0a0f15cc,#060a0ef2),var(--world-bg,none) center/160px repeat,#0a0f15}
body[data-world="ai-foundations"] #ttl{background:radial-gradient(ellipse at 16% 0,rgba(106,74,176,.46),transparent 50%),radial-gradient(ellipse at 92% 100%,rgba(42,138,176,.2),transparent 42%),radial-gradient(ellipse at center,#0a0f15cc,#060a0ef2),var(--world-bg,none) center/160px repeat,#0a0f15}
body[data-world="ai-evals"] #ttl{background:radial-gradient(ellipse at 16% 0,rgba(42,138,122,.44),transparent 50%),radial-gradient(ellipse at 92% 100%,rgba(201,138,42,.18),transparent 42%),radial-gradient(ellipse at center,#0a0f15cc,#060a0ef2),var(--world-bg,none) center/160px repeat,#0a0f15}
body[data-world="ai-safety"] #ttl{background:radial-gradient(ellipse at 16% 0,rgba(47,138,106,.44),transparent 50%),radial-gradient(ellipse at 92% 100%,rgba(201,144,42,.18),transparent 42%),radial-gradient(ellipse at center,#0a0f15cc,#060a0ef2),var(--world-bg,none) center/160px repeat,#0a0f15}
body[data-world="portfolio-guide"] #ttl{background:radial-gradient(ellipse at 16% 0,rgba(47,106,74,.42),transparent 50%),radial-gradient(ellipse at 92% 100%,rgba(176,138,42,.18),transparent 42%),radial-gradient(ellipse at center,#0a0f15cc,#060a0ef2),var(--world-bg,none) center/160px repeat,#0a0f15}
body[data-world] #area{box-shadow:inset 0 -2px 0 var(--course-warm)}
body[data-world] .world-cover,body[data-world] .lesson-plate,body[data-world] .qrow .plate{border-color:var(--course)}
#ttl .panel{max-width:520px;width:100%;margin:auto}
#ov{background-image:linear-gradient(#060a0ee8,#060a0ee8),var(--world-bg,none);background-size:auto,160px 160px;background-color:#060a0e}
body.intitle #hud{visibility:hidden}
.legend{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 4px}.legend i{width:10px;height:10px;border-radius:50%;box-shadow:0 0 0 2px #2a1d0a;display:block}
.kbd{display:inline-block;min-width:22px;padding:0 6px;border:1px solid var(--brass-mid);border-bottom-width:2px;border-radius:5px;background:#070b10;font:800 12px/20px var(--font);text-align:center;color:var(--gold-hi)}
.toast{z-index:40}
body.indlg .toast{bottom:calc(max(12px,env(safe-area-inset-bottom)) + var(--lq-dlg-h,150px) + 10px)}
.mapfull{width:100%;border:1px solid var(--brass);border-radius:10px;background:#0a0f15;display:block;margin-bottom:10px}
.qrow{display:flex;gap:10px;align-items:center;padding:8px 0;border-bottom:1px solid #2b3643}
.qrow .plate{width:56px;height:36px;object-fit:cover;object-position:center;border-radius:6px;border:1px solid var(--brass-mid);background:#0a0f15;flex:none}
.qrow .ic{width:28px;text-align:center;font-size:18px;color:var(--gold)}
.qrow .ic svg{display:block;margin:0 auto}
.qrow .qb{flex:1}.qrow .btn{width:auto;min-height:44px;font-size:14px;padding:6px 12px}
.disc{pointer-events:auto}
body.indlg #pad,body.indlg #acts{display:none!important}body.indlg #area{opacity:0!important}body.indlg #narrcap{visibility:hidden}
#narrcap{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);z-index:30;max-width:min(680px,92vw);padding:10px 16px;border:1px solid #d7b56a99;border-radius:12px;background:#0a0f15ee;color:#f3ead6;font-size:15px;line-height:1.4;pointer-events:none;display:flex;gap:10px;align-items:baseline}#narrcap:not([hidden]){animation:ovfade .18s ease}
#narrcap[hidden]{display:none}#narrcap .who{font:700 12px var(--display);letter-spacing:.1em;text-transform:uppercase;color:#d7b56a;flex:none}
/* while a dialogue is open the guide caption floats just above the dialogue box (--lq-dlg-h from guide.js) instead of under it */
body.indlg #narrcap{bottom:calc(max(12px,env(safe-area-inset-bottom)) + var(--lq-dlg-h,150px) + 10px)}
/* phone guide caption (r2): a full-width strip just under the top HUD stack (the map camera often parks the hero low on the screen,
   above the move pad, so the bottom is not safe). While it shows, the region banner drops below it (--lq-cap-h comes from guide.js).
   Short phones (<=760px tall) drop the region medallion row (the stats line already says n/N regions) and the banner kicker, so a centred hero stays clear. */
@media (max-width:560px){#narrcap{top:calc(var(--lq-hud-b,206px) + 6px);bottom:auto;width:calc(100vw - 24px);max-width:none;box-sizing:border-box;font-size:14px;line-height:1.35;padding:8px 12px}
body:has(#narrcap:not([hidden])) #area{top:calc(var(--lq-hud-b,206px) + var(--lq-cap-h,60px) + 12px)}
body.indlg #narrcap{bottom:auto}
@media (max-height:760px){#pm{display:none}#mm{height:60px}#narrcap{font-size:13px;padding:6px 10px}body:has(#narrcap:not([hidden])) #area{top:calc(var(--lq-hud-b,206px) + var(--lq-cap-h,60px) + 8px)}body:has(#narrcap:not([hidden])) #area{padding:4px 16px}body:has(#narrcap:not([hidden])) #area .kicker{display:none}body:has(#narrcap:not([hidden])) #area b{font-size:17px}}}

#cutscene{position:fixed;inset:0;z-index:25;background:#000;display:flex;align-items:center;justify-content:center;animation:ovfade .18s ease}#cutscene video{max-width:100%;max-height:100%;width:100%;height:100%;object-fit:contain}#cutscene .skip{position:absolute;top:14px;right:14px;z-index:2;padding:8px 16px;border:1px solid #d7b56a;border-radius:10px;background:#0a0f15dd;color:#f3ead6;font:700 14px var(--display);cursor:pointer;min-height:44px;transition:border-color .14s,transform .1s}#cutscene .skip:hover{border-color:#f3e2b0}#cutscene .skip:active{transform:translateY(1px)}
/* Python challenges */
.codeq .cq-prompt{color:var(--ink-dim);margin:0 0 12px}.codeq .cq-prompt code,.cq-hintbox code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.92em;background:#070b10;border:1px solid #2b3643;border-radius:5px;padding:1px 5px;color:var(--ink)}
.cq-ed{display:block;width:100%;box-sizing:border-box;min-height:220px;margin:4px 0 12px;padding:12px;font:600 14px/1.5 ui-monospace,Menlo,Consolas,monospace;color:#f6efe0;background:#070b10;border:1px solid var(--brass-mid);border-radius:var(--radius);tab-size:4;white-space:pre;overflow:auto;resize:vertical;transition:border-color .14s,box-shadow .14s}
.cq-ed:focus{outline:none;border-color:var(--gold-hi);box-shadow:0 0 0 2px #d7b56a40}
.cq-btns{display:flex;gap:10px}.cq-btns .btn{flex:1}.cq-btns2{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px}.cq-btns2 .btn{width:auto;min-height:44px;flex:1 1 auto;animation:pop .22s ease backwards}.cq-btns2 .btn:nth-child(2){animation-delay:.05s}.cq-btns2 .btn:nth-child(3){animation-delay:.1s}.cq-btns2 .btn:nth-child(4){animation-delay:.15s}
.cq-out{margin-top:12px;padding:10px 12px;border:1px solid var(--brass-mid);border-radius:var(--radius);background:#0a0f15;min-height:20px;font-size:14px}.cq-out:empty{display:none}.cq-out.ok{border-color:var(--good)}.cq-out.bad{border-color:var(--bad)}.cq-out.cheer{animation:cqcheer .5s ease}
.cq-out pre,.cq-sol{margin:0 0 6px;white-space:pre-wrap;font:600 13px/1.45 ui-monospace,Menlo,Consolas,monospace;color:var(--ink)}.cq-sol{background:#070b10;border:1px solid #2b3643;border-radius:8px;padding:10px;margin:8px 0}
.cq-t{padding:4px 0;animation:pop .22s ease both}.cq-t.ok{color:var(--good)}.cq-t.no{color:var(--bad);animation-name:optno}.cq-t .small{color:var(--ink-dim);margin-left:18px}
.cq-hintbox{margin-top:10px;padding:10px 12px;border-left:3px solid var(--gold);background:#121a24;border-radius:8px;color:var(--ink-dim);font-size:14px}

.cq-edwrap{position:relative;margin:4px 0 12px;border:1px solid var(--brass-mid);border-radius:var(--radius);background:#070b10;overflow:hidden;transition:border-color .14s,box-shadow .14s}
.cq-edwrap:focus-within{border-color:var(--gold-hi);box-shadow:0 0 0 2px #d7b56a40}
.cq-gut{position:absolute;left:0;top:0;bottom:0;width:38px;background:#0b1118;border-right:1px solid #2b3643;overflow:hidden;pointer-events:none}
.cq-gin{padding:12px 8px 12px 0;text-align:right;white-space:pre;font:600 14px/21px ui-monospace,Menlo,Consolas,monospace;color:#7d8b9a}
.cq-edwrap .cq-ed{margin:0;border:0;border-radius:0;padding:12px 12px 12px 48px;line-height:21px;box-shadow:none;background:transparent;overflow:auto;white-space:pre}
.cq-edwrap .cq-ed:focus{box-shadow:none}
pre.code{margin:10px 0;padding:10px 12px;background:#070b10;border:1px solid #2b3643;border-left:3px solid var(--gold);border-radius:8px;color:#f6efe0;font:600 13.5px/1.55 ui-monospace,Menlo,Consolas,monospace;overflow:auto;white-space:pre}
.sim-row{margin:10px 0}.sim-row label{display:block;color:var(--ink-dim)}.sim-row input[type=range]{display:block;width:100%;margin-top:6px;accent-color:#d7b56a}.sim-row select{margin-left:6px;background:#0b1118;color:var(--ink);border:1px solid var(--brass-mid);border-radius:8px;padding:6px 8px;font:inherit;transition:border-color .14s,box-shadow .14s}.sim-row select:focus{outline:none;border-color:var(--gold-hi);box-shadow:0 0 0 2px #d7b56a40}
.sim-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:12px 0}.sim-grid .cell{padding:10px 12px;border-radius:10px;border:1px solid #2b3643;background:#0b1118}.sim-grid .cell b{display:block;font-size:24px;color:var(--ink)}.sim-grid .cell span{font-size:13px;color:var(--ink-dim)}.sim-grid .good{border-color:#3f6a45}.sim-grid .warn{border-color:#8a6a2a}.sim-grid .bad{border-color:#8a3b3b}
.sm-bar{display:flex;align-items:center;gap:8px;margin:5px 0;font-size:14px}.sm-t{width:56px;color:var(--ink)}.sm-b{flex:1;height:14px;background:#0b1118;border:1px solid #2b3643;border-radius:7px;overflow:hidden}.sm-b i{display:block;height:100%;width:0;background:linear-gradient(90deg,#8a6a2a,#d7b56a);transition:width .28s cubic-bezier(.22,.7,.3,1)}.sm-p{width:54px;text-align:right;color:var(--ink-dim)}
.ac-row{transition:opacity .28s cubic-bezier(.22,.7,.3,1)}.ac-fill{transition:width .28s cubic-bezier(.22,.7,.3,1),background-color .28s linear}#ac-t{transition:border-color .14s,box-shadow .14s}#ac-t:focus{outline:none;border-color:var(--gold-hi);box-shadow:0 0 0 2px #d7b56a40}textarea.exp-note{font:inherit;color:var(--ink);background:#070b10;border:1px solid var(--brass-mid);border-radius:8px;padding:8px;transition:border-color .14s,box-shadow .14s}textarea.exp-note:focus{outline:none;border-color:var(--gold-hi);box-shadow:0 0 0 2px #d7b56a40}#cb-bar .segs span{height:100%;flex:none;transition:width .28s cubic-bezier(.22,.7,.3,1)}
#cx-svg circle{transition:opacity .22s linear}

/* beginner scaffolding for Python challenges */
.cq-learn{margin:0 0 14px;border:1px solid var(--brass-mid);border-radius:var(--radius);background:#0b1118;padding:0 12px 10px}
.cq-learn>summary{cursor:pointer;padding:10px 0;color:var(--gold-hi);font-weight:800;font-size:14px}
.cq-exh{margin:8px 0 4px;color:var(--ink);font-weight:800;font-size:14px}.cq-say{color:var(--ink-dim);font-size:14px;margin:0 0 6px}
.cq-say code,.cq-walkbox code{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:.92em;background:#070b10;border:1px solid #2b3643;border-radius:5px;padding:1px 5px;color:var(--gold-hi)}
.cq-exed{display:block;width:100%;box-sizing:border-box;margin:4px 0;padding:10px 12px;font:600 13px/1.5 ui-monospace,Menlo,Consolas,monospace;color:#f6efe0;background:#070b10;border:1px solid #2b3643;border-radius:8px;white-space:pre;overflow:auto;resize:vertical;transition:border-color .14s,box-shadow .14s}
.cq-exed:focus{outline:none;border-color:var(--gold-hi)}.cq-exed:focus-visible{outline:2px solid var(--gold-hi);outline-offset:2px}.cq-exrow{margin:2px 0 4px}.cq-exrow .btn{width:auto;min-height:44px;animation:pop .22s ease backwards}.cq-exrow .btn:nth-child(2){animation-delay:.05s}.cq-exrow .btn:nth-child(3){animation-delay:.1s}
.cq-exout{font-size:13px}.cq-exout:empty{display:none}.cq-exout{padding:6px 10px;border-left:3px solid var(--good);background:#0a0f15;border-radius:6px;margin-bottom:4px}.cq-exout.bad{border-left-color:var(--bad)}.cq-exout pre{margin:0;white-space:pre-wrap;font:600 13px/1.45 ui-monospace,Menlo,Consolas,monospace;color:var(--ink)}.cq-exout>pre,.cq-exout>span,.cq-exout>b,.cq-out>pre,.cq-out>span,.cq-out>b{animation:pop .22s ease backwards}
.cq-walkbox{margin-top:10px;padding:10px 14px;border-left:3px solid var(--good);background:#101a20;border-radius:8px;color:var(--ink-dim);font-size:14px}.cq-walkbox ol{margin:6px 0 0 18px;padding:0}.cq-walkbox li{margin:4px 0}

/* runnable lesson examples, scratchpad, "Python ideas used here" */
.pyx{margin:12px 0;padding:10px 12px;border:1px solid var(--brass-mid);border-radius:var(--radius);background:#0b1118}
.pyx .cq-exed{min-height:48px}
.pyx .cq-exrow .btn{margin-right:6px}
.cq-ideas{margin:6px 0 12px}.pyidea-link{background:none;border:1px solid var(--brass-mid);border-radius:999px;color:var(--gold-hi);font:700 12px/1 var(--font);padding:5px 10px;margin:2px 2px;cursor:pointer;min-height:44px;transition:border-color .14s,transform .1s}.pyidea-link:hover{border-color:var(--gold-hi)}.pyidea-link:active{transform:translateY(1px)}
.pyidea{position:fixed;inset:0;z-index:9500;background:rgba(5,8,12,.82);display:flex;align-items:flex-start;justify-content:center;overflow:auto;padding:4vh 12px;animation:ovfade .18s ease}
.pyidea-in{width:min(760px,100%);background:var(--panel,#0e141c);border:1px solid var(--brass-mid);border-radius:var(--radius);padding:14px 18px 18px;box-shadow:0 12px 40px rgba(0,0,0,.6);animation:pop .22s ease backwards}
.pyidea-bar{display:flex;justify-content:space-between;align-items:center;gap:8px;margin-bottom:8px;color:var(--gold-hi)}.pyidea-bar .btn{width:auto}
.scratch select{max-width:100%}.pyx-scr-sel{background:#0b1118;color:var(--ink);border:1px solid var(--brass-mid);border-radius:8px;padding:6px 8px;font:inherit;transition:border-color .14s,box-shadow .14s}.pyx-scr-sel:focus{outline:none;border-color:var(--gold-hi);box-shadow:0 0 0 2px #d7b56a40}
.lesson .pyx p{margin:0 0 6px}

.ib .ico{display:block;margin:auto;color:#e0c070;filter:drop-shadow(0 1px 0 rgba(0,0,0,.5))}.ib:hover .ico,.ib:focus-visible .ico{color:#f3e2b0}.qrow .ico{color:#d7b56a;display:block;margin:auto}
.stk{display:inline-flex;align-items:center;gap:4px}.stk .mk{color:#e0c070}
.plate{width:84px;height:84px;border-radius:12px;border:2px solid var(--brass);display:grid;place-items:center;background:#121a24;flex:none;color:#e0c070;box-shadow:0 0 0 1px var(--brass-ink)}
.plate .mk{width:40px;height:40px}
.bmk{width:36px;height:36px;display:grid;place-items:center;flex:none;color:#e0c070;border:1px solid var(--brass-mid);border-radius:10px;background:#0a0f15}
.badge.off .bmk{color:#a89878}
.sat{display:flex;align-items:flex-start;gap:8px}.sat .mk{color:#e0c070;flex:none;margin-top:4px}
.lvl .ico .mk{color:#e0c070}
/* Python primer layer and guide clips (Phase 2) */
.pp-list{margin:4px 0 10px 18px;padding:0;color:var(--ink-dim);font-size:14px}.pp-list li{margin:3px 0}
.pp-how{margin:4px 0 6px}.pp-how>summary{cursor:pointer;color:var(--gold-hi);font-weight:800;font-size:13px;padding:6px 0}.pp-how ol{margin:6px 0 6px 18px;padding:0;color:var(--ink-dim);font-size:14px}.pp-how p{color:var(--ink-dim);font-size:14px}
.pp-blank{border-top:1px solid rgba(215,181,106,.18);padding-top:6px}.pp-blank:first-of-type{border-top:0}.pp-blank .cq-exrow{display:flex;flex-wrap:wrap;gap:6px}
.pp-primer>summary,.pp-blanks>summary{min-height:24px}
.lq-guide{margin:0 0 14px;padding:8px 10px 10px;border:1px solid var(--brass-mid);border-radius:var(--radius);background:#0b1118;animation:ovfade .18s ease}.lq-guide .kicker{margin:0 0 6px}
.lq-guide-v{display:block;width:100%;max-height:320px;border-radius:8px;background:#000}

/* phone: challenge buttons in a 2-column grid, full 44px targets (Opus review #4) */
.cq-chknote{margin:6px 0 0}.cq-walknote{margin:8px 0 0}
@media (max-width:560px){.cq-btns2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.cq-btns2 #cq-giveup{grid-column:1/-1}.cq-btns2 .btn{min-height:44px;font-size:14px;padding:8px 10px}}
@keyframes dlgin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes ovfade{from{opacity:0}to{opacity:1}}
@keyframes cqcheer{50%{box-shadow:0 0 0 3px #d7b56acc,0 0 16px 2px #d7b56a80}}
@keyframes idlebreath{50%{transform:translateY(1px)}}
@keyframes arrive{from{opacity:0}to{opacity:1}}
@keyframes flame{50%{transform:translateY(-1px) scale(1.12)}}
@keyframes qping{0%{box-shadow:0 0 0 0 #d7b56a88}100%{box-shadow:0 0 0 10px #d7b56a00}}
@keyframes xpup{40%{transform:scale(1.12)}to{transform:none}}
#quest.ping{animation:qping .6s ease}#xpn.xpup{display:inline-block;animation:xpup .45s ease}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* Expedition base camp, procedural WebGL diorama */
.exp-stage{position:relative;margin:0 0 16px;padding:0;border:1px solid var(--brass);border-top-color:var(--gold-hi);border-bottom-color:var(--brass-lo);border-radius:var(--radius);overflow:hidden;background:#0e141c;box-shadow:inset 0 0 0 1px #070b10c7,0 8px 20px #0006}
.exp-stage canvas{display:block;width:100%;height:min(62vw,340px);min-height:200px;background:#121a22;touch-action:none;cursor:grab}
.exp-stage canvas:active{cursor:grabbing}
.exp-stage figcaption{margin:0;padding:8px 12px 10px;color:var(--ink-dim)}

/* ===== r4 HUD + game feel (26 Oct 2026). UI only: frames, reward card, XP feedback, button feel, map cards, banner dodge. ===== */
/* Framed HUD panels: a forged double frame (brass, dark gap, thin gold) with four brass rivets. Same palette as the rest of the game. */
#hud .panel{border-color:#c8a86a;border-top-color:#f3e2b0;border-bottom-color:#6b4a0e;box-shadow:inset 0 0 0 2px #070b10d9,inset 0 0 0 3px #d7b56a5c,inset 0 10px 18px -12px #f3e2b033,inset 0 -14px 22px -14px #000c,0 0 0 1px #8a6528,0 0 0 3px #1a1208,0 0 0 4px #6b4a0e99,0 4px 8px #0007,0 14px 26px #0009}
#hud .panel:after{content:"";position:absolute;inset:4px;border-radius:calc(var(--radius) - 3px);pointer-events:none;z-index:2;
 background:radial-gradient(circle at 4px 4px,#f3e2b0 0 1.2px,#b08a38 1.8px 2.8px,#2a1d0a 3.2px,transparent 3.8px),radial-gradient(circle at calc(100% - 4px) 4px,#f3e2b0 0 1.2px,#b08a38 1.8px 2.8px,#2a1d0a 3.2px,transparent 3.8px),radial-gradient(circle at 4px calc(100% - 4px),#f3e2b0 0 1.2px,#b08a38 1.8px 2.8px,#2a1d0a 3.2px,transparent 3.8px),radial-gradient(circle at calc(100% - 4px) calc(100% - 4px),#f3e2b0 0 1.2px,#b08a38 1.8px 2.8px,#2a1d0a 3.2px,transparent 3.8px)}
#quest{transition:transform .12s ease,filter .14s ease}
#quest:hover{filter:brightness(1.08);transform:translateY(-1px)}#quest:active{transform:translateY(1px)}
/* XP bar: an inset trough, a warm fill with a top gloss, quarter ticks, and a shine sweep when XP is gained */
#party .bar{position:relative;height:10px;border-radius:6px;background:linear-gradient(#05080b,#0d131a);border:1px solid #8a6528;box-shadow:inset 0 2px 3px #000c,0 1px 0 #f3e2b022}
#party .bar>i{position:relative;background:linear-gradient(180deg,#fff1c4 0,#f0c860 35%,#c9902a 70%,#8a5a14 100%);box-shadow:0 0 8px #f0c86088;border-radius:5px 0 0 5px}
#party .bar:before{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;background:linear-gradient(90deg,transparent calc(25% - 1px),#0a0f15aa 25%,transparent calc(25% + 1px),transparent calc(50% - 1px),#0a0f15aa 50%,transparent calc(50% + 1px),transparent calc(75% - 1px),#0a0f15aa 75%,transparent calc(75% + 1px))}
#party .bar:after{content:"";position:absolute;top:0;bottom:0;left:-40%;width:40%;z-index:3;pointer-events:none;opacity:0;background:linear-gradient(90deg,transparent,#fff8dccc,transparent)}
#party .bar.gain:after{animation:xpshine .9s ease-out}
#party .bar.gain{animation:xpglow .9s ease-out}
@keyframes xpshine{0%{left:-40%;opacity:1}100%{left:110%;opacity:0}}
@keyframes xpglow{30%{box-shadow:inset 0 2px 3px #000c,0 0 12px #f0c860cc}}
#party.rankup{animation:rankup 1.2s ease-out}
@keyframes rankup{20%{box-shadow:inset 0 0 0 2px #070b10d9,inset 0 0 0 3px #f3e2b0,0 0 0 1px #f3e2b0,0 0 24px 6px #f0c86099}}
.xpfloat{position:fixed;z-index:19;transform:translate(-50%,0);pointer-events:none;font:800 16px/1 var(--font);color:#fff1c4;text-shadow:0 1px 0 #5a3a0a,0 0 8px #f0c860,0 2px 4px #000;animation:xpfloat 1.3s ease-out forwards;white-space:nowrap}
.xpfloat.big{font:700 20px/1 var(--display);letter-spacing:.06em}
.xpfloat.calm{animation:none;opacity:1}
@keyframes xpfloat{0%{opacity:0;transform:translate(-50%,6px) scale(.8)}15%{opacity:1;transform:translate(-50%,0) scale(1.08)}30%{transform:translate(-50%,-2px) scale(1)}100%{opacity:0;transform:translate(-50%,-26px)}}
/* buttons: lift on hover, a warm rim, and a press that sinks */
.ib{transition:border-color .14s,transform .1s ease,background .14s,box-shadow .14s,filter .14s;box-shadow:inset 0 1px #f3e2b02e,inset 0 -2px #0008,0 2px 0 #1a1208,0 4px 8px #0007}
.ib:hover{border-color:var(--gold-hi);background:#152030;transform:translateY(-1px);box-shadow:inset 0 1px #f3e2b04d,inset 0 -2px #0008,0 3px 0 #1a1208,0 0 12px #d7b56a40,0 6px 10px #0008}
.ib:active,#pad button.hold{transform:translateY(2px) scale(.96);box-shadow:inset 0 2px 4px #000c,0 0 0 #1a1208;filter:brightness(.92)}
#acts .ib{box-shadow:inset 0 2px #fff8dc8c,inset 0 -4px #5a3c0a66,0 3px 0 #2a1d0a,0 6px 14px #000a}
#acts .ib:active,#bact.hold{transform:translateY(3px) scale(.95);box-shadow:inset 0 3px 6px #5a3c0a99,0 0 0 #2a1d0a}
/* region banner: moves out of the way of figures (see bannerDodge in world.js) */
body #area.dodge{top:auto!important;bottom:calc(max(12px,env(safe-area-inset-bottom)) + 96px)!important}
body #area.mini{padding:3px 14px!important;opacity:.92}
body #area.mini .kicker{display:none}body #area.mini b{font-size:15px!important}
@media (max-width:560px){body #area.dodge{bottom:calc(max(12px,env(safe-area-inset-bottom)) + 204px)!important}}
@media (pointer:coarse) and (min-width:561px){body #area.dodge{bottom:calc(max(14px,env(safe-area-inset-bottom)) + 100px)!important}}
/* chest reward card */
#lqreward{position:fixed;inset:0;z-index:18;display:flex;align-items:center;justify-content:center;padding:max(16px,env(safe-area-inset-top)) 16px calc(max(12px,env(safe-area-inset-bottom)) + 150px);background:radial-gradient(ellipse at center,#0a0f1599,#060a0ecc);animation:ovfade .2s ease;--rar:#7fb2ff}
#lqreward.out{opacity:0;transition:opacity .2s ease}
#lqreward .rw-rays{position:absolute;left:50%;top:calc(50% - 75px);width:min(640px,150vw);aspect-ratio:1;transform:translate(-50%,-50%);pointer-events:none;background:repeating-conic-gradient(from 0deg,color-mix(in srgb,var(--rar) 40%,transparent) 0 6deg,transparent 6deg 20deg);-webkit-mask:radial-gradient(circle,#000 10%,#0008 35%,transparent 66%);mask:radial-gradient(circle,#000 10%,#0008 35%,transparent 66%);animation:rwspin 18s linear infinite,rwin .5s ease-out}
#lqreward .rw-card{position:relative;width:min(340px,100%);margin:0;text-align:center;padding:18px 18px 16px;border-color:var(--rar);box-shadow:inset 0 0 0 2px #070b10d9,inset 0 0 0 3px color-mix(in srgb,var(--rar) 55%,transparent),0 0 0 1px #8a6528,0 0 0 3px #1a1208,0 0 28px color-mix(in srgb,var(--rar) 45%,transparent),0 18px 40px #000c;animation:rwcard .55s cubic-bezier(.2,.9,.3,1.25) both}
#lqreward .kicker{margin:0 0 6px}
#lqreward .rw-icon{width:96px;height:96px;margin:2px auto 6px;filter:drop-shadow(0 0 14px color-mix(in srgb,var(--rar) 70%,transparent)) drop-shadow(0 4px 4px #000a);animation:rwicon .6s .22s cubic-bezier(.2,.9,.3,1.4) both,rwbob 2.6s 1s ease-in-out infinite}
#lqreward .rw-icon svg{display:block;width:96px;height:96px}
#lqreward .rw-rar{display:inline-block;padding:2px 12px;border-radius:99px;font:800 12px/1.6 var(--font);letter-spacing:.12em;text-transform:uppercase;color:#0a0f15;background:var(--rar);box-shadow:0 0 12px color-mix(in srgb,var(--rar) 60%,transparent);animation:pop .3s .4s ease backwards}
#lqreward .rw-name{margin:8px 0 2px;font:700 24px/1.15 var(--display);letter-spacing:.03em;color:var(--rar);text-shadow:0 0 10px color-mix(in srgb,var(--rar) 40%,transparent),0 2px 2px #000}
#lqreward .rw-where{margin:0 0 8px;font-size:14px;color:var(--ink-dim)}
#lqreward .rw-xp{margin:0 0 12px;font:800 26px/1 var(--font);color:#fff1c4;text-shadow:0 0 10px #f0c86099,0 2px 2px #000}
#lqreward .rw-ok{width:100%}
#lqreward.rw-legendary .rw-name{color:#ffb35a}
#lqreward.calm,#lqreward.calm *{animation:none!important}
@keyframes rwcard{0%{opacity:0;transform:perspective(700px) translateY(30px) rotateX(55deg) scale(.7)}60%{opacity:1}100%{opacity:1;transform:none}}
@keyframes rwicon{0%{opacity:0;transform:scale(.2) rotate(-25deg)}100%{opacity:1;transform:none}}
@keyframes rwbob{50%{transform:translateY(-4px)}}
@keyframes rwspin{to{transform:translate(-50%,-50%) rotate(360deg)}}
@keyframes rwin{from{opacity:0;transform:translate(-50%,-50%) scale(.4)}}
/* world map: a framed map and region cards with a numbered seal, the level title, and a status chip */
.mapfull{border:1px solid #c8a86a;box-shadow:0 0 0 1px #1a1208,0 0 0 3px #6b4a0e88,inset 0 0 30px #000a}
#mr .mr-head{display:flex;align-items:center;gap:12px;margin:2px 0 10px;font-size:14px;color:var(--ink-dim)}#mr .mr-head .bar{flex:1;height:10px}
#mr .mr-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:8px}
#mr .mr-card{position:relative;gap:10px;padding:8px 10px 8px 8px;border:1px solid #2b3643;border-left:4px solid var(--rt,#8a6528);border-radius:10px;background:linear-gradient(90deg,color-mix(in srgb,var(--rt,#8a6528) 18%,#0b1118),#0b1118 60%);transition:transform .12s ease,border-color .14s,box-shadow .14s}
#mr .mr-card.open:hover,#mr .mr-card.done:hover{transform:translateY(-1px);border-color:#c8a86a;border-left-color:var(--rt,#8a6528);box-shadow:0 0 12px #d7b56a33}
#mr .mr-card.locked{filter:saturate(.35) brightness(.75)}
#mr .mr-card.here{border-color:#f3e2b0;box-shadow:0 0 0 1px #f3e2b055,0 0 14px #f3e2b033}
#mr .mr-n{flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;font:800 14px/1 var(--font);color:#1a1208;background:radial-gradient(circle at 35% 30%,#fff1c4,#d7b56a 55%,#8a6528);border:1px solid #2a1d0a;box-shadow:0 1px 2px #000a}
#mr .mr-card.locked .mr-n{background:#2b3643;color:#9aa6b2}
#mr .qb{display:flex;flex-wrap:wrap;align-items:center;gap:2px 8px;min-width:0}#mr .qb b{flex:1 1 100%;line-height:1.2}
#mr .mr-sub{flex:1 1 100%;font-size:12.5px;color:var(--ink-dim);line-height:1.25}
#mr .chip{display:inline-flex;align-items:center;gap:4px;padding:0 8px;border-radius:99px;font:800 11.5px/20px var(--font);letter-spacing:.04em}
#mr .chip svg{width:12px;height:12px}
#mr .chip.ok{background:#2f5a2a;color:#d8f0c8;border:1px solid #6aa85a}#mr .chip.go{background:#4a3a14;color:#f3e2b0;border:1px solid #c9a24f}#mr .chip.lock{background:#1a222c;color:#9aa6b2;border:1px solid #3a4654}#mr .chip.here{background:#f3e2b0;color:#1a1208}
#mr .mr-card .btn{flex:none}
@media (prefers-reduced-motion:reduce){#party .bar.gain:after,#party .bar.gain,#party.rankup,.xpfloat{animation:none}.ib:hover,#quest:hover,#mr .mr-card:hover{transform:none}}
/* the reward card already names the find, so fx2's cheer pill steps back (still announced to screen readers) */
body:has(#lqreward) .lq-cheer{opacity:0!important}
/* short screens (phone landscape): a compact card that still fits above the dialogue box */
@media (max-height:520px){#lqreward{padding:8px 16px;overflow:auto;align-items:flex-start}#lqreward .rw-card{padding:10px 14px;display:grid;grid-template-columns:64px 1fr;column-gap:12px;text-align:left;align-items:center}
#lqreward .rw-card>*{grid-column:2}#lqreward .rw-icon{grid-column:1;grid-row:1/span 5;width:64px;height:64px;margin:0}#lqreward .rw-icon svg{width:64px;height:64px}
#lqreward .rw-name{font-size:19px;margin:4px 0 0}#lqreward .rw-xp{font-size:20px;margin:2px 0 8px}#lqreward .rw-ok{grid-column:1/span 2;min-height:44px}#lqreward .rw-rays{top:30%}}
@media (max-height:520px){#lqreward .rw-rar{justify-self:start}#lqreward .rw-where{margin:0 0 2px;font-size:13px}}
/* the card says "Added to your badges", so the badge toast waits underneath it (still announced) */
body:has(#lqreward) .toast{opacity:0!important}
