:root{
  --bg:#0c0a0e; --panel:#171220; --panel2:#1f1830; --line:#332a44;
  --ink:#d8cfbe; --dim:#8d8398; --ember:#d4763c; --blood:#a53a2e;
  --gold:#e8c74a; --mana:#3f6fd4;
  /* Minimum comfortable touch target. Apple HIG and Material both say 44px, and the
     player reported exactly this problem with the potion belt. Applied as an INVISIBLE
     expansion (.tap below) so a control can stay visually small without being small
     to a thumb. */
  --tap:44px;
}
/* One breakpoint for phones, one for desktop. There used to be twelve, at 400 / 640 /
   760 / 820 / 840 / 860 / 1100, which is why layouts came apart at odd widths.
     MOBILE : (max-width:820px),(pointer:coarse) and (max-height:520px)
     DESKTOP: (min-width:821px) and (min-height:521px)
   The single survivor is #dailyCard's 1100px rule, which asks a genuinely different
   question — "is there room for a card BESIDE the title?" — not "is this a phone?".

   Invisible hit-area expansion: the box keeps its drawn size, the tappable area grows
   to --tap. Growing the drawn size instead would reflow the bottom bar, which has a
   fixed height, and push controls off screen. */
.tap{position:relative;}
/* ::BEFORE, not ::after. .pbtn.nudge::after already draws the attention dot, and being
   the more specific selector it replaced this box entirely — so a nudging button
   silently lost its 44px thumb area. Two different jobs, two different pseudos. */
.tap::before{content:'';position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);width:var(--tap);height:var(--tap);}
*{box-sizing:border-box; margin:0; padding:0; user-select:none;}
html,body{width:100%;height:100vh;height:100dvh;overflow:hidden;background:var(--bg);
  font-family:Georgia,'Times New Roman',serif;color:var(--ink);}
/* #game, NOT every canvas. As a bare element selector this also caught the hat
   previews in the Vault and pinned them to the top-left corner of the screen,
   outside their own cards — they were being drawn correctly and rendered nowhere
   near where they belonged. */
#game{position:fixed;top:0;left:0;display:block;touch-action:none;}
html,body{overscroll-behavior:none;}
.hidden{display:none !important;}
/* low-HP danger vignette — pure CSS, JS only toggles .on */
#lowhp{position:fixed;inset:0;z-index:15;pointer-events:none;opacity:0;
  transition:opacity .5s ease;
  background:radial-gradient(ellipse at 50% 50%,rgba(0,0,0,0) 42%,rgba(120,10,10,.28) 78%,rgba(150,12,12,.55) 100%);}
/* --losev (set from JS) ramps 0 at the 35% threshold → 1 near death: the vignette
   deepens and the pulse quickens instead of snapping to full panic at 34%. */
#lowhp.on{opacity:1;animation:lowhpPulse calc(1.8s - var(--losev,0)*1s) ease-in-out infinite;}
@keyframes lowhpPulse{0%,100%{opacity:calc((0.45 + var(--losev,0)*0.55)*0.55);}
                      50%{opacity:calc(0.45 + var(--losev,0)*0.55);}}

/* ---------- overlays ---------- */
.overlay{position:fixed;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:flex-start;background:radial-gradient(ellipse at 50% 40%,#191122 0%,#0c0a0e 70%);z-index:40;text-align:center;padding:20px;overflow-y:auto;}
/* Vertical centring that survives overflow. This used to be `justify-content:safe center`,
   which Chrome here does not support — it fell back to flex-start, so EVERY overlay in the
   game sat pinned to the top edge with the rest of a tall phone screen empty below it.
   Plain `center` is not the fix either: once the content is taller than the screen it
   overflows equally in both directions and the top is clipped out of reach, which is
   exactly what `safe` was asking to avoid — and the death screen and the card draft are
   both tall enough for that to happen. Two zero-height spacer items with `margin:auto`
   split the free space when there is any and collapse to 0 when there is not, giving safe
   centring in every browser. Deliberately pseudo-elements rather than :first/:last-child:
   #select swaps between two views by toggling `display:none`, and a display:none child
   would silently take its auto margin out of the layout. */
.overlay::before,.overlay::after{content:'';flex:0 0 auto;margin:auto;}
#select{background:transparent;}   /* let the burning-gate canvas scene show through (darkening comes from the scene) */
.overlay h1{font-size:56px;letter-spacing:14px;color:var(--ember);font-weight:normal;
  text-shadow:0 0 30px rgba(212,118,60,.35);}
.overlay h1.blood{color:var(--blood);letter-spacing:10px;}
.overlay .sub{color:var(--dim);margin:8px 0 26px;font-style:italic;font-size:clamp(13px,1.3vw,17px);}
.overlay .controls{margin-top:22px;color:var(--dim);font-size:13px;}
#deathScreen p{color:var(--dim);margin-top:10px;}

/* ⚠ auto-fit, NOT repeat(5). The grid was authored for five columns and the redesign left
   four archetypes, so the row was laid out inside a box 150px+gap wider than its contents and
   sat ~80px left of the title above it — reported as "the heroes are off-centre", which is
   exactly what it was. Counting the classes in CSS is how that happens again the next time
   the roster changes. */
/* ⚠ FLEX, NOT auto-fit GRID. repeat(auto-fit,150px) resolves its column count from the
   CONTAINER's width, and this container is sized by its content — so it settled on one
   150px column and stacked the heroes vertically. Flex-wrap centres however many classes
   exist without needing to be told the number, which was the point of the change. */
#classGrid{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;}
#classGrid>*{flex:0 0 150px;}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){
  #classGrid{gap:10px;}
  #classGrid>*{flex:0 0 minmax(0,150px);}
  .overlay h1{font-size:34px;letter-spacing:8px;}
  .overlay{justify-content:flex-start;padding:16px 12px 30px;}
  .overlay .sub{margin:6px 0 18px;}
  #cardTitle{font-size:18px;margin-bottom:14px;}
  #cardChoices{gap:12px;}
  .card{width:150px;min-height:0;padding:14px 10px;}
  .card .cicon{font-size:38px;margin:6px 0 4px;}
  .card .ctitle{font-size:15px;margin-bottom:8px;}
  .card .cdesc{font-size:11px;}
  .cardhint,.overlay .controls{margin-top:14px;}
}
.classCard{background:var(--panel);border:1px solid var(--line);padding:14px 10px;cursor:pointer;
  transition:border-color .15s, transform .15s;}
.classCard:hover{border-color:var(--cc,var(--ember));transform:translateY(-3px);}
.classCard .ci{font-size:30px;display:block;}
/* The hero's own sprite, at an INTEGER multiple of its 32px source (32 -> 64) with
   smoothing off, so it scales up as pixel art rather than as a blurred photograph.
   The card is 30px of emoji tall, so 64 also gives the picker some presence. */
/* the 128x128 bust, cut from one sheet — see tools/portrait_gen.py. Rendered 1:1 so
   nothing is resampled; the inline background-position picks the hero. */
.classCard .cbust{display:block;width:128px;height:128px;margin:-4px auto 6px;
  /* VERSIONED on purpose. The sheet is referenced from CSS, so it is not covered by the
     ?v= sweep over index.html's script tags — and when portrait_gen.py added the ascended
     variants the sheet grew from 768x384 to 768x768. A cached copy of the old one would
     leave every evolved bust blank, because those rows simply do not exist in it. Bump
     this whenever the sheet is regenerated. */
  background-image:url(art/portraits.png?v=20260730dq);background-repeat:no-repeat;
  image-rendering:pixelated;image-rendering:crisp-edges;
  box-shadow:0 4px 14px rgba(0,0,0,.55);}
.classCard:hover .cbust{box-shadow:0 4px 20px var(--cc,#e0402e);}
.classCard.locked .cbust{filter:grayscale(1) brightness(.45);}
.classCard .cpor{display:block;width:64px;height:64px;margin:0 auto -2px;
  image-rendering:pixelated;image-rendering:crisp-edges;
  filter:drop-shadow(0 3px 5px rgba(0,0,0,.6));}
.classCard:hover .cpor{filter:drop-shadow(0 3px 8px var(--cc,#e0402e));}
.classCard .cn{display:block;margin:6px 0 4px;color:var(--cc,var(--ink));letter-spacing:1px;}
.classCard .cd{font-size:clamp(11px,1vw,13.5px);color:var(--dim);line-height:1.45;font-family:Verdana,sans-serif;}
.classCard .ctr{display:block;margin-top:7px;padding-top:6px;border-top:1px dashed #3a3050;
  font-size:clamp(10px,0.95vw,12.5px);font-family:Verdana,sans-serif;line-height:1.45;}
/* Upgrades, on the hero picker (v4.71). Narrower than a hub card and centred over the grid:
   it is a signpost on the way to choosing a hero, not a twelfth thing competing with them.
   `.hasPts` lights it only when there is actually something to spend — a permanently glowing
   button teaches players to ignore it. */
/* ⚠ display:block UNDID .hubCard's column layout, so the icon, the title and the subtitle
   ran together on one line — "Tvůj účet12 Cinder · Vylepšení…". It only showed once the card
   grew a subtitle worth reading (v5.52). Keep the column; constrain the width. */
#classView .classUpg{display:flex;flex-direction:column;align-items:center;margin:0 auto 14px;max-width:330px;}
.hubCard.hasPts{border-color:#c9a227;box-shadow:0 0 0 1px #c9a22755, 0 0 16px -6px #ffd75e;}
.hubCard.hasPts .hsub{color:#ffd75e;}
#accBadge.spend{font-size:9px;font-weight:700;color:#1a1420;background:#ffd75e;
  border-radius:7px;padding:0 4px;margin-left:3px;vertical-align:middle;}

/* What an Evolution actually grants, under the trait (v4.69). Dimmer and tighter than the
   trait line: it is the reward you already bought, not the promise the class makes. */
.classCard .cevod{display:block;margin-top:6px;padding-top:5px;border-top:1px dotted #4a3f66;
  font-size:clamp(9.5px,0.9vw,12px);font-family:Verdana,sans-serif;line-height:1.45;color:#c9a227;}
.classCard .cevod b{color:#ffd75e;}
.classCard.locked{opacity:.55;cursor:not-allowed;filter:grayscale(.6);}
.classCard.locked:hover{border-color:var(--line);transform:none;}
.classCard.locked .ci{filter:grayscale(1);}
/* achievements panel */
.achHead{color:var(--ember);letter-spacing:1px;margin-bottom:10px;font-size:13px;}
.achrow{display:flex;gap:10px;align-items:flex-start;padding:9px 8px;border:1px solid var(--line);
  border-radius:5px;margin-bottom:7px;background:rgba(0,0,0,.18);}
.achrow.done{border-color:#5a7a4a;background:rgba(60,90,50,.14);}
.achico{font-size:22px;line-height:1;flex:0 0 auto;width:26px;text-align:center;}
.achbody{flex:1 1 auto;min-width:0;}
.achname{color:var(--ink);font-size:13px;letter-spacing:.5px;}
.achrow.done .achname{color:#bfe6a8;}
.achok{color:#8fe08f;}
.achdesc{color:var(--dim);font-size:11px;font-family:Verdana,sans-serif;line-height:1.4;margin-top:2px;}
.achbar{height:6px;background:#241d33;border-radius:3px;overflow:hidden;margin:6px 0 3px;}
.achbar>span{display:block;height:100%;background:linear-gradient(90deg,#c96a3b,#e8c74a);}
.achprog{color:var(--dim);font-size:10px;font-family:Verdana,sans-serif;}
.achrew{color:#7ce0a0;font-size:10px;font-family:Verdana,sans-serif;margin-top:4px;}

/* ---------- Home hub (start screen) ---------- */
#homeView,#classView{width:100%;display:flex;flex-direction:column;align-items:center;}
#homeView{max-width:560px;margin:0 auto;}
#classView{max-width:820px;margin:0 auto;}
#homeView.hidden,#classView.hidden{display:none;}
#homeView #acctBar{margin:0 0 12px;width:100%;}
.hubHero{margin:2px 0 4px;}
#homeView .sub{margin:6px 0 18px;}
/* The Cinder strip, between the title and Start Game. Deliberately NOT a hub card: it is
   the only thing on this screen that states a fact about you rather than offering a door,
   so it is a quiet plaque that happens to be clickable. .hidden hides it at zero. */
#hubCinder{display:flex;flex-direction:column;align-items:center;gap:2px;
  width:100%;max-width:340px;margin:0 0 16px;padding:9px 14px;cursor:pointer;
  background:var(--panel);border:1px solid var(--line);border-radius:3px;
  font-family:inherit;color:var(--dim);transition:border-color .2s,box-shadow .2s;}
#hubCinder.hidden{display:none;}
#hubCinder:hover{border-color:var(--ember);}
/* lit only when there is something SPENDABLE — locked Cinder is not money, and a glowing
   plaque over a number you cannot use is the same lie the account badge used to tell */
#hubCinder.hasFree{border-color:var(--ember);box-shadow:0 0 18px rgba(212,118,60,.22);}
#hubCinder .hcMain{font-size:clamp(15px,3.4vw,19px);letter-spacing:1px;color:var(--dim);}
#hubCinder.hasFree .hcMain{color:#ffd06a;}
#hubCinder .hcLock{font-family:Verdana,sans-serif;font-size:11px;color:var(--dim);}
.startBtn{font-family:inherit;font-size:22px;letter-spacing:3px;color:#140b0b;font-weight:bold;
  background:linear-gradient(#e6a24a,#c4763c);border:1px solid var(--ember);
  padding:16px 44px;min-height:56px;cursor:pointer;border-radius:3px;
  box-shadow:0 0 26px rgba(212,118,60,.45);transition:transform .12s,box-shadow .2s;
  text-shadow:0 1px 0 rgba(255,220,180,.45);}
.startBtn:hover{transform:translateY(-2px);box-shadow:0 0 40px rgba(212,118,60,.7);}
.startBtn:active{transform:translateY(0);}
#hubActions{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;
  width:100%;margin:22px 0 6px;}   /* fixed 2 cols → clean 2x2 on both mobile & desktop */
.hubCard{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
  /* min-height covers the tallest card rather than the shortest. The Upgrades card
     carries a second line of text, and grid rows stretch to their tallest member — so
     without this only ITS row grew and the hub lost its even rhythm. */
  gap:5px;min-height:100px;padding:12px 8px;background:var(--panel);border:1px solid var(--line);
  /* ⚠ SIZED WITH clamp(), NOT WITH A MEDIA QUERY. Asked for: bigger, more readable menu text,
     "but everything has to be fine on a phone". A flat bump does the opposite of that — the
     hub is a fixed 2-column grid at every width, so a font that fits a desktop card wraps a
     phone card into four lines and pushes the grid past the fold. clamp(min, vw, max) grows
     the type with the viewport and refuses to pass either end: the phone keeps its current
     size, the desktop reads a third larger, and nothing needs a breakpoint to be maintained. */
  color:var(--ink);font-family:inherit;font-size:clamp(13px,1.35vw,17px);letter-spacing:1px;cursor:pointer;text-align:center;
  transition:border-color .15s,transform .15s;}
.hubCard:hover{border-color:var(--ember);transform:translateY(-2px);}
.hubCard.hidden{display:none;}
.hubCard .hicon{font-size:clamp(22px,2.1vw,28px);line-height:1;}
/* Optional third line on a hub card. Only Upgrades uses it: that card needs to say what
   it is, because "Shop" plus a cart icon read as a paid store, and the card sits on the
   home screen where a new player forms that impression first. Wraps rather than clipping,
   and the cards are a flex column already, so the row simply grows to fit. */
.hubCard .hsub{font-size:clamp(10px,0.95vw,12.5px);letter-spacing:0;line-height:1.25;color:var(--dim);
  text-transform:none;max-width:16ch;}
.hubCard .soon{position:absolute;top:4px;right:4px;font-size:9px;letter-spacing:.5px;
  color:var(--gold);border:1px solid var(--gold);border-radius:8px;padding:1px 5px;text-transform:uppercase;}
/* ---------- Home hub facelift (v0.7.61) — the game's face, not a form ----------
   Owner: "je to nas face co laka lidi a vypada to fakt trosku nudne a stare."
   Three moves: the title becomes a LOGO (ember gradient + breathing glow), the OS emoji
   die (mask-SVG icons, one style, theme-coloured), and the actual game walks onto the
   screen (#hubParade — real atlas frames, filled by hubParadeInit in 25-core.js). */
.hubHero h1{
  font-size:clamp(40px,7vw,74px);letter-spacing:clamp(6px,1.5vw,16px);margin:0;
  background:linear-gradient(180deg,#ffe9a0 0%,#ffb44a 38%,#e0742e 62%,#8a3a1c 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  animation:hubTitleGlow 4.5s ease-in-out infinite;}
@keyframes hubTitleGlow{
  0%,100%{filter:drop-shadow(0 0 12px rgba(224,116,46,.32)) drop-shadow(0 2px 0 rgba(16,7,5,.9));}
  50%{filter:drop-shadow(0 0 26px rgba(255,180,74,.55)) drop-shadow(0 2px 0 rgba(16,7,5,.9));}}
.hubHero::after{content:'';display:block;width:min(430px,82%);height:2px;margin:8px auto 0;
  background:linear-gradient(90deg,transparent,#e0742e 28%,#ffd75e 50%,#e0742e 72%,transparent);}
#hubParade{display:flex;gap:30px;justify-content:center;align-items:flex-end;
  margin:12px 0 2px;min-height:56px;}
#hubParade canvas{width:52px;height:52px;image-rendering:pixelated;
  filter:drop-shadow(0 7px 5px rgba(0,0,0,.55));animation:paradeBob 1.15s ease-in-out infinite;}
#hubParade canvas:nth-child(2){animation-delay:.14s;}
#hubParade canvas:nth-child(3){animation-delay:.28s;}
#hubParade canvas:nth-child(4){animation-delay:.42s;}
@keyframes paradeBob{0%,100%{transform:translateY(0);}50%{transform:translateY(-3px);}}
.startBtn{position:relative;overflow:hidden;border-radius:6px;
  background:linear-gradient(180deg,#f2b45a,#d4763c 55%,#a94f28);
  animation:startPulse 3.2s ease-in-out infinite;}
@keyframes startPulse{
  0%,100%{box-shadow:0 0 24px rgba(212,118,60,.45);}
  50%{box-shadow:0 0 44px rgba(255,180,74,.7);}}
.startBtn::after{content:'';position:absolute;top:0;left:-60%;width:38%;height:100%;
  transform:skewX(-18deg);
  background:linear-gradient(90deg,transparent,rgba(255,242,210,.38),transparent);
  animation:startSheen 3.2s ease-in-out infinite;}
@keyframes startSheen{0%,55%{left:-60%;}100%{left:140%;}}
.hubCard{background:linear-gradient(180deg,#241c31,#181223);border:1px solid #3c3154;border-radius:7px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05);
  transition:border-color .15s,transform .15s,box-shadow .2s;}
.hubCard:hover{border-color:var(--ember);transform:translateY(-3px);
  box-shadow:0 10px 24px -12px rgba(224,116,46,.6),inset 0 1px 0 rgba(255,255,255,.07);}
/* one icon language instead of five operating systems' emoji: alpha-mask SVGs, painted
   with the ember ramp so every card matches the game's own light */
.hubCard .hicon{width:32px;height:32px;font-size:0;
  background:linear-gradient(180deg,#ffd75e,#e0742e);
  -webkit-mask:var(--ic) center/contain no-repeat;mask:var(--ic) center/contain no-repeat;}
.hicon[data-ic="login"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='8' r='4'/%3E%3Cpath d='M4 21c0-4.4 3.6-7 8-7s8 2.6 8 7z'/%3E%3C/svg%3E");}
.hicon[data-ic="key"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M7 3a5 5 0 1 0 4.6 7l1.4 1.4V14h2v2h2v2h2l2-2-7.4-7.4A5 5 0 0 0 7 3zm0 3a2 2 0 1 1 0 4 2 2 0 0 1 0-4z'/%3E%3C/svg%3E");}
.hicon[data-ic="play"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 4l13 8-13 8z'/%3E%3C/svg%3E");}
.hicon[data-ic="trophy"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 3h14v2h3v3c0 2.8-2.2 4.8-5 5a7 7 0 0 1-4 3.7V19h4v2H7v-2h4v-2.3A7 7 0 0 1 7 13c-2.8-.2-5-2.2-5-5V5h3zm-1 4v1c0 1.5 1 2.6 2.3 2.9A9.5 9.5 0 0 1 4 7zm16 0a9.5 9.5 0 0 1-2.3 3.9C19 10.6 20 9.5 20 8z'/%3E%3C/svg%3E");}
.hicon[data-ic="account"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2l7 7h-4v7H9V9H5z'/%3E%3Cpath d='M5 19h14v3H5z'/%3E%3C/svg%3E");}
.hicon[data-ic="book"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 4.5C6 3 9.5 3 11.5 4.6V20C9.5 18.4 6 18.4 3 20zM21 4.5C18 3 14.5 3 12.5 4.6V20c2-1.6 5.5-1.6 8.5 0z'/%3E%3C/svg%3E");}
.hicon[data-ic="scroll"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect x='6' y='6' width='12' height='12'/%3E%3Crect x='3' y='2' width='18' height='4' rx='2'/%3E%3Crect x='3' y='18' width='18' height='4' rx='2'/%3E%3C/svg%3E");}
.hicon[data-ic="gear"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill-rule='evenodd' d='M10 2h4l.6 2.6 2.4 1 2.3-1.4 2.8 2.8-1.4 2.3 1 2.4 2.3.6v3l-2.3.6-1 2.4 1.4 2.3-2.8 2.8-2.3-1.4-2.4 1L14 22h-4l-.6-2.6-2.4-1-2.3 1.4-2.8-2.8 1.4-2.3-1-2.4L0 13.5v-3l2.3-.6 1-2.4-1.4-2.3 2.8-2.8 2.3 1.4 2.4-1zm2 6a4 4 0 1 0 0 8 4 4 0 0 0 0-8z'/%3E%3C/svg%3E");}
.hicon[data-ic="gem"]{--ic:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 3h12l4 6-10 12L2 9z'/%3E%3C/svg%3E");}
@media (prefers-reduced-motion:reduce){
  .hubHero h1,.startBtn,.startBtn::after,#hubParade canvas{animation:none;}
}

.backLink{align-self:flex-start;color:var(--dim);cursor:pointer;font-size:14px;letter-spacing:1px;
  padding:6px 4px;margin-bottom:2px;user-select:none;}
.backLink:hover{color:var(--ember);}
/* leaderboard (and other) panels float above the start overlay when opened from the hub */
body.cg-home .panel{z-index:45;}
#hubToast{position:fixed;left:50%;top:24px;transform:translateX(-50%);z-index:60;
  background:var(--panel2);border:1px solid var(--ember);color:var(--ink);
  font-family:Verdana,sans-serif;font-size:13px;padding:10px 18px;border-radius:3px;
  box-shadow:0 6px 20px rgba(0,0,0,.6);opacity:0;pointer-events:none;transition:opacity .25s;
  max-width:90vw;text-align:center;}
#hubToast.show{opacity:1;}

/* ---------- HUD ---------- */
/* height is driven by JS (--app-h = visualViewport.height) so the bottom HUD sits at the
   real visible bottom, not under the mobile browser toolbar; dvh is the no-JS fallback */
#hud{position:fixed;top:0;left:0;right:0;height:100vh;height:100dvh;height:var(--app-h,100dvh);
  pointer-events:none;z-index:20;}
#topline{position:absolute;top:10px;left:14px;right:14px;display:flex;justify-content:space-between;
  font-size:14px;letter-spacing:1px;text-shadow:0 1px 3px #000;}
#tierline{color:var(--ember);}
#tierbadge{position:absolute;top:34px;right:14px;z-index:5;padding:3px 10px;border-radius:11px;
  font-size:12px;font-weight:700;letter-spacing:.6px;color:#e9d8ff;
  background:linear-gradient(180deg,rgba(80,40,120,.85),rgba(46,22,74,.9));
  border:1px solid #a060e0;box-shadow:0 0 8px rgba(160,96,224,.45);pointer-events:auto;white-space:nowrap;}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){ #tierbadge{top:30px;right:10px;font-size:11px;padding:2px 8px;} }
/* #dailyBanner was here, at `top:34px; left:50%` — the SAME coordinates as #bossbar below,
   so during a daily boss fight the rules sat across the boss's health bar. The rules now
   live in the character sheet beside the mutators they describe (runRulesHtml). */
#bossbar{position:absolute;top:34px;left:50%;transform:translateX(-50%);width:min(520px,80vw);
  height:16px;background:#1a0d0d;border:1px solid var(--blood);}
#bossfill{height:100%;background:linear-gradient(#c9483a,#7c261e);width:100%;}
#bossname{position:absolute;inset:0;text-align:center;font-size:11px;line-height:16px;
  letter-spacing:2px;color:#f0d9c8;}

#bottombar{position:absolute;left:0;right:0;bottom:0;height:calc(200px + env(safe-area-inset-bottom,0px));
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:8px 18px calc(8px + env(safe-area-inset-bottom,0px));background:#120e1a;
  border-top:2px solid var(--line);box-shadow:0 -6px 18px rgba(0,0,0,.5);}
.orb{position:relative;width:104px;height:104px;border-radius:50%;border:3px solid #4a3a2c;flex:0 0 auto;
  background:#140b0b;overflow:hidden;box-shadow:0 0 18px rgba(0,0,0,.8) inset;transition:box-shadow .2s;}
.orb.hp.warn{animation:hpWarn .7s ease-in-out infinite;border-color:#e0402e;}
.orb.mana.warn{animation:mpWarn .7s ease-in-out infinite;border-color:#5d8ae8;}
@keyframes hpWarn{0%,100%{box-shadow:0 0 8px rgba(224,64,46,.5),0 0 18px rgba(0,0,0,.8) inset;}
  50%{box-shadow:0 0 26px 6px rgba(224,64,46,.9),0 0 18px rgba(0,0,0,.8) inset;}}
@keyframes mpWarn{0%,100%{box-shadow:0 0 8px rgba(93,138,232,.5),0 0 18px rgba(0,0,0,.8) inset;}
  50%{box-shadow:0 0 26px 6px rgba(93,138,232,.9),0 0 18px rgba(0,0,0,.8) inset;}}
.orb.mana{border-color:#2c3a52;}
.orb .fill{position:absolute;left:0;right:0;bottom:0;height:100%;
  background:radial-gradient(circle at 35% 30%,#e0604a,#7c1c14 70%);transition:height .15s;}
.orb.mana .fill{background:radial-gradient(circle at 35% 30%,#5d8ae8,#1c2f6e 70%);}
.orbtxt{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  font-size:16px;font-family:Verdana,sans-serif;text-shadow:0 1px 2px #000;}
#midbar{display:flex;flex-direction:column;align-items:center;gap:6px;flex:1;min-width:0;}
#skillbar{display:flex;gap:7px;flex-wrap:wrap;justify-content:center;}
.skslot{position:relative;width:64px;height:64px;background:var(--panel);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;font-size:30px;pointer-events:auto;}
.skslot.combo{border-color:#ff9a3c;box-shadow:0 0 8px rgba(255,154,60,.4);}
.skslot .key{position:absolute;top:1px;left:4px;font-size:16px;color:var(--dim);font-family:Verdana,sans-serif;}
.skslot .cdov{position:absolute;left:0;right:0;bottom:0;background:rgba(10,6,14,.82);}
.skslot.locked{filter:grayscale(1) brightness(.5);}
.skslot .lock{position:absolute;bottom:1px;right:4px;font-size:14px;color:var(--dim);}
.skslot.nomana{outline:1px solid var(--mana);}
.skslot.off{filter:grayscale(1) brightness(.55);}
.skslot.off::after{content:'OFF';position:absolute;inset:0;display:flex;align-items:center;
  justify-content:center;font-size:15px;color:#e05a4a;font-family:Verdana,sans-serif;
  letter-spacing:1px;background:rgba(10,6,14,.45);text-shadow:0 1px 2px #000;}
.skslot .costmark{position:absolute;top:1px;right:4px;font-size:14px;}
/* effective minion/turret cap (base + Growing Legion) shown top-right of summon/turret slots */
.skslot .mcap{position:absolute;top:0;right:3px;font-size:12px;font-weight:700;color:#cfeee0;
  text-shadow:0 1px 2px #000;font-family:Verdana,sans-serif;}
.skslot .mcap.boosted{color:#7fe0a0;}
.skslot .aoemark{position:absolute;inset:2px;border:2px dashed;pointer-events:none;}
.skslot.cost{border-color:#8f3a3a;}
.skslot.nowep{filter:grayscale(1) brightness(.45);outline:1px dashed #e05a4a;}
#xpbar{position:relative;width:100%;max-width:900px;height:20px;background:#221a30;border:1px solid var(--line);}
#xpfill{height:100%;background:linear-gradient(90deg,#8a6bd4,#c9a44a);width:0;}
#xptxt{position:absolute;inset:0;font-size:15px;line-height:20px;text-align:center;color:#cbc;font-family:Verdana,sans-serif;}
/* The slice the last orb just added, drawn UNDER the fill and left behind as it fades —
   so the bar answers "how much was that one worth?" without a number to read. */
#xpghost{position:absolute;top:0;height:100%;background:#f0dc9a;opacity:0;pointer-events:none;}
#xpgain{position:absolute;right:8px;top:0;line-height:20px;font-size:13px;color:#ffe9a0;
  font-family:Verdana,sans-serif;opacity:0;pointer-events:none;text-shadow:0 1px 2px #000;}
#beltrow{display:flex;gap:14px;align-items:center;justify-content:center;flex-wrap:wrap;}
#beltline{display:flex;gap:12px;font-size:22px;align-items:center;}
#howtoBtn{height:36px;padding:0 13px;border-radius:18px;white-space:nowrap;font-size:13px;background:var(--panel2);border:1px solid var(--ember);
  color:var(--ember);font-family:Georgia,serif;font-size:20px;cursor:pointer;pointer-events:auto;line-height:1;}
#howtoBtn:hover{background:var(--ember);color:#140b0b;}
#panelBtns{display:flex;gap:6px;}
.pbtn{width:38px;height:38px;border-radius:6px;background:var(--panel2);border:1px solid var(--line);
  font-size:19px;cursor:pointer;pointer-events:auto;line-height:1;padding:0;}
.pbtn:hover{border-color:var(--ember);}
#actionBtns{position:absolute;right:14px;bottom:216px;display:flex;flex-direction:column;gap:8px;z-index:24;}
.abtn{min-width:120px;padding:12px 16px;border-radius:8px;background:rgba(20,15,29,.92);
  border:2px solid var(--ember);color:var(--ember);font-family:Georgia,serif;font-size:17px;
  cursor:pointer;pointer-events:auto;box-shadow:0 4px 14px #000;}
.abtn:active{background:var(--ember);color:#140b0b;}
/* the caravan button carries two extra things: the key (desktop only) and the fare */
.abtn kbd{background:rgba(0,0,0,.45);border:1px solid var(--line);border-radius:4px;
  padding:1px 6px;font:600 12px Verdana,sans-serif;margin-left:5px;color:var(--ink);}
.abtn small{display:block;font:11px Verdana,sans-serif;color:var(--dim);margin-top:2px;letter-spacing:0;}
/* native dash button — round, thumb-reachable, with a recharge ring (bg set live in updateHUD) */
#dashBtn{position:absolute;right:16px;bottom:300px;width:72px;height:72px;border-radius:50%;
  background:conic-gradient(from -90deg,#d08a45 360deg,rgba(20,15,24,.92) 0);
  border:2px solid var(--ember);color:#fff;font-size:26px;line-height:1;cursor:pointer;pointer-events:auto;
  z-index:25;box-shadow:0 4px 16px #000;display:flex;align-items:center;justify-content:center;user-select:none;
  -webkit-user-select:none;text-shadow:0 1px 2px #000;}
#dashBtn b{position:absolute;right:-2px;bottom:-2px;min-width:20px;height:20px;border-radius:10px;
  background:var(--ember);color:#140b0b;font-size:12px;font-weight:700;font-family:Georgia,serif;
  display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 4px #000;}
#dashBtn.empty{filter:grayscale(1) brightness(.7);opacity:.62;}
#dashBtn:active{transform:scale(.94);}
/* ---------- mobile layout ---------- */
@media (max-width:820px),(pointer:coarse) and (max-height:520px){
  #bottombar{height:calc(168px + env(safe-area-inset-bottom,0px));
    padding:6px clamp(5px,2vw,8px) calc(6px + env(safe-area-inset-bottom,0px));
    gap:clamp(5px,1.6vw,8px);}
  /* keep the skill row to ONE horizontally-scrolling line so learning skills never
     balloons the bar and pushes the panel buttons (inventory/options) off-screen */
  #skillbar{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;justify-content:flex-start;
    max-width:100%;-webkit-overflow-scrolling:touch;}
  #skillbar .skslot{flex:0 0 auto;}
  #topline{flex-wrap:wrap;gap:2px 10px;font-size:12px;}
  #topline #charline,#topline #tierline{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  /* scales continuously from a 360px phone up to the 820px boundary, instead of
     stepping down at a hard 400px cutoff */
  .orb{width:clamp(58px,17vw,72px);height:clamp(58px,17vw,72px);}
  .orbtxt{font-size:clamp(10px,2.8vw,12px);}
  .skslot{width:48px;height:48px;font-size:22px;}
  .skslot .key{font-size:12px;}
  .skslot .lock{font-size:11px;}
  #xpbar{height:14px;} #xptxt{font-size:11px;line-height:14px;} #xpgain{font-size:10px;line-height:14px;}
  #beltline{font-size:clamp(13px,3.6vw,15px);gap:clamp(5px,1.6vw,7px);}
  #beltline .pot{padding:clamp(2px,.8vw,3px) clamp(4px,1.6vw,6px);}
  #beltline .pot small{display:none;}
  #beltline kbd{min-width:18px;font-size:12px;}
  #hintbar{display:none;}
  /* stays 34px to the eye — the .tap class gives it a 44px thumb area */
  .pbtn{width:34px;height:34px;font-size:16px;}
  /* offsets clear the bottombar, which itself grows by the home-indicator safe area */
  #howto{bottom:calc(176px + env(safe-area-inset-bottom,0px));}
  #toasts{bottom:calc(186px + env(safe-area-inset-bottom,0px));}
  /* .panel mobile positioning lives in the bottom-of-file media block — the base
     .panel rule below out-orders anything written here (equal specificity) */
  #actionBtns{bottom:calc(184px + env(safe-area-inset-bottom,0px));}
  /* ON A PHONE the dash sits on the LEFT, stacked ABOVE the two potions, so every
     action control is under one thumb: dash 332 / life 258 / mana 184. On desktop it
     stays on the right, where there is room and a mouse to reach it. */
  #dashBtn{left:14px;right:auto;bottom:calc(332px + env(safe-area-inset-bottom,0px));
    width:62px;height:62px;font-size:23px;}
}
/* NB: mobile overrides for #invPanel and stash slots live at the BOTTOM of this file —
   the base rules below this block would out-order them here (equal specificity). */
/* very narrow phones — shrink orbs/belt so gold doesn't collide with the mana orb */
/* The 400px tier used to live here. It shrank .pbtn to 30px and .skslot to 42px —
   making the touch targets SMALLEST exactly where fingers have the least room. Its
   spacing now scales continuously inside the single mobile block via clamp(), and
   nothing tappable shrinks any further. */
#howto{position:absolute;bottom:210px;left:50%;transform:translateX(-50%);z-index:25;
  max-width:720px;width:min(720px,92vw);text-align:center;font-family:Verdana,sans-serif;font-size:12px;line-height:1.6;
  color:var(--ink);background:rgba(16,12,24,.97);border:1px solid var(--line);border-radius:4px;
  padding:10px 16px;pointer-events:auto;box-shadow:0 8px 30px #000;}
#howto b{color:var(--ember);}
/* ⚠ ALWAYS ITS OWN LINE, AND THE `flex-basis` IS THE WHOLE RULE (2026-08-11). #hintbar is a
   direct child of #beltrow, which wraps — so on a narrow window it fell to its own row and on a
   wide one it did not, and the keyboard cheatsheet ended up threaded between the potion, the
   gold and the panel buttons in a single 2000px strip. Reported as "UI je v jednom radku, coz
   je nehezke", and it was never a deliberate layout: it was whatever the viewport happened to
   allow. It is REFERENCE TEXT, not a control, and it does not belong in the row of controls at
   any width. flex-basis:100% forces the wrap that a wide screen otherwise never triggers.
   ⚠ It is still display:none under 560px (see the phone block above) — a cheatsheet for keys a
   phone does not have. That keeps working only because NOTHING HERE SETS `display`; this rule
   sits after that media query, so adding one would switch the bar back on for every phone. */
#hintbar{flex-basis:100%;text-align:center;margin-top:2px;
  color:var(--dim);font-size:14px;font-family:Verdana,sans-serif;letter-spacing:.4px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;max-width:90vw;}
#beltline .pot{position:relative;display:flex;align-items:center;gap:5px;background:rgba(20,15,29,.75);
  border:1px solid var(--line);border-radius:4px;padding:4px 9px;pointer-events:auto;overflow:hidden;}
/* potion cooldown overlay — a darkening sweep + ticking seconds while on cooldown */
#beltline .pot .potcd{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
  border-radius:inherit;font-family:Verdana,sans-serif;font-weight:700;font-size:15px;color:#ffe6a8;
  text-shadow:0 1px 2px #000;pointer-events:none;}
#beltline .pot.cooling .potcd{display:flex;}
#beltline .pot.cooling{border-color:#5a4a6a;}
#beltline .pot small{font-size:15px;color:var(--dim);font-family:Verdana,sans-serif;
  letter-spacing:.5px;margin-left:2px;}
#beltline .pot.gold{border-color:#6a5a2c;}
#beltline kbd{display:inline-block;min-width:26px;text-align:center;font-size:17px;
  font-family:Verdana,sans-serif;color:var(--ink);background:#2b2140;border:1px solid #4d3f6a;
  border-bottom-width:2px;border-radius:3px;padding:1px 4px;margin-right:2px;}
.skslot .lock{font-size:15px;}
.sech{color:var(--ember);letter-spacing:2px;font-size:13px;font-weight:normal;margin:14px 0 6px;
  border-bottom:1px solid var(--line);padding-bottom:4px;}
.sech small{color:var(--dim);letter-spacing:0;font-size:10px;font-family:Verdana,sans-serif;}
.fusebtn.go{border-color:#ff9a3c;color:#ff9a3c;text-align:center;font-weight:bold;}
#beltline b{color:var(--gold);font-family:Verdana,sans-serif;font-weight:normal;}

#toasts{position:absolute;left:16px;bottom:218px;display:flex;flex-direction:column-reverse;gap:3px;
  font-size:12px;font-family:Verdana,sans-serif;text-shadow:0 1px 2px #000;}

/* ---------- panels ---------- */
/* EVERY panel takes the whole screen. Four of them (Features, Database, Leaderboards,
   Achievements) already did, because a 340px rail on the right made a document
   unreadable — but that same rail made the inventory, the skill tree, the forge and the
   options page just as cramped, and there is nothing to watch behind them anyway:
   opening any panel PAUSES the game (see `paused` in 25-core.js).
   --pad is the horizontal padding, referenced by the sticky h2 below so the header can
   bleed to the panel edge at ANY width — hard-coding -60px against a clamped padding
   left the header hanging off the left edge on mid-width screens. */
.panel{--pad:max(clamp(14px,5vw,60px),calc((100vw - 1180px) / 2));
  position:fixed;top:0;right:0;bottom:0;left:0;width:auto;max-width:none;
  /* ⚠ 46, NOT 40, AND NOT ONLY ON THE HOME SCREEN. .overlay (#select, the title screen) is
     also z-index 40 and comes LATER in the DOM, so with the two tied the overlay won and the
     home screen's cards painted straight over an open panel. It was hidden by
     `body.cg-home .panel{z-index:45}` — but that class is only set when the home screen is
     ENTERED, so arriving straight at /database (a real route since v5.53) had nothing to lift
     the panel and the Database rendered underneath the menu. */
  background:rgba(14,10,20,.985);border:none;z-index:46;
  padding:22px var(--pad) 44px;overflow-y:auto;box-shadow:0 0 40px #000;}
.panel.wide{width:auto;}          /* the old 430px cap — a no-op now, so the markup need not change */
.panel h2{font-weight:normal;letter-spacing:3px;font-size:22px;color:var(--ember);
  border-bottom:1px solid var(--line);position:sticky;top:-22px;z-index:2;
  background:rgba(14,10,20,.99);
  padding:20px var(--pad) 12px;margin:-22px calc(var(--pad) * -1) 16px;}
/* The comfortable measure is done with PADDING (the max() in --pad above), not with
   `max-width` + `margin:auto` on the children. Auto margins flip a grid ITEM from
   stretch to shrink-to-fit, which silently collapsed the inventory's eight backpack
   columns to 2px each — the panel is a grid, so its children are grid items. */
/* ⚠ 10px AND 11px WERE UNREADABLE, AND THEY CARRY THE EXPLANATIONS (owner, 2026-08-12: "vsechny
   popisne texty jsou strasne male"). These two classes hold every sentence in the game that says
   what a screen is FOR — the panel subtitles and the in-panel notes — so they were the smallest
   type in the build and also the type doing the most work. Anything a player has to squint at is
   text they will not read, which turns an explained mechanic back into an unexplained one. */
.phint{font-size:13px;color:var(--dim);letter-spacing:0;float:right;margin-top:4px;font-family:Verdana,sans-serif;max-width:62%;line-height:1.45;}
.panelClose{vertical-align:middle;margin-right:12px;background:rgba(60,40,70,.55);
  border:1px solid var(--ember);color:var(--ember);font-family:inherit;font-size:12px;
  letter-spacing:1px;padding:5px 12px;border-radius:6px;cursor:pointer;line-height:1;}
.panelClose:hover{background:var(--ember);color:#1a1020;}
.panelClose:active{transform:translateY(1px);}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){ .panelClose{font-size:13px;padding:7px 14px;margin-right:10px;} }
.tab{background:none;border:none;color:var(--dim);font-family:inherit;font-size:15px;letter-spacing:2px;
  cursor:pointer;margin-right:14px;padding:0 0 6px;}
.tab.on{color:var(--ember);border-bottom:2px solid var(--ember);}

#equipGrid{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;margin-bottom:14px;}
#invGrid{display:grid;grid-template-columns:repeat(8,1fr);gap:5px;}
.slot{position:relative;aspect-ratio:1;background:var(--panel2);border:1px solid var(--line);
  display:flex;align-items:center;justify-content:center;font-size:19px;cursor:pointer;}
.slot .sl{position:absolute;bottom:1px;left:0;right:0;text-align:center;font-size:7px;
  color:var(--dim);letter-spacing:1px;font-family:Verdana,sans-serif;pointer-events:none;}
/* forge upgrade level (+N) badge — top-right corner of the item */
.slot .upg{position:absolute;top:0;right:2px;font-size:11px;font-weight:700;color:#e8c74a;
  text-shadow:0 1px 2px #000;font-family:Verdana,sans-serif;pointer-events:none;line-height:1;}
.slot.r0{border-color:#6a6458;} .slot.r1{border-color:#5f86d9;} .slot.r2{border-color:#b45fe0;}
.slot.r3{border-color:#e8c74a;} .slot.r4{border:2px solid #e0402e;box-shadow:0 0 8px rgba(224,64,46,.5);}
.slot.r5{border:2px solid #ff9a3c;animation:uniqueGlow 1.6s ease-in-out infinite;}
.slot.rset{border:2px solid #43d17a;box-shadow:0 0 9px rgba(67,209,122,.55);}   /* set items — green framing */
/* ---- mass-salvage bar ---- */
#salvbar .salvrow{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:8px;font-size:12px;}
.salvchip{background:var(--panel2);border:1px solid var(--line);color:var(--ink);font-family:inherit;
  font-size:11px;padding:5px 9px;border-radius:20px;cursor:pointer;white-space:nowrap;}
.salvchip.on{border-color:var(--rc);color:var(--rc);box-shadow:0 0 7px color-mix(in srgb,var(--rc) 45%,transparent);}
.salvchip.locked{opacity:.6;cursor:pointer;}
.salvchip:hover{border-color:var(--rc);}
.salvgo{background:#3a2a1a;border:1px solid var(--ember);color:var(--ember);font-family:inherit;font-size:11px;
  font-weight:bold;padding:5px 12px;border-radius:20px;cursor:pointer;}
.salvgo:hover{background:var(--ember);color:#1a0f08;}
#salvbar .salvnote{font-size:10px;color:var(--dim);margin-top:4px;}
/* the Resolution chips in Options — same chip as the salvage bar, laid out in a row */
.qchips{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px;}
/* the level pip on a grove node — small, under the icon, never competing with it */
.gweb .gwlv{font:700 15px ui-monospace,Menlo,Consolas,monospace;fill:#e8e2d8;text-anchor:middle;
  opacity:.85;pointer-events:none;}
.gweb .gwnode.max .gwlv{fill:#7fe0a0;}
/* ---- Codex / Database ---- */
#codexPanel #codexTabs{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;}
.cxtab{background:var(--panel2);border:1px solid var(--line);color:var(--ink);font-family:inherit;
  font-size:12px;padding:6px 10px;border-radius:6px;cursor:pointer;white-space:nowrap;}
.cxtab.on{border-color:var(--ember);color:var(--ember);}
.cxcount{font-size:10px;color:var(--dim);}
.cxtab.on .cxcount{color:var(--ember);}
.cxgrouphead{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);
  margin:12px 2px 6px;font-weight:700;}
.cxgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(94px,1fr));gap:8px;}
.cxcell{display:flex;flex-direction:column;align-items:center;gap:4px;padding:10px 6px;border-radius:7px;
  background:var(--panel2);border:1px solid var(--line);border-bottom:2px solid var(--tone);cursor:default;
  text-align:center;transition:filter .15s,opacity .15s,transform .1s;}
.cxcell:hover{transform:translateY(-1px);}
.cxicon{font-size:22px;line-height:1;color:var(--tone);}
.cxname{font-size:10px;color:var(--ink);line-height:1.2;word-break:break-word;}
/* ⚠ THIS USED TO BE grayscale(1) brightness(.42) opacity(.6), FROM WHEN THE PAGE WAS A
   COLLECTION LOG and an unmet thing was meant to be a silhouette. The Database is a wiki now
   (v6.65): the twelve craftable sets are the most important rows on the page and, being unmet
   by definition until you make one, they were the DIMMEST things on it. A tick you have not
   earned should be a quiet difference, not a veil. */
.cxcell.unseen{opacity:.72;}
.cxcell.unseen:hover{opacity:1;}
/* ---- FPS counter (bottom-left, above the HUD bar) ---- */
#fps{position:absolute;left:10px;bottom:calc(206px + env(safe-area-inset-bottom,0px));
  font:700 13px ui-monospace,Menlo,Consolas,monospace;padding:2px 8px;border-radius:5px;
  background:rgba(0,0,0,0.55);z-index:16;pointer-events:none;letter-spacing:.5px;}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){ #fps{bottom:calc(176px + env(safe-area-inset-bottom,0px));font-size:12px;} }
/* item<->slot wayfinding: blink the equip slot an item belongs to; green-mark the
   inventory items that fit a hovered/tapped slot. Works for mouse hover AND touch. */
.slot.hlblink{animation:slotBlink .75s ease-in-out infinite;z-index:2;}
@keyframes slotBlink{0%,100%{box-shadow:0 0 0 2px #e8c74a inset,0 0 6px rgba(232,199,74,.5);}
  50%{box-shadow:0 0 0 3px #ffe9a0 inset,0 0 16px rgba(255,233,160,.95);}}
.slot.hlfit{box-shadow:0 0 0 2px #5ad06a inset,0 0 11px rgba(90,208,106,.65);z-index:2;}
.slot.hldim{opacity:.32;}
/* offhand slot while a two-handed weapon is equipped: inert, greyed, padlocked */
.slot.locked{opacity:.4;filter:grayscale(1);cursor:not-allowed;border-style:dashed;background:var(--panel);}
.slot.locked .sl{color:#7a7266;}
/* Inventory — everything visible at once, NEVER scrolls (PC or mobile). Equipment sits
   in a 2-wide column beside the backpack grid so all cells fit in ~5 rows. */
/* ⚠ THE TWO-COLUMN GRID MOVED DOWN A LEVEL (v4.87). It used to live on #invPanel itself,
   laying out the doll and the backpack as panel areas — so wrapping them in .invwrap put
   both of them inside ONE cell and collapsed the backpack to zero width. The panel is now
   simply header + body, and the equip/inv/mat areas belong to .invmain, where they always
   described the same thing. */
/* ⚠ THE STRIP NEEDS ITS OWN AREA, AND THIS IS WHY IT KEPT APPEARING AT THE BOTTOM. This panel is
   a GRID with exactly two named areas, head and body. An element with no grid-area is
   auto-placed into an implicit row AFTER them — so .heronav landed under the whole inventory no
   matter where it sat in the DOM, which is why moving it in the markup changed nothing and
   making it sticky changed nothing.
   Found from the owner's DevTools screenshot: the element inspector showed it correctly as the
   second child while the page drew it last, which is a sentence that only makes sense about a
   grid. Two guesses at the cause before that, both wrong, both shipped. */
#invPanel{overflow:hidden;display:grid;grid-template-columns:1fr;
  grid-template-rows:auto auto 1fr;grid-template-areas:"head" "nav" "body";align-content:start;}
#invPanel h2{grid-area:head;}
#invPanel > .heronav{grid-area:nav;}
#invPanel .invwrap{grid-area:body;min-width:0;}
#invPanel .invmain{display:grid;grid-template-columns:auto 1fr;
  grid-template-rows:auto auto;grid-template-areas:"equip inv" "mat mat";
  column-gap:18px;align-content:start;}
#invPanel #equipGrid{grid-area:equip;align-content:start;margin:0;justify-self:start;}
#invPanel #invGrid{grid-area:inv;align-content:start;}
#invPanel #matline{grid-area:mat;}
#invPanel .slot .sl{color:#cabfa8;}
@media (min-width:821px) and (min-height:521px){
  /* Full screen like every other panel, but the GRID must not stretch across a 27-inch
     monitor — eight backpack columns at 1400px would be absurd cells. Rather than cap
     the grid (which would fight the "head/equip/inv" areas), --pad grows to swallow the
     surplus width, so the content stays a ~900px measure while the panel itself covers
     the screen. The sticky h2 keys off the same variable, so it still bleeds edge to edge. */
  #invPanel{--pad:max(clamp(14px,5vw,60px),calc((100vw - 900px) / 2));
    left:0;right:0;top:0;bottom:0;transform:none;
    width:auto;height:auto;max-height:none;padding:22px var(--pad) 14px;
    /* the base rule clips (overflow:hidden) to keep the "everything visible at once"
       promise; full-screen it very nearly always fits, but a short laptop viewport plus
       the salvage bar can still run over — scrolling beats silently cutting it off */
    overflow-y:auto;}
  #invPanel h2{font-size:21px;margin-bottom:16px;}
  #invPanel .invmain{grid-template-columns:182px 1fr;column-gap:24px;}
  #invPanel #equipGrid{grid-template-columns:repeat(2,86px);gap:10px;}
  /* ⚠ `1fr` IS `minmax(auto, 1fr)` AND `auto` HAS A MIN-CONTENT FLOOR (found v5.09). That
     floor is the slot's own icon, so on a narrow-enough measure the eight columns REFUSED
     to shrink and the grid overflowed to the right — under the character column, which is
     what was reported twice as "Character is over the inventory" and what I could not
     reproduce at the widths I happened to test. This file already knew the answer: the
     stash grids use minmax(0,1fr) for exactly this reason. */
  #invPanel #invGrid{grid-template-columns:repeat(8,minmax(0,1fr));gap:10px;}
  #invPanel .slot{font-size:30px;border-radius:4px;}
  #invPanel #equipGrid .slot{padding-bottom:13px;}      /* room for the label under the icon */
  #invPanel .slot .sl{font-size:11px;bottom:3px;letter-spacing:.4px;}
  #invPanel #matline{font-size:13px;margin-top:16px;}
}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){
  /* phones: stack equipment ABOVE the backpack and shrink the grids so the WHOLE
     inventory — including Mass/Auto-salvage at the bottom — fits with NO scrolling
     (inventory never scrolls by design; side-by-side crushed backpack slots) */
  #invPanel{display:block;padding:10px;}
  /* ⚠ THE PHONE RULE SAID display:block ON THE PANEL, AND THE GRID MOVED (v4.87). Since
     v4.87 the two columns live on .invmain, so blocking only the panel left the doll and
     the backpack side by side on a 386px screen: slots came out 22px — half the 44px touch
     target this project holds itself to — and the panel scrolled sideways. Both levels have
     to unstack, and the sheet column comes last because it is the part you scroll TO. */
  #invPanel .invmain{display:block;}
  #invPanel .invwrap{display:block;}
  #invPanel .invside{margin-top:14px;}
  #invPanel .phint{display:none;}
  /* The panel header bleeds to the edge with a negative margin of -1 × --pad, but this
     rule shrinks the inventory's padding to 10px without moving --pad off 14px — so the
     header stuck 4px past both edges and the phone could scroll the panel sideways.
     Stated here rather than by changing --pad, because --pad also drives the bottom
     padding and the tighter 10px is deliberate: the inventory must fit with no scroll. */
  #invPanel h2{margin:-10px -10px 8px;}
  #invPanel #equipGrid{grid-template-columns:repeat(6,minmax(0,1fr));gap:4px;margin-bottom:8px;max-width:none;}
  #invPanel #invGrid{grid-template-columns:repeat(10,minmax(0,1fr));gap:4px;}
  #invPanel .slot{font-size:16px;}
  #invPanel #equipGrid .slot{padding-bottom:8px;}
  #invPanel .slot .sl{font-size:6px;bottom:1px;letter-spacing:0;}
  #invPanel #matline{font-size:11px;margin-top:6px;}
  #salvbar .salvrow{margin-top:5px;gap:4px;font-size:11px;}
  #salvbar .salvnote{font-size:9px;}
}

/* Shared by the character sheet and the Account page (40-account-stats.js): both are a
   column of "label ......... value" rows under headings, and they should read as the same
   kind of document. Extended here rather than duplicated, so the two cannot drift apart. */
#charStats .srow,#invStats .srow,#statsPanel .srow{display:flex;justify-content:space-between;gap:16px;padding:4px 2px;font-size:13px;
  border-bottom:1px solid #241d33;font-family:Verdana,sans-serif;}
#charStats .srow[title],#invStats .srow[title],#statsPanel .srow[title]{cursor:help;}
#charStats .srow[title] span:first-child,#invStats .srow[title] span:first-child,#statsPanel .srow[title] span:first-child{border-bottom:1px dotted #4d4168;}
#charStats .srow span:last-child,#invStats .srow span:last-child,#statsPanel .srow span:last-child{color:var(--gold);text-align:right;white-space:nowrap;}
#charStats .shead,#invStats .shead,#statsPanel .shead{margin:12px 0 4px;color:var(--ember);letter-spacing:2px;font-size:13px;font-family:Georgia,serif;}
/* A caption row: it labels the rows under it rather than stating a value of its own. */
#statsPanel .srow.shint span{color:var(--dim);font-size:12px;white-space:normal;}
#statsPanel .srow small{color:var(--dim);font-size:12px;margin-left:6px;}
/* The Account page is read, not scanned mid-fight — the character sheet's 13px is sized to
   fit a full stat block on a phone during a run, and this page has no such pressure. */
#statsPanel .srow{font-size:15px;padding:6px 2px;}
#statsPanel .shead{font-size:16px;margin:18px 0 6px;}
#statsPanel h2{font-size:24px;}

.skrow{display:flex;align-items:center;gap:10px;padding:9px 6px;border-bottom:1px solid #241d33;}
.skrow .ic{font-size:24px;width:34px;text-align:center;}
.skrow .nm{flex:1;}
.skrow .nm b{font-weight:normal;letter-spacing:1px;}
.skrow .nm .d{display:block;font-size:11px;color:var(--dim);font-family:Verdana,sans-serif;margin-top:2px;}
.skrow .lv{font-size:12px;color:var(--gold);font-family:Verdana,sans-serif;white-space:nowrap;}
.plus{width:26px;height:26px;background:var(--panel2);border:1px solid var(--ember);color:var(--ember);
  font-size:16px;cursor:pointer;line-height:1;}
.plus:disabled{opacity:.25;cursor:default;border-color:var(--line);color:var(--dim);}
.sklocked{opacity:.45;}

/* six branches since v3.47, so the column count is derived rather than typed. The
   panel is full-screen now, so it fits three on a phone and six on a monitor. */
/* Sized for the FULL-SCREEN panel. 11px node text was set when this lived in a 340px
   rail; on a monitor, in six columns of 220px, it read as fine print. Same defect the
   town labels had — a size chosen for a small box, never revisited when the box grew. */
#passiveTree{display:grid;grid-template-columns:repeat(auto-fit,minmax(182px,1fr));gap:14px;}
.branch h3{font-weight:normal;letter-spacing:2px;font-size:18px;color:var(--ink);
  text-align:center;margin-bottom:10px;}
.pnode{position:relative;background:var(--panel2);border:1px solid var(--line);padding:11px 8px;margin-bottom:9px;
  font-size:14px;text-align:center;cursor:pointer;font-family:Verdana,sans-serif;line-height:1.45;}
.pnode .pr{display:block;color:var(--gold);font-size:12.5px;margin-top:4px;}
.pnode.keystone{font-size:13px;}
.pnode.can{border-color:var(--ember);}
.pnode.maxed{border-color:var(--gold);}
.pnode.locked{opacity:.35;cursor:default;}
.pnode.keystone{background:#241333;border-color:#6b4a8f;}
.pnode.keystone.owned{border-color:var(--gold);box-shadow:0 0 10px rgba(232,199,74,.3);}

/* ---------- item action menu (tap/click an item) ---------- */
#itemMenu{position:fixed;left:50%;bottom:220px;transform:translateX(-50%);width:min(340px,92vw);
  background:rgba(20,15,29,.98);border:1px solid var(--ember);z-index:60;padding:12px;
  box-shadow:0 0 40px #000;pointer-events:auto;}
#itemMenu .imtip{font-size:12px;font-family:Verdana,sans-serif;line-height:1.5;color:var(--ink);
  text-align:left;margin-bottom:10px;max-height:38vh;overflow-y:auto;}
#itemMenu .imbtns{display:flex;flex-wrap:wrap;gap:8px;}
.imbtn{flex:1;min-width:90px;padding:12px 8px;background:var(--panel2);border:1px solid var(--line);
  color:var(--ink);font-family:Verdana,sans-serif;font-size:13px;cursor:pointer;}
.imbtn:hover,.imbtn:active{border-color:var(--ember);color:var(--ember);}
.imbtn.sell{border-color:#8a7a3a;} .imbtn.sell b{color:var(--gold);}
.imbtn.salv{border-color:#3a5a7a;} .imbtn.salv b{color:#7aa8d0;}
.imbtn.close{flex:0 0 100%;background:none;border-color:#443a55;color:var(--dim);padding:8px;}

/* ---------- card draft ---------- */
#cardOverlay{z-index:50;background:radial-gradient(ellipse at 50% 40%,rgba(25,17,34,.94),rgba(8,6,12,.97));}
#cardTitle{color:var(--gold);letter-spacing:3px;font-size:22px;font-weight:normal;margin-bottom:22px;text-align:center;}
#cardChoices{display:flex;gap:18px;flex-wrap:wrap;justify-content:center;}
#cardReroll{margin-top:24px;display:flex;align-items:center;gap:14px;justify-content:center;}
#cardReroll .cgbtn{background:var(--panel2);border:1px solid var(--gold);color:var(--gold);
  padding:11px 26px;letter-spacing:2px;font-size:14px;cursor:pointer;border-radius:2px;transition:background .12s;}
#cardReroll .cgbtn:hover:not(:disabled){background:#2a2140;}
#cardReroll .cgbtn:disabled{opacity:.4;cursor:default;border-color:var(--line);color:var(--dim);}
#cardReroll .rrhint{color:var(--dim);font-size:11px;font-family:Verdana,sans-serif;letter-spacing:.5px;}
/* on-a-roll escalation offer + HUD indicator */
#rollOverlay{z-index:52;background:radial-gradient(ellipse at 50% 40%,rgba(40,14,14,.95),rgba(8,6,10,.98));}
.rollbox{max-width:640px;text-align:center;padding:0 20px;}
.rollbox h2{color:#f0a83c;letter-spacing:4px;font-size:30px;font-weight:normal;margin-bottom:14px;}
.rollbox p{color:var(--ink);font-size:15px;line-height:1.6;margin-bottom:24px;}
.rollbtns{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;}
.rollbtn{min-width:120px;padding:16px 14px;background:linear-gradient(180deg,#2a1414,#1a0e0e);
  border:2px solid var(--blood);color:#f0c048;font-size:20px;letter-spacing:1px;cursor:pointer;
  display:flex;flex-direction:column;align-items:center;gap:6px;transition:transform .12s,box-shadow .12s;border-radius:3px;}
.rollbtn small{color:var(--dim);font-size:11px;font-family:Verdana,sans-serif;letter-spacing:.3px;}
.rollbtn:hover{transform:translateY(-4px);box-shadow:0 0 16px rgba(165,58,46,.6);}
.rollbtn.decline{border-color:var(--line);color:var(--dim);background:linear-gradient(180deg,#1c1826,#12101a);}
.rollnote{display:block;margin-top:22px;color:var(--dim);font-size:12px;font-family:Verdana,sans-serif;
  line-height:1.5;font-style:italic;}
#onroll{position:absolute;top:10px;left:50%;transform:translateX(-50%);color:#f0a83c;
  font-size:16px;letter-spacing:2px;text-shadow:0 0 8px rgba(240,64,46,.7);pointer-events:none;
  font-family:Verdana,sans-serif;font-weight:bold;}
/* Features panel — systems overview / onboarding */
#featuresBody{display:grid;grid-template-columns:1fr 1fr;gap:15px;overflow-y:auto;max-height:72vh;padding-right:6px;}
.featsec{background:var(--panel2);border:1px solid var(--line);border-radius:4px;padding:14px 16px;}
.featsec h3{color:var(--gold);font-size:15px;font-weight:normal;letter-spacing:1px;margin-bottom:9px;}
.featsec p,.featsec li{color:var(--ink);font-size:12.5px;line-height:1.55;font-family:Verdana,sans-serif;}
.featsec p{margin-bottom:8px;}
.featsec p:last-child,.featsec ul:last-child{margin-bottom:0;}
.featsec ul{margin:0 0 4px;padding-left:18px;}
.featsec li{margin-bottom:5px;}
.featsec b{color:#e9dcc4;}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){ #featuresBody{grid-template-columns:1fr;max-height:66vh;} }
#cardHelp{max-width:660px;margin-top:20px;font-family:Verdana,sans-serif;font-size:11px;line-height:1.65;
  color:var(--dim);background:rgba(20,15,29,.7);border:1px solid var(--line);border-radius:4px;
  padding:10px 14px;text-align:left;}
#cardHelp b{color:var(--ember);font-weight:normal;}
/* Card draft: what you already own (20-cards.js cardOwned).
   `.cown` is the rank badge, top-left, opposite the number key. `.have` pulses a card you
   already hold so a familiar pick reads before the text does; `.maxed` deliberately does
   NOT pulse — a rank-10 card cannot go higher, so drawing the eye to it would be a lie. */
.cown{position:absolute;top:6px;left:24px;z-index:2;font:700 11px Verdana,sans-serif;
  padding:1px 6px;border-radius:9px;background:rgba(0,0,0,.5);border:1px solid #4a3f5c;
  color:#c9bfae;letter-spacing:.02em}
.cown.max{color:#ffd75e;border-color:#8a6b1f;background:rgba(60,44,8,.6)}
.card.have{animation:cardHave 1.5s ease-in-out infinite}
@keyframes cardHave{
  0%,100%{box-shadow:0 0 0 0 rgba(200,150,255,0)}
  50%    {box-shadow:0 0 14px 2px rgba(200,150,255,.45)}
}
@media(prefers-reduced-motion:reduce){ .card.have{animation:none;border-color:#c896ff} }

.card{position:relative;width:210px;min-height:250px;background:linear-gradient(180deg,#1c1526,#120d1a);
  border:2px solid var(--line);padding:18px 14px;cursor:pointer;display:flex;flex-direction:column;
  align-items:center;text-align:center;transition:transform .12s,box-shadow .12s;pointer-events:auto;}
.card:hover{transform:translateY(-6px);}
.card .cnum{position:absolute;top:6px;left:9px;font-size:12px;color:var(--dim);font-family:Verdana,sans-serif;}
/* The number is the 1/2/3 keyboard shortcut (25-core.js). It sat at the same corner as
   `.cown` and drew straight over it, so a rank badge read "10/10" instead of "1" + "0/10"
   — the comment above `.cown` already claimed it was "opposite the number key", which it
   never was. `.cown` now starts to the right of the digit; and on a touch screen there is
   no key to press, so the digit goes away entirely and the badge takes the corner back. */
@media(pointer:coarse){
  .card .cnum{display:none}
  .cown{left:8px}
}
.card .cardban{position:absolute;top:4px;right:5px;width:24px;height:24px;padding:0;line-height:22px;
  font-size:12px;text-align:center;background:rgba(40,26,42,.7);border:1px solid #4a3050;border-radius:5px;
  color:#c0507a;cursor:pointer;opacity:.35;transition:opacity .12s,border-color .12s,transform .12s;z-index:3;}
.card .cardban:hover{opacity:1;border-color:#e0402e;transform:scale(1.12);}
.card .cicon{font-size:48px;margin:10px 0 6px;}
.card .crar{font-size:11px;letter-spacing:2px;font-family:Verdana,sans-serif;text-transform:uppercase;margin-bottom:6px;}
.card .ctitle{font-size:18px;letter-spacing:1px;color:var(--ink);margin-bottom:10px;}
.card .cdesc{font-size:12px;color:var(--dim);font-family:Verdana,sans-serif;line-height:1.5;}
.card .cdesc .statwhy{display:block;margin-top:8px;padding-top:7px;border-top:1px dashed #3a3050;
  color:#a396c0;font-style:italic;font-size:11px;}
.card .cdesc .creq{display:block;margin-top:7px;color:#c9a88a;font-size:11px;letter-spacing:.3px;}
.card .cdesc .creq.bad{color:#ff5a4a;font-weight:bold;}
.card .cdesc .crarwhy{display:block;margin-top:7px;padding-top:6px;border-top:1px dashed #3a3050;
  color:#e8c74a;font-size:11px;letter-spacing:.3px;}
.card .cdesc .crarwhy b{color:#f4e04a;font-weight:normal;}
.card .cdesc .cevohint{display:block;margin-top:7px;padding:5px 7px;border-radius:5px;
  background:linear-gradient(90deg,rgba(255,154,60,.16),rgba(255,154,60,.04));
  color:#ff9a3c;font-size:11px;font-weight:bold;letter-spacing:.3px;
  border:1px solid rgba(255,154,60,.4);animation:evopulse 1.4s ease-in-out infinite;}
@keyframes evopulse{0%,100%{box-shadow:0 0 4px rgba(255,154,60,.25);}50%{box-shadow:0 0 12px rgba(255,154,60,.55);}}
.card.r0{border-color:#6a6458;}
.card.r1{border-color:#5f86d9;box-shadow:0 0 16px rgba(95,134,217,.3);}
.card.r2{border-color:#b45fe0;box-shadow:0 0 22px rgba(180,95,224,.4);}
.card.r3{border-color:#e8c74a;box-shadow:0 0 24px rgba(232,199,74,.42);}
.card.r4{border-color:#e0402e;box-shadow:0 0 32px rgba(224,64,46,.55);}
.card.r0:hover{box-shadow:0 0 14px rgba(160,160,160,.3);}
.card.r1:hover{box-shadow:0 0 24px rgba(95,134,217,.5);}
.card.r2:hover{box-shadow:0 0 30px rgba(180,95,224,.6);}
.card.r3:hover{box-shadow:0 0 32px rgba(232,199,74,.6);}
.card.r4:hover{box-shadow:0 0 42px rgba(224,64,46,.75);}
.cardhint{margin-top:22px;color:var(--dim);font-size:12px;font-family:Verdana,sans-serif;}

/* ---------- vendor / stash / save ---------- */
.shopgold{font-size:12px;color:var(--dim);font-family:Verdana,sans-serif;margin-bottom:10px;}
.shopgold b{color:var(--gold);}
.shoprow{display:flex;align-items:center;gap:10px;padding:8px 6px;border-bottom:1px solid #241d33;cursor:pointer;}
.shoprow:hover{background:rgba(212,118,60,.08);}
.shoprow .ic{font-size:22px;width:32px;text-align:center;}
.shoprow .nm{flex:1;}
.shoprow .nm b{font-weight:normal;letter-spacing:1px;}
.shoprow .nm .d{display:block;font-size:11px;color:var(--dim);font-family:Verdana,sans-serif;margin-top:2px;}
.shoprow .price{color:var(--gold);font-family:Verdana,sans-serif;font-size:13px;white-space:nowrap;}
.shoprow .price.poor{color:var(--blood);}
.empty{color:var(--dim);font-style:italic;padding:14px 4px;}
/* ⚠ #stashPanel USED TO CAP ITSELF AT 520px (reported 2026-08-03: "the stash looks
   terrible"). Panels went FULL SCREEN in the GUI pass, and `.panel` sets width:auto with
   left/right:0 — but this one rule still won, so the Stash was a 520px column inside a
   full-screen backdrop: the header hint wrapped one word per line, the tab strip stacked
   vertically instead of wrapping, and ten grid columns were squeezed to a few pixels each.
   The cap is gone; the grids are held to a sane SLOT SIZE instead, because ten columns of
   1fr across a 1180px measure would be 114px slots, which is the same bug the other way. */
.stashcol{margin-bottom:12px;}
.stashcol h3{font-weight:normal;letter-spacing:2px;font-size:13px;color:var(--ember);margin-bottom:6px;}
#stashGrid,#stashInv{display:grid;grid-template-columns:repeat(10,minmax(0,54px));justify-content:start;
  gap:4px;border-radius:5px;transition:box-shadow .1s;}
/* stash tabs: switchable pages of the shared vault, unlocked with gold */
#stashTabs{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:6px;}
.stab{min-width:26px;padding:3px 8px;font:inherit;font-size:12px;line-height:1;cursor:pointer;
  color:#b9b3a6;background:#241d29;border:1px solid #3a3040;border-radius:4px;transition:background .12s,color .12s,box-shadow .12s;}
.stab:hover{background:#2f2636;color:#e8e0d4;}
.stab.active{color:#1a1420;background:var(--ember);border-color:var(--ember);font-weight:bold;}
.stab.buy{color:#e8c74a;border-color:#6b5a2a;}
.stab.buy:hover{background:#3a3020;}
.stab.locked{opacity:.4;cursor:default;}
.stab.hasitems{animation:stabPulse 1.4s ease-in-out infinite;}
@keyframes stabPulse{0%,100%{box-shadow:0 0 0 0 rgba(232,199,74,0);border-color:#3a3040;}
  50%{box-shadow:0 0 7px 1px rgba(232,199,74,.55);border-color:#e8c74a;}}
/* drag & drop: draggable slots suppress touch-scroll; the active drop target glows green */
#stashGrid .slot.draggable,#stashInv .slot.draggable{touch-action:none;cursor:grab;}
#stashGrid.dropok,#stashInv.dropok{box-shadow:0 0 0 2px #5ad06a,0 0 14px rgba(90,208,106,.6);}
.dragGhost{position:fixed;transform:translate(-50%,-50%);z-index:100000;pointer-events:none;
  font-size:30px;filter:drop-shadow(0 2px 4px rgba(0,0,0,.8));opacity:.9;}
.savehint{font-size:12px;color:var(--dim);font-family:Verdana,sans-serif;line-height:1.5;margin-bottom:10px;}
#saveCode{width:100%;height:150px;background:#0c0812;color:var(--ink);border:1px solid var(--line);
  font-family:monospace;font-size:11px;padding:8px;resize:none;user-select:text;word-break:break-all;}
.savebtns{display:flex;gap:8px;margin-top:10px;}
.savebtns button,.loadbtn{background:var(--panel2);border:1px solid var(--ember);color:var(--ember);
  font-family:inherit;font-size:13px;letter-spacing:1px;padding:8px 14px;cursor:pointer;pointer-events:auto;}
.savebtns button:hover,.loadbtn:hover{background:var(--ember);color:#140b0b;}
.loadbtn{margin-top:22px;}
/* ---------- release log (main screen, collapsible) ---------- */
#releaseLog{margin-top:30px;width:min(560px,94vw);text-align:left;font-family:Verdana,sans-serif;
  background:rgba(12,10,14,.75);border-radius:8px;padding:2px 12px;}   /* 75% backing so text stays readable over the flames */
#releaseLog .rlhead{cursor:pointer;color:var(--dim);font-size:12px;letter-spacing:1.5px;text-transform:uppercase;
  display:flex;align-items:center;gap:8px;justify-content:center;padding:9px;border-top:1px solid var(--line);}
#releaseLog .rlhead:hover{color:var(--ember);}
#releaseLog .rlarrow{transition:transform .2s;display:inline-block;}
#releaseLog.open .rlarrow{transform:rotate(90deg);}
#releaseLog .rlbody{display:none;margin-top:10px;max-height:min(300px,40vh);overflow-y:auto;padding:0 6px;}
#releaseLog.open .rlbody{display:block;}
#releaseLog .rel{margin-bottom:14px;padding-bottom:12px;border-bottom:1px solid #241d33;}
#releaseLog .rel h4{color:var(--ink);font-size:13px;font-weight:normal;margin:0 0 2px;}
#releaseLog .rel .rlmeta{color:var(--ember);font-size:11px;margin-bottom:6px;}
#releaseLog .rel ul{list-style:none;padding:0;margin:0;}
#releaseLog .rel li{color:var(--dim);font-size:12px;line-height:1.5;padding-left:15px;position:relative;}
#releaseLog .rel li:before{content:'\25B9';position:absolute;left:0;color:var(--ember);}
/* ---------- bug / feedback report modal ---------- */
#bugModal{position:fixed;inset:0;z-index:60;display:none;align-items:center;justify-content:center;
  background:rgba(6,4,10,.72);padding:16px;}
#bugModal.open{display:flex;}
#bugModal .bmbox{background:var(--panel);border:1px solid var(--line);border-radius:6px;
  width:min(440px,96vw);max-height:92vh;overflow-y:auto;padding:18px;box-shadow:0 0 50px #000;text-align:left;}
#bugModal h3{color:var(--ember);font-weight:normal;letter-spacing:2px;margin:0 0 4px;font-size:18px;}
#bugModal .bmsub{color:var(--dim);font-size:11px;font-family:Verdana,sans-serif;margin-bottom:12px;line-height:1.5;}
#bugModal img.bmshot{width:100%;border:1px solid var(--line);border-radius:4px;margin-bottom:10px;display:block;}
#bugModal textarea{width:100%;min-height:96px;background:var(--panel2);border:1px solid var(--line);
  color:var(--ink);font-family:Verdana,sans-serif;font-size:13px;padding:9px;border-radius:4px;resize:vertical;}
#bugModal label.bmchk{display:flex;align-items:center;gap:8px;color:var(--dim);font-size:12px;
  font-family:Verdana,sans-serif;margin:10px 0;cursor:pointer;}
#bugModal .bmrow{display:flex;gap:10px;justify-content:flex-end;margin-top:6px;}
#bugModal button{background:var(--panel2);border:1px solid var(--ember);color:var(--ember);
  font-family:inherit;letter-spacing:1px;padding:9px 16px;border-radius:4px;cursor:pointer;font-size:14px;}
#bugModal button.ghost{border-color:var(--line);color:var(--dim);}
/* ---------- options panel rows ---------- */
#optionsPanel #optRows{display:flex;flex-direction:column;}
.optrow{display:flex;align-items:center;gap:10px;width:100%;background:var(--panel2);border:1px solid var(--line);
  color:var(--ink);font-family:inherit;font-size:14px;padding:12px;margin-bottom:8px;border-radius:5px;cursor:pointer;text-align:left;}
.optrow:hover{border-color:var(--ember);color:var(--ember);}
.optrow .oi{font-size:17px;width:22px;text-align:center;flex:none;align-self:flex-start;margin-top:1px;}
.optrow .optbody{display:flex;flex-direction:column;gap:3px;min-width:0;}
.optrow .subhint{font-size:10px;line-height:1.4;color:#8d8398;font-weight:400;white-space:normal;}
.optrow:hover .subhint{color:#a89ba8;}
.optsec{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:#8d8398;font-weight:700;margin:12px 2px 6px;}
.optsec:first-child{margin-top:2px;}
.optnote{font-size:11px;line-height:1.5;color:#9a90a6;margin:-2px 2px 9px;}
/* ---------- account / cloud / leaderboard (ADDITIVE — offline-safe) ---------- */
#acctBar{margin-top:20px;font-family:Verdana,sans-serif;font-size:12px;color:var(--dim);
  display:flex;flex-direction:column;align-items:center;gap:6px;max-width:440px;width:min(440px,92vw);}
#acctBar .cgbtn{background:var(--panel2);border:1px solid var(--ember);color:var(--ember);
  font-family:inherit;font-size:12px;letter-spacing:1px;padding:7px 14px;cursor:pointer;pointer-events:auto;}
#acctBar .cgbtn:hover{background:var(--ember);color:#140b0b;}
#acctBar .cgbtn.ghost{border-color:var(--line);color:var(--dim);}
#acctBar .cgbtn.ghost:hover{background:var(--panel2);color:var(--ink);border-color:var(--ember);}
/* The reroll die next to the wanderer name — a nudge, not a control that competes with Log in. */
#acctBar .cgbtn.mini{padding:1px 6px;font-size:11px;line-height:1.4;margin-left:4px;vertical-align:middle;}
#acctBar .row{display:flex;gap:8px;align-items:center;flex-wrap:wrap;justify-content:center;}
#acctBar .who{color:var(--gold);}
#cgTeleLine{margin-top:14px;font-family:Verdana,sans-serif;font-size:11px;color:#6a6478;
  display:flex;gap:8px;align-items:center;justify-content:center;flex-wrap:wrap;max-width:440px;}
#cgTeleLine a{color:var(--dim);cursor:pointer;text-decoration:underline;pointer-events:auto;}
.cgmodal{position:fixed;inset:0;z-index:60;display:flex;align-items:center;justify-content:center;
  background:rgba(6,4,10,.82);padding:18px;overflow-y:auto;}
.cgmodal .box{background:var(--panel);border:1px solid var(--line);box-shadow:0 0 50px #000;
  padding:22px;width:min(400px,94vw);text-align:left;}
.cgmodal h2{font-weight:normal;letter-spacing:3px;font-size:18px;color:var(--ember);margin-bottom:6px;}
.cgmodal .cgnote{font-family:Verdana,sans-serif;font-size:11px;color:var(--dim);line-height:1.55;margin:8px 0 14px;}
.cgmodal .cgwarn{color:#e0a54a;}
.cgmodal input{width:100%;background:#0c0812;color:var(--ink);border:1px solid var(--line);
  font-family:Verdana,sans-serif;font-size:14px;padding:9px 10px;margin:6px 0;user-select:text;}
.cgmodal input:focus{outline:1px solid var(--ember);}
.cgmodal .cgrow{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap;}
.cgmodal .cgbtn{flex:1;min-width:110px;background:var(--panel2);border:1px solid var(--ember);color:var(--ember);
  font-family:inherit;font-size:13px;letter-spacing:1px;padding:9px 12px;cursor:pointer;}
.cgmodal .cgbtn:hover{background:var(--ember);color:#140b0b;}
.cgmodal .cgbtn.ghost{border-color:var(--line);color:var(--dim);flex:0 0 auto;min-width:0;}
.cgmodal .cgbtn.ghost:hover{background:var(--panel2);color:var(--ink);}
.cgmodal .cgerr{color:var(--blood);font-family:Verdana,sans-serif;font-size:12px;min-height:16px;margin-top:8px;}
.cgslot{display:flex;align-items:center;gap:8px;padding:9px 6px;border-bottom:1px solid #241d33;
  font-family:Verdana,sans-serif;font-size:12px;}
.cgslot .meta{flex:1;color:var(--ink);}
.cgslot .meta small{color:var(--dim);display:block;font-size:10px;margin-top:2px;}
.cgslot .cgbtn{flex:0 0 auto;min-width:0;padding:6px 10px;font-size:11px;}
.cgslot.bound{background:rgba(212,118,60,.08);}
#cloudSection{margin-top:16px;border-top:1px solid var(--line);padding-top:12px;}
#cloudSection h3{color:var(--ember);letter-spacing:2px;font-size:13px;font-weight:normal;margin-bottom:6px;}
#cloudSection .cgmuted{font-family:Verdana,sans-serif;font-size:11px;color:var(--dim);line-height:1.5;}
/* leaderboard panel */
#lbTop{font-family:Verdana,sans-serif;font-size:11px;color:var(--dim);margin-bottom:8px;line-height:1.5;}
#lbTop b{color:var(--gold);}
.lbtabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:8px;}
.lbtab{background:none;border:1px solid var(--line);color:var(--dim);font-family:inherit;font-size:12px;
  letter-spacing:1px;padding:5px 9px;cursor:pointer;}
.lbtab.on{color:var(--ember);border-color:var(--ember);}
#lbClsSel{background:#0c0812;color:var(--ink);border:1px solid var(--line);font-family:Verdana,sans-serif;
  font-size:12px;padding:5px 6px;margin-bottom:10px;width:100%;user-select:text;}
#lbList{font-family:Verdana,sans-serif;font-size:12px;}
/* ⚠ COLUMNS, NOT A ROW OF THINGS (v5.02). Reported: "people say it is not clear at first
   glance." It was a flex row with the class right-aligned hard against the score, so the
   name and the class ran together and nothing said which number was which. A grid with one
   template, shared by the header and every row, makes them line up by construction rather
   than by each cell happening to be the same width. */
.lbrow{display:grid;grid-template-columns:30px minmax(0,1fr) 130px 22px 92px;
  align-items:center;gap:10px;padding:6px 4px;border-bottom:1px solid #241d33;}
.lbhead{color:var(--ember);font-size:11px;letter-spacing:2px;text-transform:uppercase;
  border-bottom:1px solid var(--line);padding-bottom:8px;margin-bottom:2px;}
.lbhead .vl,.lbrow .vl{text-align:right;}
.lbrow .rk{text-align:right;color:var(--dim);}
.lbrow .nm{color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.lbrow .cl{color:var(--dim);font-size:11px;text-align:left;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.lbrow .cl .ci{font-style:normal;margin-right:4px;}
.lbrow .cl b{font-weight:400;}
/* ⚠ THE WORKING IS A CLICK, NOT A HOVER (2026-08-11). It was a native `title` and was reported
   missing twice while being perfectly present: a tooltip waits about a second on a motionless
   cursor, cannot be styled, and ON A PHONE DOES NOTHING AT ALL. A row that answers "where did
   this number come from" has to look like something you can press. */
.lbrow.hasWhy{cursor:pointer;}
.lbrow.hasWhy:hover{background:#1d1729;}
.lbrow.hasWhy .vl::after{content:'ⓘ';margin-left:6px;color:var(--dim);font-size:10px;
  vertical-align:2px;}
.lbrow.hasWhy.open .vl::after{content:'▾';color:var(--ember);}
/* pre-line: cgScoreExplain separates the rule from this row's own numbers with blank lines,
   and that shape is the whole readability of it. */
/* ⚠ MONOSPACE, AND THAT IS NOT A STYLE CHOICE. cgWhyTable pads with SPACES so one string can
   serve both this panel and the plain-text tooltip; in a proportional face those columns do not
   line up and the receipt is prose again — which is the exact complaint this replaced. */
.lbwhy{white-space:pre-line;color:var(--dim);font-size:11.5px;line-height:1.55;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  padding:8px 10px 10px 34px;border-bottom:1px solid #241d33;background:#17121f;}
/* the rule paragraph above the numbers is prose and stays readable as prose */
.lbwhy{tab-size:2;}
@media (max-width:560px){ .lbwhy{padding-left:12px;font-size:11px;} }
/* Phone: the icon alone carries the class. Eleven characters of "Chronomancer" beside a
   name, a rank and a score does not fit 390px, and the name is the row's subject. */
@media (max-width:560px){
  .lbrow{grid-template-columns:24px minmax(0,1fr) 34px 18px 74px;gap:6px;}
  .lbrow .cl b{display:none;}
  .lbrow .cl .ci{margin-right:0;font-size:14px;}
}
.lbrow .vl{color:var(--gold);width:64px;text-align:right;}
.lbrow.me{background:rgba(232,199,74,.12);}
.lbrow.me .nm{color:var(--gold);}
.lbempty{color:var(--dim);font-family:Verdana,sans-serif;font-size:12px;padding:10px 2px;}
#matline,#matline2{font-size:11px;color:var(--dim);font-family:Verdana,sans-serif;margin:10px 0;line-height:1.7;}
#matline b,#matline2 b{color:#7aa8d0;}
.forgerow{display:flex;align-items:center;gap:10px;padding:7px 6px;border-bottom:1px solid #241d33;}
.forgerow .ic{font-size:20px;width:30px;text-align:center;}
.forgerow .nm{flex:1;}
.forgerow .nm b{font-weight:normal;letter-spacing:1px;}
.forgerow .nm .d{display:block;font-size:10px;color:var(--dim);font-family:Verdana,sans-serif;margin-top:2px;}
.powrow{display:flex;align-items:center;gap:10px;padding:7px 6px;border-bottom:1px solid #241d33;}
.powrow .ic{font-size:20px;width:28px;text-align:center;}
.powrow .nm{flex:1;}
.powrow .nm b{font-weight:normal;letter-spacing:1px;}
.powrow .bar{display:block;height:6px;background:#221a30;border:1px solid var(--line);margin-top:5px;}
.powrow .bar i{display:block;height:100%;background:linear-gradient(90deg,#8a6bd4,#e8c74a);}
.powrow .lv{font-size:11px;color:var(--gold);font-family:Verdana,sans-serif;white-space:nowrap;}
.powrow.maxed .lv{color:#ff9a3c;}
.powrow.fused{background:rgba(255,154,60,.06);}
.powrow.fused .nm .d{display:block;font-size:10px;color:#ff9a3c;font-family:Verdana,sans-serif;}
#fuseTray{margin-top:14px;border-top:1px solid var(--line);padding-top:10px;}
/* The merge instructions are the one thing on this panel a player has to READ, and they
   were set smaller than the skill rows they explain (12px / 10.5px against 13px+). */
.fusehdr{font-size:15px;color:var(--ember);letter-spacing:1px;margin-bottom:10px;line-height:1.45;}
.fusebtn{display:block;width:100%;text-align:left;background:var(--panel2);border:1px solid var(--line);
  color:var(--ink);font-family:Verdana,sans-serif;font-size:12px;padding:7px 10px;margin-bottom:6px;cursor:pointer;pointer-events:auto;}
.fusebtn:hover{border-color:var(--ember);}
.fusebtn.sel{border-color:#ff9a3c;box-shadow:0 0 8px rgba(255,154,60,.5);color:#ff9a3c;}
.fusehdr .fusesub{display:block;margin-top:5px;font-size:13px;letter-spacing:.2px;color:#c48a4a;
  text-transform:none;font-weight:normal;line-height:1.45;}
.fusehdr .fusesub b{color:#ff9a3c;font-weight:bold;}
.fusebtn.attuned{border-color:#ffb055;color:#ffcf8a;
  background:linear-gradient(90deg,rgba(255,154,60,.14),transparent);}
.fusebtn.go.attuned{background:linear-gradient(90deg,rgba(255,154,60,.28),rgba(255,154,60,.08));
  box-shadow:0 0 12px rgba(255,154,60,.5);}

/* ---------- tooltip ---------- */
#tooltip{position:fixed;z-index:60;max-width:260px;background:rgba(12,8,18,.97);border:1px solid var(--line);
  padding:10px 12px;font-size:12px;pointer-events:none;font-family:Verdana,sans-serif;line-height:1.5;}
:is(#tooltip, #itemMenu .imtip) .tn{font-family:Georgia,serif;font-size:14px;letter-spacing:1px;margin-bottom:4px;display:block;}
:is(#tooltip, #itemMenu .imtip) .tb{color:var(--dim);display:block;}
:is(#tooltip, #itemMenu .imtip) .ta{color:#9fb4e8;display:block;}
:is(#tooltip, #itemMenu .imtip) .tv{color:var(--gold);display:block;margin-top:5px;}
:is(#tooltip, #itemMenu .imtip) .tu{color:#ff9a3c;display:block;margin-top:2px;text-shadow:0 0 6px rgba(255,154,60,.5);}
:is(#tooltip, #itemMenu .imtip) .tf{color:var(--dim);font-style:italic;display:block;margin-top:5px;line-height:1.4;}
:is(#tooltip, #itemMenu .imtip) .ta.dim{opacity:.6;}
:is(#tooltip, #itemMenu .imtip) .tah{color:#7a7288;font-style:italic;font-size:10px;margin-left:7px;}
:is(#tooltip, #itemMenu .imtip) .tuh{color:#c9a88a;display:block;font-size:11px;margin:0 0 3px 12px;line-height:1.4;}
/* "Found, not made" (23-panels.js). Muted and boxed rather than red: it is not a warning
   about the item, it is the rule the item is obeying — and it has to be readable in one
   glance next to the rarity line it explains. */
:is(#tooltip, #itemMenu .imtip) .tfound{color:#a79ab8;display:block;font-size:11px;line-height:1.4;
  margin:4px 0 3px;padding:4px 7px;border-left:2px solid #6b4ea8;background:rgba(107,78,168,.13);}
:is(#tooltip, #itemMenu .imtip) .tw{color:#e05a4a;display:block;margin-top:3px;}
:is(#tooltip, #itemMenu .imtip) .tk{color:#7cc4f4;display:block;margin-top:4px;font-size:11px;}
.up{color:#5fd070;font-size:11px;} .dn{color:#e05a4a;font-size:11px;} .eqm{color:var(--dim);font-size:11px;}
.r0c{color:#e6e0d4;} .r1c{color:#5f86d9;} .r2c{color:#b45fe0;} .r3c{color:#e8c74a;}
.r4c{color:#e0402e;font-weight:bold;}
.r5c{color:#ff9a3c;font-weight:bold;text-shadow:0 0 8px rgba(255,154,60,.9);}
.rsetc{color:#43d17a;font-weight:bold;text-shadow:0 0 8px rgba(67,209,122,.65);}
:is(#tooltip, #itemMenu .imtip) .tset{color:#43d17a;display:block;margin:5px 0 2px;font-weight:bold;text-shadow:0 0 6px rgba(67,209,122,.45);}
:is(#tooltip, #itemMenu .imtip) .tsetstar{color:#e8c74a;text-shadow:0 0 6px rgba(232,199,74,.5);letter-spacing:1px;}
:is(#tooltip, #itemMenu .imtip) .tsb{color:#6b7a68;display:block;font-size:11px;margin:0 0 1px 10px;line-height:1.35;}
:is(#tooltip, #itemMenu .imtip) .tsb.on{color:#7be08a;}
@keyframes uniqueGlow{0%,100%{box-shadow:0 0 6px rgba(255,154,60,.5);}50%{box-shadow:0 0 16px rgba(255,154,60,.95);}}


/* ---- leaderboard titles + achievement title picker (v2.55) ---- */
.lbrow .ti{font-style:normal;color:var(--ember);font-size:10px;margin-left:6px;letter-spacing:1px;opacity:.9;}
/* The Twitch badge on a board row. Only rows whose perks ask for it ever carry one. */
.lbrow .twb{font-style:normal;font-size:11px;margin-left:5px;opacity:.85;cursor:help;}
.achtitle{background:var(--panel2);border:1px solid var(--line);color:var(--dim);font-family:inherit;
  font-size:10px;letter-spacing:1px;padding:2px 8px;border-radius:4px;cursor:pointer;margin-top:5px;}
.achtitle:hover{border-color:var(--ember);color:var(--ember);}
.achtitle.on{border-color:var(--ember);color:var(--ember);box-shadow:0 0 6px color-mix(in srgb,var(--ember) 45%,transparent);}

/* ---- mobile overrides that MUST sit after the base rules above (equal specificity —
       source order wins; earlier copies inside the main mobile block never applied,
       so phones silently ran the desktop panel layout) ---- */
@media (max-width:820px),(pointer:coarse) and (max-height:520px){
  /* Phones get the same full screen, just tighter padding — this block used to inset
     the panel to a strip above the bottom bar, which would now fight the full-screen
     geometry (it is later in source order and would win). */
  .panel{--pad:14px;padding:16px var(--pad) 40px;}
  .panel h2{padding:14px var(--pad) 10px;margin:-16px calc(var(--pad) * -1) 12px;font-size:19px;}
  /* a vertical swipe on stash slots scrolls the panel (drag uses pointer events, so
     touch-action governs); tap still opens the deposit/withdraw/salvage menu */
  #stashGrid .slot.draggable,#stashInv .slot.draggable{touch-action:pan-y;}
  /* Ten fixed 54px columns are 540px wide and a phone is 360 — here the slots share the
     width instead, which is what they always did before the desktop cap was fixed. */
  #stashGrid,#stashInv{grid-template-columns:repeat(10,minmax(0,1fr));}
}

/* landscape phones (touch + short viewport): the HUD leaves ~170px of panel height —
   nothing fits that without scrolling, so ONLY here the inventory may scroll
   (portrait keeps the everything-visible, no-scroll layout) */
@media (max-width:820px),(pointer:coarse) and (max-height:520px){
  #invPanel{overflow-y:auto;-webkit-overflow-scrolling:touch;}
}

/* ---- language switcher (hub / options / HUD) ---------------------------- */
.cglangsw{display:inline-flex;gap:4px;align-items:center;}
.cglangbtn{font:600 12px Verdana,sans-serif;color:#b9ab90;background:#241d28;
  border:1px solid #4a3d52;border-radius:6px;padding:4px 9px;cursor:pointer;
  letter-spacing:.3px;transition:border-color .15s,color .15s,background .15s;}
.cglangbtn:hover{color:#f2e6c8;border-color:#8a6a3a;}
.cglangbtn.on{color:#1a1400;background:#e0a53a;border-color:#f4d68a;}
#hubLang{position:absolute;top:10px;right:12px;z-index:6;}
#hudLangBtn b{font:700 10px Verdana,sans-serif;margin-left:2px;vertical-align:top;opacity:.85;}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){#hubLang{position:static;margin:6px auto 0;text-align:center;}}

/* ---- loot goblin: the "it got away" message ---------------------------- */
/* Across the whole screen and then gone. pointer-events:none matters — the player is
   almost always mid-chase when this fires and must not have a click eaten by it. */
#gobBanner{position:fixed;inset:0;z-index:55;display:flex;align-items:center;justify-content:center;
  pointer-events:none;opacity:0;text-align:center;padding:0 6vw;
  font-family:inherit;font-size:clamp(20px,4.4vw,46px);letter-spacing:3px;
  color:#8fd0ff;text-shadow:0 0 24px rgba(74,168,240,.55),0 3px 10px #000;}
#gobBanner.show{animation:gobFade 3.4s ease-out forwards;}
@keyframes gobFade{
  0%   {opacity:0;   transform:scale(1.10);letter-spacing:11px;}
  14%  {opacity:1;   transform:scale(1);   letter-spacing:3px;}
  60%  {opacity:.95; transform:scale(1);}
  100% {opacity:0;   transform:scale(.96); letter-spacing:8px;}
}
@media (prefers-reduced-motion:reduce){
  #gobBanner.show{animation:gobFadePlain 3.4s ease-out forwards;}
  @keyframes gobFadePlain{0%{opacity:0}14%{opacity:1}60%{opacity:.95}100%{opacity:0}}
}

/* ---- the long reading panels ------------------------------------------- */
/* The full-screen GEOMETRY that used to live here now belongs to every .panel (see the
   panels section above), so `.full` is left carrying only what is specific to these
   four documents: a denser codex grid and two-column prose. The class stays in the
   markup — removing it would mean editing four files to change nothing visible. */
.panel.full .cxgrid{grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;}
.panel.full #featuresBody{columns:2;column-gap:46px;}
.panel.full .featsec{break-inside:avoid;margin-bottom:18px;}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){
  .panel.full #featuresBody{columns:1;}
}

/* ---- Daily Challenge card, shown beside the title before you pick a hero -- */
#dailyCard{position:fixed;left:14px;top:50%;transform:translateY(-50%);z-index:12;
  width:min(310px,26vw);max-height:86vh;overflow-y:auto;padding:14px 16px;
  background:rgba(18,13,26,.94);border:1px solid #4a3d52;border-left:3px solid #c47de0;
  border-radius:8px;box-shadow:0 10px 40px #000;font-family:Verdana,sans-serif;}
#dailyCard.hidden{display:none;}
#dailyCard h3{font-family:Georgia,serif;font-size:15px;letter-spacing:1.5px;color:#e8c74a;
  margin:0 0 3px;font-weight:normal;}
#dailyCard .dcsub{font-size:10px;color:#8d8398;line-height:1.5;margin-bottom:10px;}
#dailyCard .dcmut{border-top:1px solid #342b3c;padding:9px 0 2px;}
#dailyCard .dcmut b{display:block;font-size:12px;color:#c47de0;margin-bottom:3px;}
#dailyCard .dcmut span{font-size:11px;color:#b9ab90;line-height:1.5;}
#dailyCard .dcgo{display:block;width:100%;margin-top:12px;padding:9px;cursor:pointer;
  background:#3a2a1a;border:1px solid var(--ember);color:var(--ember);
  font-family:Georgia,serif;font-size:14px;letter-spacing:1px;border-radius:6px;}
#dailyCard .dcgo:hover{background:var(--ember);color:#1a0f08;}
@media (max-width:1100px){#dailyCard{display:none;}}

/* ---- HUD nudge: a panel button breathes when free power waits inside ------ */
/* Purely informational — it surfaces something already earned, never grants it.
   Slow and low-contrast on purpose: this is a hint, not an alarm. */
.pbtn.nudge{animation:pbtnNudge 2.1s ease-in-out infinite;border-color:#e8c74a;}
.pbtn.nudge::after{content:'';position:absolute;top:-3px;right:-3px;width:8px;height:8px;
  border-radius:50%;background:#e8c74a;box-shadow:0 0 6px rgba(232,199,74,.9);}
.pbtn{position:relative;}
@keyframes pbtnNudge{
  0%,100%{box-shadow:0 0 0 rgba(232,199,74,0);}
  50%    {box-shadow:0 0 11px rgba(232,199,74,.55);}
}
@media (prefers-reduced-motion:reduce){
  .pbtn.nudge{animation:none;box-shadow:0 0 9px rgba(232,199,74,.5);}
}
/* the only salvage chip that can destroy something irreplaceable — reads as a warning */
.salvchip.danger{border-style:dashed;}
.salvchip.danger.on{border-style:solid;font-weight:700;}

/* Boons shares a tab strip with Skills/Passives now, and on a phone its hint wrapped to
   two lines and ran into the list under it. It also says "hover a row", which means
   nothing on a touch screen — so it is desktop-only rather than merely shortened. */
@media(max-width:700px){ #powersPanel h2 .phint{display:none} }

/* Explainer modal (39-explain.js): one thing to read, one button to press. Sized for a
   phone first — this is aimed at people in their first ten levels, and most of them are
   on one. .overlay already supplies the full-screen dim and centring. */
#explainOverlay .expbox{width:min(480px,92vw);background:linear-gradient(180deg,#1c1526,#120d1a);
  border:1px solid #4a3f5c;border-radius:12px;padding:22px 22px 18px;text-align:center;
  box-shadow:0 12px 48px rgba(0,0,0,.6)}
#explainOverlay .expicon{font-size:40px;line-height:1;margin-bottom:8px}
#explainOverlay h2{margin:0 0 10px;font-size:20px;color:#e8c74a;letter-spacing:.02em}
#explainOverlay p{margin:0 0 18px;font-size:15px;line-height:1.6;color:#c9bfae;text-align:left}
#explainOverlay .cgbtn{font-size:16px;padding:11px 30px;min-width:170px}
#explainOverlay .exphint{margin-top:10px;font-size:11px;color:#6f6678}
#pauseOverlay h1{color:#c9bfae;letter-spacing:.22em}
#pauseOverlay p{color:#8d8398;margin-bottom:18px}

/* One line under the leaderboard tabs saying what the selected board ranks (27-cloud.js).
   Sits between the tabs and the class filter, so it reads as a caption for the tabs. */
#lbDesc{max-width:760px;margin:2px auto 10px;padding:0 8px;text-align:center;
  font-size:13px;line-height:1.5;color:#8d8398}
#lbDesc.hidden{display:none}

/* ---- end-of-run summary + the rules the run was bound to (22-ui-helpers.js).
   .rsum/.rsrow open the death screen; .rulehead/.rulerow are shared with the
   character sheet (C), which is why they carry no #deathLog prefix. ---- */
.rsum{margin:0 0 12px;padding-bottom:10px;border-bottom:1px solid #3a2f2a}
.rsrow{display:flex;justify-content:space-between;align-items:baseline;gap:12px;
  font-size:14px;line-height:1.7}
.rsrow>span:first-child{color:#8d8398}
.rsrow>span:last-child{color:#e8e2d8;text-align:right}
.rsxp{color:#ffd75e}
.rulehead{font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:#c47de0;
  margin:10px 0 6px}
.rulehead small{letter-spacing:0;text-transform:none;color:#e8c74a}
.rulerow{display:flex;flex-direction:column;gap:1px;font-size:13px;line-height:1.45;
  padding:4px 6px;margin:0 -6px 2px;border-left:2px solid rgba(196,125,224,.5)}
.rulerow>b{color:#e8e2d8;font-weight:600}
.rulerow>span{color:#8d8398}

/* ---- last-stand log on the death screen (renderDeathLog, 22-ui-helpers.js) ---- */
#deathLog{width:min(560px,92vw);margin:18px auto 0;text-align:left;
  background:rgba(0,0,0,.34);border:1px solid #3a2f2a;border-radius:8px;padding:10px 12px;
  max-height:52vh;overflow-y:auto}
/* Wide screens: side by side, and use the height that was sitting empty. One flowing
   column pushed the score out of view behind the last-stand log — on a 1080p desktop the
   box used a third of the width and a third of the height. Phones keep the single column. */
@media(min-width:900px){
  #deathLog{width:min(1040px,94vw);max-height:62vh;padding:14px 18px;
    display:grid;grid-template-columns:minmax(0,0.95fr) minmax(0,1.05fr);
    gap:4px 28px;align-items:start}
  #deathLog .dcolA,#deathLog .dcolB{min-width:0}
  #deathLog .dcolA .rsum{margin-bottom:10px}
  #deathLog .dcolB .cloghead{margin-top:0}
}
.cloghead{font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:#8d8398;margin-bottom:6px}
.clogkiller{font-size:15px;color:#e0402e;font-weight:700;margin:0 0 8px;
  padding-bottom:8px;border-bottom:1px solid #3a2f2a}
.clogrow{display:flex;align-items:baseline;gap:8px;font-size:13px;line-height:1.5;padding:1px 0}
.clogrow.kill{background:rgba(224,64,46,.16);border-radius:4px;padding:2px 4px;margin:0 -4px}
.clogt{flex:0 0 44px;color:#6f6560;font-variant-numeric:tabular-nums;font-size:12px}
.clogx{flex:1 1 auto}
.cloghp{flex:0 0 auto;color:#8d8398;font-variant-numeric:tabular-nums;font-size:12px}

/* boss is leashed → untouchable. Grey the bar so "my damage does nothing" is never a mystery. */
#bossbar.leashed #bossfill{filter:grayscale(1) brightness(.55)}
#bossbar.leashed #bossname{color:#8d8398;animation:leashpulse 1.1s ease-in-out infinite}
@keyframes leashpulse{0%,100%{opacity:.55}50%{opacity:1}}

/* ---- awakened gear (30-awaken.js) ---- */
/* Bottom-LEFT on purpose: the forge badge already owns the top-right corner. */
/* TOP-LEFT. The forge's +N badge owns the top-right, so the two never collide, and an
   awakened piece is now identifiable without opening anything. */
.slot .awkb{position:absolute;top:1px;left:3px;font-size:10px;font-weight:700;color:#9ad8f0;
  text-shadow:0 1px 2px #000;font-family:Verdana,sans-serif;pointer-events:none;line-height:1;}
.slot .awkb.max{color:#ffd75e;text-shadow:0 0 6px rgba(255,215,94,.9),0 1px 2px #000;}
/* the same mark beside the item's name, mirroring the forge's +N chip */
.awkchip{color:#9ad8f0;font-size:11px;vertical-align:top;}
.awkchip.max{color:#ffd75e;text-shadow:0 0 6px rgba(255,215,94,.8);}
.awk{display:block;margin:5px 0 3px;padding:5px 7px;border-radius:5px;font-size:11px;
  background:rgba(90,150,190,.14);border:1px solid rgba(154,216,240,.35);color:#9ad8f0;}
.awk.max{background:rgba(255,215,94,.14);border-color:rgba(255,215,94,.5);color:#ffd75e;}
.awk .awkobj{color:#c9c2b4;}
.awk .awkbar{display:block;height:5px;margin:4px 0 2px;border-radius:3px;
  background:rgba(0,0,0,.45);overflow:hidden;}
.awk .awkbar i{display:block;height:100%;background:linear-gradient(90deg,#5d8ae8,#9ad8f0);}
.awk .awknum{color:#c9c2b4;}
.awk .awkhint{display:block;margin-top:2px;color:#8d8398;font-size:10px;font-style:italic;}

/* ---- mana cost on the skill bar + regen on the orbs (v3.02) ---- */
/* Bottom-LEFT: the other three corners of a skill slot are taken — key top-left,
   minion cap top-right, skill level bottom-right. */
.skslot .mana{position:absolute;bottom:1px;left:4px;font-size:12px;font-weight:700;
  color:#8fc0f0;text-shadow:0 1px 2px #000;font-family:Verdana,sans-serif;line-height:1;
  pointer-events:none;}
.skslot .mana.short{color:#e05a4a;}          /* you cannot afford this right now */
.orbtxt{flex-direction:column;gap:1px;}
.orbtxt .orbrgn{font-style:normal;font-size:11px;opacity:.75;}
.awk .awkbonus{display:block;margin-top:2px;color:#9ad8f0;font-size:11px;font-weight:700;}
.awk.max .awkbonus{color:#ffd75e;}
.awkforge{display:block;margin-top:3px;color:#e8c74a;font-weight:700;}
/* Per-stat awakening credit, at the end of a stat line: "⚔️ Damage 120–180  ✦ +12–18".
   Same blue as the rest of the awakening chrome so it reads as one story, and deliberately
   quieter than the stat itself — it annotates the number, it is not the number. */
.awkg{margin-left:6px;color:#9ad8f0;font-size:11px;font-weight:700;white-space:nowrap;}
.awk .awkbhint{display:block;margin-top:1px;color:var(--dim);font-size:10px;font-weight:400;font-style:normal;}
/* The exact numbers behind a daily rule / pact, in brackets after its written line. */
.rulerow .ruleeff,.dcmut .ruleeff{display:block;margin-top:2px;color:#c47de0;font-size:11px;font-style:italic;}
/* What a card's attributes or a buff's stats actually buy, for THIS hero. Sits between the
   raw numbers and the flavour, because it is the line that turns one into the other. */
.statgain{display:block;margin-top:4px;color:#9ad8f0;font-size:11px;font-style:italic;line-height:1.45;}
/* The arithmetic behind a composite board, under its description. */
.lbformula{display:block;margin-top:3px;color:#8d8398;font-size:11px;font-style:italic;}
/* What the daily is, and what winning it means — replaces the old HUD banner. */
.ruleabout{margin:2px 0 6px;color:var(--dim);font-size:11px;line-height:1.5;}
.ruleabout b{display:block;margin-top:2px;color:#e8c74a;font-weight:700;}

/* ---- account XP track (31-account.js) ---- */
/* A corner pip, like #dashBtn's charge count. Writing "Account 2" inside a 38px
   square button stretched it into a lump twice the width of its neighbours. */
.pbtn{position:relative;}
#accBadge{position:absolute;right:-3px;bottom:-3px;min-width:15px;height:15px;border-radius:8px;
  background:var(--panel2);border:1px solid var(--line);color:#c9c2b4;font-size:9px;font-weight:700;
  font-family:Verdana,sans-serif;align-items:center;justify-content:center;
  padding:0 3px;line-height:1;pointer-events:none;
  /* v3.95: hidden unless there is something to spend. It carried the account LEVEL, which
     on a button about spending points read as a count of purchases. With the number gone
     the element still has a fixed size, so without this it would sit there as a permanent
     grey dot — which is not "nothing shown". */
  display:none;}
#accBadge.spend{display:flex;background:#ffd75e;border-color:#ffd75e;color:#1a1220;
  box-shadow:0 0 7px rgba(255,215,94,.85);}
/* Block, not flex: the panel docks to a narrow column and space-between shrank both
   children to min-content, breaking 'Account level 2' one word per line. */
.acchead{display:block;}
.accpt{display:block;margin-top:2px;}
.acclvl{font-family:Georgia,serif;font-size:17px;letter-spacing:1px;color:#e8e2d0;}
.accpt{color:#ffd75e;font-weight:700;}
.accbar{height:9px;margin:8px 0 4px;border-radius:5px;background:rgba(0,0,0,.5);
  border:1px solid var(--line);overflow:hidden;}
.accbar i{display:block;height:100%;background:linear-gradient(90deg,#c08a2a,#ffd75e);}
.accnum{color:var(--dim);font-size:12px;}
.acchint{color:var(--dim);font-size:14px;font-style:italic;line-height:1.6;margin:10px 0;}
.acclist{margin:4px 0 0;padding-left:18px;line-height:1.7;font-size:12px;}
.acclist b{color:#ffd75e;}

/* ---- thumb-reachable potions (v3.05) ----
   The belt entries at the bottom are a small target in a crowded row, and on a phone
   they sit under the hand rather than the thumb. These mirror #dashBtn on the OPPOSITE
   side, so life and mana land where the left thumb already rests. Touch only: on
   desktop the belt row is fine and two big circles would just be clutter.
   They are DOM buttons, so touching one never plants the movement joystick — that only
   happens on the canvas (see 14-input.js). */
.potbtn{display:none;position:absolute;left:16px;width:72px;height:72px;border-radius:50%;
  background:rgba(20,15,24,.92);border:2px solid var(--line);color:#fff;font-size:26px;
  line-height:1;cursor:pointer;pointer-events:auto;z-index:25;box-shadow:0 4px 16px #000;
  align-items:center;justify-content:center;user-select:none;-webkit-user-select:none;
  text-shadow:0 1px 2px #000;}
#potBtnHp{bottom:300px;border-color:#e05a4a;}
.potbtn b{position:absolute;right:-2px;bottom:-2px;min-width:20px;height:20px;border-radius:10px;
  color:#140b0b;font-size:12px;font-weight:700;font-family:Georgia,serif;
  display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 4px #000;}
#potBtnHp b{background:#e05a4a;}
.potbtn .potbcd{position:absolute;inset:-2px;border-radius:50%;display:flex;
  align-items:center;justify-content:center;font-size:15px;font-weight:700;
  font-family:Verdana,sans-serif;color:#e8e2d0;pointer-events:none;}
.potbtn.empty{filter:grayscale(1) brightness(.7);opacity:.55;}
.potbtn:active{transform:scale(.94);}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){
  .potbtn{display:flex;width:62px;height:62px;font-size:23px;left:14px;}
  #potBtnHp{bottom:calc(258px + env(safe-area-inset-bottom,0px));}
  /* the belt entries stay, but shrink out of the way — the round buttons are the target now */
  #beltline .pot{opacity:.75;}
}

/* The Account page is a READING page, so it uses the same full-screen treatment as
   Features and the Database rather than the narrow docked column. */
.panel.full #accBody{max-width:900px;}
.panel.full .acclvl{font-size:30px;}
.panel.full .accbar{height:14px;}
.panel.full .acclist{columns:2;column-gap:36px;font-size:13px;}
@media (max-width:820px),(pointer:coarse) and (max-height:520px){ .panel.full .acclist{columns:1;} }

/* ---- the Vault (32-vault.js) ---- */
.vhead{display:block;margin-bottom:6px;}
.vpts{font-family:Georgia,serif;font-size:28px;color:#ffd75e;display:block;}
.vsub{color:var(--dim);font-size:13px;font-style:italic;}
/* Sized for the FULL-SCREEN panel this lives in now. 10-12px was chosen when the Vault
   sat in a 340px rail; across a 1100px page it was fine print, and this is the screen
   where a player spends 90 000 points. Cards align to the TOP now, not the middle —
   they carry four or five lines each and centring made them drift out of step. */
.vgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(400px,1fr));gap:12px;margin-top:12px;}
.vcard{display:flex;align-items:flex-start;gap:12px;padding:13px 14px;border-radius:7px;
  background:var(--panel2);border:1px solid var(--line);}
.vcard.owned{border-color:#ffd75e;box-shadow:0 0 10px rgba(255,215,94,.18);}
.vicon{font-size:32px;line-height:1;flex:0 0 auto;}
.vtxt{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1;font-size:13.5px;line-height:1.4;}
.vtxt b{font-family:Georgia,serif;font-size:18px;}
/* the ordinary class name, under the evolution's — what this hero WAS */
.vwas{color:var(--dim);font-size:12px;letter-spacing:.4px;}
.vwas::before{content:'← ';opacity:.6;}
.vdiff{color:#8d8398;font-size:11px;margin-top:4px;
  border-top:1px solid rgba(255,255,255,.07);padding-top:4px;}
.vname{color:#9ad8f0;font-size:13.5px;}
.vaff{color:#9fb4e8;font-size:13px;}
.vawk{color:var(--dim);font-size:12px;font-style:italic;}
.vbuy{flex:0 0 auto;min-width:62px;padding:10px 12px;border-radius:6px;cursor:pointer;
  background:var(--panel);border:1px solid #ffd75e;color:#ffd75e;
  font-family:Georgia,serif;font-size:15px;font-weight:700;}
.vbuy:hover{background:#ffd75e;color:#1a1220;}
.vbuy.poor{border-color:var(--line);color:var(--dim);opacity:.6;}
.vown{flex:0 0 auto;color:#ffd75e;font-size:13px;font-weight:700;}
.panel.full #vaultBody{max-width:1100px;}

/* ---- unspent points: a number, not a mood (v3.08) ----
   The tree button nudged for two different reasons — "you have points" and "you could
   combine two skills" — and they looked identical, so it seemed to stay lit after
   spending. Points now show their COUNT and blink; the combine hint keeps the quiet dot. */
.pbtn .ptspip{position:absolute;top:-4px;left:-4px;min-width:16px;height:16px;border-radius:9px;
  background:#5fd070;color:#0e1a10;font:700 10px Verdana,sans-serif;display:flex;
  align-items:center;justify-content:center;padding:0 3px;line-height:1;pointer-events:none;
  box-shadow:0 0 7px rgba(95,208,112,.85);animation:ptsPulse 1.4s ease-in-out infinite;}
@keyframes ptsPulse{0%,100%{transform:scale(1);}50%{transform:scale(1.16);}}
.tab.hasPts{animation:tabBlink 1.3s ease-in-out infinite;}
.tab.hasPts::after{content:'';display:inline-block;width:7px;height:7px;margin-left:6px;
  border-radius:50%;background:#5fd070;box-shadow:0 0 6px rgba(95,208,112,.9);vertical-align:middle;}
@keyframes tabBlink{0%,100%{color:#5fd070;}50%{color:#c9f0d0;}}
@media (prefers-reduced-motion:reduce){
  .pbtn .ptspip,.tab.hasPts{animation:none;}
}
.vtitle{font-family:Georgia,serif;font-weight:normal;letter-spacing:2px;font-size:19px;
  color:var(--ember);border-top:1px solid var(--line);margin:26px 0 12px;padding-top:16px;}

/* ---- hats (33-hats.js) ---- */
.hgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:10px;margin-top:10px;}
.hcard{display:flex;flex-direction:column;align-items:center;gap:6px;padding:9px 7px;
  border-radius:7px;background:var(--panel2);border:1px solid var(--line);}
.hcard.owned{border-color:#7a6a8e;}
.hcard.worn{border-color:#ffd75e;box-shadow:0 0 10px rgba(255,215,94,.2);}
.hprev{image-rendering:pixelated;background:rgba(0,0,0,.28);border-radius:5px;}
.hname{font-size:11px;color:var(--ink);text-align:center;line-height:1.3;}
.hbtn{width:100%;padding:7px 6px;border-radius:6px;cursor:pointer;font-size:12px;
  background:var(--panel);border:1px solid var(--line);color:var(--ink);font-family:Georgia,serif;}
.hbtn.buy{border-color:#ffd75e;color:#ffd75e;font-weight:700;}
.hbtn.buy:hover{background:#ffd75e;color:#1a1220;}
.hbtn.buy.poor{border-color:var(--line);color:var(--dim);opacity:.6;}
.hbtn.off{border-color:#ffd75e;color:#ffd75e;}
.panel.full #hatBody{max-width:1100px;}
.hlore{font-size:10px;color:var(--dim);font-style:italic;text-align:center;line-height:1.4;}

/* the branch opening bonus (passive tree) — reads as a promise, not as a node you can
   click, so it is deliberately flatter than .pnode and has no hover affordance */
.popen{background:rgba(60,42,80,.35);border:1px dashed #6b4a8f;border-radius:4px;
  padding:9px 8px;margin-bottom:9px;font-size:13px;color:#c3b6d6;line-height:1.45;}
.popen b{color:#d8b0ff;}
.popen.got{border-style:solid;border-color:var(--gold);color:#e6dcc6;}
.popen.got b{color:var(--gold);}
.popen .pr{display:block;color:var(--dim);font-size:11.5px;margin-top:4px;}
.popen.got .pr{color:var(--gold);}

/* ---------- The Eater's Legacy (38-legacy.js) ---------- */
/* Above the card draft (z 50) because it is offered before the run begins, and it must
   never be reachable past — there is no dismiss, the choice IS the gate. */
#legacyOverlay{z-index:54;background:radial-gradient(ellipse at 50% 40%,rgba(38,16,52,.95),rgba(8,5,12,.98));}
#legacyOverlay h2{color:#c98af8;letter-spacing:6px;font-size:26px;font-weight:normal;margin-bottom:4px;}
.lgsub{color:var(--gold);font-family:Verdana,sans-serif;font-size:14px;margin-bottom:2px;}
.lghint{color:var(--dim);font-family:Verdana,sans-serif;font-size:12px;margin-bottom:18px;max-width:520px;}
.lgrow{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;}
.lgcard{width:210px;background:var(--panel);border:1px solid #6b4a8f;padding:16px 12px;
  cursor:pointer;transition:transform .12s,border-color .12s,box-shadow .12s;}
.lgcard:hover{transform:translateY(-3px);border-color:#c98af8;box-shadow:0 0 18px rgba(176,74,240,.35);}
.lgcard .lgi{display:block;font-size:34px;margin-bottom:6px;}
.lgcard b{display:block;color:#d8b0ff;letter-spacing:2px;margin-bottom:6px;}
.lgcard .lgd{display:block;color:var(--dim);font-size:11.5px;font-family:Verdana,sans-serif;line-height:1.5;}
.lgcard.locked{opacity:.4;cursor:default;border-style:dashed;}
.lgcard.locked:hover{transform:none;border-color:#6b4a8f;box-shadow:none;}

/* the World-Eater slain: the death screen becomes an ascension */
.overlay h1.ascended{color:var(--gold);text-shadow:0 0 26px rgba(232,199,74,.55);}
.lgcard.slain{border-color:#8a4ad0;}
.lgcard.slain:not(.locked){box-shadow:0 0 16px rgba(176,74,240,.30);}

/* Evolution II carries a passive on top of everything Evolution I has, and its
   description is a sentence, not a stat line — five stacked lines made those cards tower
   over the Evolution I ones beside them. The passive NAME stays loud because that is what
   you are buying; the sentence is clamped to two lines and the full text is one hover
   away, the same bargain the skill tooltips already make. */
.vpas{color:#d8b0ff;font-size:12.5px;}
.vpas b{font-family:inherit;font-size:12.5px;color:#e8c8ff;}
.vpas{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.vcard:hover .vpas{-webkit-line-clamp:unset;overflow:visible;}

/* ---- Shop tabs (32-vault.js) ---- */
/* The three tabs SHARE the row rather than huddling at the left with dead space beside
   them, so a phone gets three equal 42px-tall targets instead of a ragged cluster.
   NOT sticky: the Hats pane lives in its own #hatBody element outside #vaultBody, so on
   that tab #vaultBody collapses to the height of the bar itself and there is nothing for
   a sticky element to stick within. A bar that holds on two tabs of three reads as a
   bug, so it scrolls with the page on all three. */
.shoptabs{display:flex;gap:8px;margin:2px 0 10px;flex-wrap:wrap;align-items:center;}
.shoppts{margin-left:auto;padding-left:12px;color:#ffd75e;font-family:Georgia,serif;
  font-size:18px;white-space:nowrap;}
.shoptab{flex:1 1 0;min-width:0;text-align:center;
  background:var(--panel2);border:1px solid var(--line);color:var(--dim);
  font-family:Georgia,serif;font-size:15px;letter-spacing:1px;padding:12px 10px;
  border-radius:6px;cursor:pointer;}
.shoptab:hover{color:var(--ink);border-color:var(--ember);}
.shoptab.on{color:#ffd75e;border-color:#ffd75e;background:rgba(255,215,94,.08);}

/* Phone: the point total takes the whole second line rather than shoving a tab off the
   edge, and the labels shrink so three of them still fit one row at 320px. */
@media (max-width:560px){
  .shoptabs{gap:6px;}
  .shoptab{font-size:13px;letter-spacing:.5px;padding:12px 4px;}
  .shoppts{flex:1 0 100%;margin-left:0;padding-left:0;text-align:right;font-size:16px;}
}

/* Crucible exit. Sits beside the dash button and deliberately does NOT look like it —
   dash is a reflex you hit mid-fight, this ends the run, so it is quieter and further
   from the thumb rather than a second bright round target next to it. */
#leaveBtn{position:fixed;right:16px;bottom:150px;width:52px;height:52px;border-radius:50%;
  font-size:22px;background:rgba(26,18,28,.9);color:#c0507a;border:1px solid #7a3450;
  cursor:pointer;z-index:6;}
#leaveBtn:hover{border-color:#c0507a;background:rgba(56,24,40,.95);}
#leaveBtn:focus-visible{outline:2px solid var(--gold);outline-offset:2px;}
#leaveBtn.hidden{display:none;}

/* Owned evolution, shown on the class picker (25-core.js buildClassSelect). */
.classCard .cn.evolved{color:#ffd75e;}
.classCard .cwas{display:block;font-size:11px;color:var(--dim);letter-spacing:.5px;margin-top:-2px;}
.classCard .cevo{display:block;font-size:11px;letter-spacing:.8px;margin:3px 0 1px;opacity:.95;}

/* ---- Pacts (opt-in run modifiers, chosen after the hero) --------------------
   The list is long (51 entries), so it scrolls inside its own box rather than
   letting the page scroll: the running total and the Begin button must stay on
   screen while you shop, or you are choosing blind. */
#pactView{max-width:960px;}
#pactTotal{margin:6px 0 14px;font-size:15px;letter-spacing:.6px;color:var(--dim);}
#pactTotal b{color:var(--gold);font-size:22px;}
#pactTotal .pcount{color:var(--ember);}
#pactList{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:8px;
  max-height:52vh;overflow-y:auto;padding:4px;text-align:left;}
.pactRow{display:flex;gap:9px;align-items:flex-start;background:var(--panel);
  border:1px solid var(--line);padding:9px 10px;cursor:pointer;transition:border-color .12s,background .12s;}
.pactRow:hover{border-color:var(--ember);}
.pactRow.on{border-color:var(--gold);background:rgba(232,199,74,.09);}
.pactRow .pico{font-size:20px;line-height:1.1;}
.pactRow .pbody{flex:1;min-width:0;}
.pactRow .pn{display:block;font-size:13px;letter-spacing:.4px;}
.pactRow.on .pn{color:var(--gold);}
.pactRow .pd{display:block;font-size:11px;color:var(--dim);line-height:1.35;margin-top:2px;}
.pactRow .pv{font-size:12px;white-space:nowrap;color:var(--ember);align-self:center;}
.pactRow .pv.free{color:var(--dim);}
@media(max-width:560px){#pactList{grid-template-columns:1fr;max-height:46vh;}}

/* MENACE READOUT (v4.00). It used to be appended to #tierline, which already carries the
   floor name and level — on a phone that line ran under the depth badge and the whole
   thing became unreadable. Its own corner, bottom-right, clear of the skill bar, and it
   shows which WAY it is moving: the commonest report about Menace is "it goes up when I
   fight well but never comes down", and without a direction there is no way to see that
   it did. */
/* Clears the mana orb rather than sitting on it. The orb is 104px tall and its top edge is
   151px off the bottom on a desktop layout, so 96px put this readout squarely across it —
   reported as "not terrible, but it looks disgusting". The phone override below is a
   separate number because the orbs shrink to clamp(58px,17vw,72px) there. */
#menaceReadout{position:fixed;right:10px;bottom:160px;z-index:6;pointer-events:none;
  padding:4px 9px;border-radius:9px;background:rgba(20,12,18,.78);
  border:1px solid rgba(224,64,46,.55);color:#f4a08a;
  font-family:Verdana,sans-serif;font-size:12px;font-weight:700;letter-spacing:.3px;
  text-shadow:0 1px 2px #000;}
#menaceReadout .mnup{color:#e0402e;}
#menaceReadout .mndn{color:#7ad07a;}
@media (max-width:760px){ #menaceReadout{bottom:118px;font-size:11px;padding:3px 7px;} }

/* ---------- FRIENDS + WRAITHS (v4.12) ---------- */
/* Why an account is worth making, on the logged-out title screen. Reads as a list of
   what the game gains, not as a signup wall — the game stays fully playable without it. */
#acctBar .cgwhy{list-style:none;margin:8px 0 0;padding:0;display:grid;gap:5px;
  font-size:11px;line-height:1.45;color:var(--dim);text-align:left;}
#acctBar .cgwhy li{padding-left:2px;}
#acctBar .cgwhy b{color:#e8c74a;font-weight:700;}
@media (max-width:760px){ #acctBar .cgwhy{font-size:10px;gap:4px;} }

/* One friend / request / news line. The name takes the slack so the buttons stay put
   down the right edge however long the usernames are. */
#friendsPanel .frow{display:flex;align-items:center;gap:8px;padding:7px 10px;margin:4px 0;
  background:rgba(0,0,0,.25);border:1px solid #3a3040;border-radius:6px;}
#friendsPanel .fname{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;font-weight:700;color:#e8dfcc;}
#friendsPanel .fname .ti{color:#b09ad0;font-style:italic;font-weight:400;font-size:11px;}
#friendsPanel .fago{flex:0 0 auto;color:var(--dim);font-size:11px;}
#friendsPanel .frAdd{display:flex;gap:8px;margin:10px 0 4px;}
#friendsPanel .frAdd input{flex:1 1 auto;min-width:0;}
#friendsPanel h3{margin:16px 0 6px;}

/* "What an account gets you" — a block under the hub cards, replacing the four reasons
   that used to be crammed into the slim #acctBar strip above the title. */
#whyAccount{max-width:760px;margin:14px auto 0;padding:12px 16px;text-align:left;
  background:rgba(0,0,0,.28);border:1px solid #3a3040;border-radius:8px;}
#whyAccount h4{margin:0 0 8px;font-size:12px;letter-spacing:.6px;text-transform:uppercase;
  color:#e8c74a;font-weight:700;}
#whyAccount .cgwhy{list-style:none;margin:0;padding:0;display:grid;gap:7px;
  font-size:12px;line-height:1.5;color:var(--dim);}
#whyAccount .cgwhy b{color:#e8dfcc;font-weight:700;}
@media (max-width:760px){ #whyAccount{margin:12px 8px 0;padding:10px 12px;}
  #whyAccount .cgwhy{font-size:11px;gap:6px;} }

/* "Scales from:" — the line that answers whether a Boon will still be worth anything in
   an hour. Same treatment on the draft card and in the Boons-panel tooltip, deliberately:
   the answer must not look different depending on where it is read. */
.card .cdesc .cscale,.tip .cscale{display:block;margin-top:7px;padding-top:6px;
  border-top:1px dashed #3a3050;font-size:11px;line-height:1.45;color:#9a90a8;}
.card .cdesc .cscale b,.tip .cscale b{color:#7ad0c4;font-weight:700;}

/* "Your dead" on the Account page. The two <small> lines are the sub-facts of each row
   (how the hero died / whether anyone beat it) and must sit UNDER their line — inline they
   run straight into the text before them ("Lv 12floor 7"). */
#accDead .srow small{display:block;font-size:11px;color:var(--dim);margin-top:2px;font-weight:400;}
#accDead .srow>span:last-child{text-align:right;}

/* The doomed-hero modal (43-doom.js): your run ended, and the Eater is the only move left. */
.doombox{max-width:560px;}
.doombox h2{color:#c47de0;}
.doombox .doomhead{margin:14px 0 6px;font-size:13px;letter-spacing:.6px;color:#e8c74a;font-weight:700;}
.doombox .doomlist{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:7px;
  font-size:12px;line-height:1.5;color:var(--dim);}
.doombox .doomlist li{padding-left:14px;position:relative;}
.doombox .doomlist li::before{content:'·';position:absolute;left:3px;color:#b04af0;font-weight:700;}
.doombox .doomlv{margin:12px 0 2px;padding:9px 12px;border:1px solid #ff7a3a;border-radius:7px;
  background:rgba(255,122,58,.10);color:#ff9a5a;font-weight:700;font-size:16px;letter-spacing:.5px;}
.doombox .doomlv small{display:block;margin-top:3px;font-size:11px;font-weight:400;color:var(--dim);letter-spacing:0;}

/* v4.19a — two items of the same base are told apart by HOW the glyph is drawn, never by
   swapping it for a different picture: the icon has to keep matching the item's name.
   Deliberately does NOT touch the border, background or any rarity styling — the rarity
   frame stays the one thing that means exactly what it always meant. Variant 0 is
   untouched, so the majority of items still look like the plain, canonical icon. */
.ivar{display:inline-block;line-height:1;}
/* atlas-cropped item art standing where the emoji stood: sized off the surrounding font so
   every context (bag slot, forge row, vendor list) keeps its own icon scale */
.ivar .icart{width:1.25em;height:1.25em;image-rendering:pixelated;vertical-align:-0.22em;}
.iv1{filter:hue-rotate(28deg) saturate(1.25);transform:rotate(-7deg);}
.iv2{filter:hue-rotate(-32deg) brightness(1.12);transform:rotate(6deg) scale(0.94);}
.iv3{filter:saturate(0.55) brightness(1.18);transform:scale(1.08);}
.iv4{filter:hue-rotate(150deg) saturate(1.15);transform:rotate(-3deg) scale(0.97);}
.iv5{filter:contrast(1.3) hue-rotate(70deg);transform:rotate(9deg);}

/* The Wish picker (20-cards.js): 25 rerolls for a common card you choose. Scrolls inside
   itself rather than growing the overlay, because the list is 40+ cards on a phone. */
/* ⚠ flex:0 0 auto IS LOAD-BEARING. #cardOverlay is a flex column, so the picker was
   shrunk by its siblings to a 22px sliver on a phone — the cards were laid out and simply
   clipped out of sight, which reads as "the Wish button does nothing". */
#wishPanel{max-width:min(760px,92vw);margin:10px auto 0;background:#171320;border:1px solid #3a3350;
  border-radius:10px;padding:10px;max-height:46vh;overflow-y:auto;flex:0 0 auto;width:100%;}
#wishPanel .wishhead{font-size:12px;color:#b9b3a6;margin-bottom:8px;}
#wishPanel .wishgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:6px;}
#wishPanel .wishcard{display:flex;align-items:center;gap:6px;background:#211b2e;border:1px solid #3a3350;
  border-radius:8px;padding:7px 8px;color:#e8e2d8;font:inherit;font-size:12px;cursor:pointer;text-align:left;
  min-height:44px;}   /* thumb-sized: this is a list you tap, not a row you read */
#wishPanel .wishcard:hover{border-color:#c9a227;background:#2a2239;}
#wishPanel .wcic{font-size:18px;}
#wishPanel .wcnm{flex:1;}
#wishPanel .wcown{color:#8d8398;font-size:11px;}

/* Says WHICH of the two alternating draft pools this is — see renderCardOverlay. Sits
   under the gold header and deliberately reads as prose, not as another card. */
#cardSubtitle{max-width:min(720px,90vw);margin:-14px auto 20px;text-align:center;
  font-size:13px;line-height:1.5;color:#b9b3a6;}
#cardSubtitle b{color:#e8e2d8;}
#cardSubtitle i{color:#8d8398;font-style:italic;}
@media (max-width:760px){ #cardSubtitle{font-size:12px;margin:-8px auto 14px;} }

/* Random-event offer (44-events.js). Deliberately reads like a person talking to you —
   wide measure, quiet frame — rather than like another card to optimise. */
#eventOverlay .evbox{max-width:min(620px,92vw);margin:auto;background:#171320;border:1px solid #6b4ea8;
  border-radius:14px;padding:22px 24px;text-align:center;box-shadow:0 0 60px rgba(107,78,168,.25);}
#eventOverlay .evicon{font-size:46px;line-height:1;margin-bottom:6px;}
#eventOverlay h2{color:var(--gold);letter-spacing:2px;font-weight:normal;font-size:20px;margin:0 0 12px;}
#eventOverlay .evpitch{color:#d8cfbe;font-size:14px;line-height:1.65;margin:0 0 16px;font-style:italic;}
#eventOverlay .evterms{display:flex;flex-wrap:wrap;gap:6px 18px;justify-content:center;
  font-size:12.5px;color:#b9b3a6;margin-bottom:18px;}
#eventOverlay .evterms b{color:#e8e2d8;}
/* A modal decision worth score is not a place to save 20 pixels: these are sized for a
   thumb (44px is the accessibility floor for a touch target) rather than inheriting the
   compact .cgbtn used in dense panels. Measured at 390x844 they came out 19px tall. */
#eventOverlay .evbtns{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;}
#eventOverlay .evbtns .cgbtn{min-height:44px;padding:12px 22px;font-size:14px;}
@media (max-width:760px){ #eventOverlay .evbtns{flex-direction:column;}
  #eventOverlay .evbtns .cgbtn{width:100%;} }
#eventOverlay .cgbtn.evghost{background:#241d33;border-color:#3a3350;color:#b9b3a6;}
#eventOverlay .evhint{margin-top:12px;font-size:11.5px;color:#8d8398;}
#menaceReadout .evrun{color:#c9a227;}
@media (max-width:760px){ #eventOverlay .evbox{padding:16px 14px;} #eventOverlay .evpitch{font-size:13px;} }

/* Permanent slot enchants, marked on the slot itself (23-panels.js). Bottom-right, clear of
   the forge badge top-right and the awakening badge bottom-left. */
.slot .ench{position:absolute;right:2px;bottom:2px;font-size:9px;line-height:1;color:#c9a227;
  background:rgba(23,19,32,.85);border-radius:4px;padding:1px 3px;pointer-events:none;}
.tip .ta.ench{color:#c9a227;}

/* ⚠ THE UNIQUE PULSE IS FOR THE BACKPACK ONLY.
   .slot.r5 pulses to say "look at this". Late game the hero wears a unique in nearly every
   slot, so the entire equipment panel throbbed at once and the marker stopped meaning
   anything — a signal that is always on is not a signal. Equipped slots carry data-eslot,
   so they keep the border and lose the animation; a unique lying in the bag still shouts. */
.slot[data-eslot].r5{animation:none;}

/* The end of a passive column — the keystone's bigger sibling, so it borrows its shape and
   only says "further" through colour, never through another layout. */
.pnode.finalnode{border-color:#c9a227;}
.pnode.finalnode.owned{background:linear-gradient(180deg,#2a2239,#241d33);border-color:#e8c74a;}

/* Achievement filters (26-meta.js). Two rows of chips: what STATE, then what KIND. They
   wrap rather than scroll — a filter you have to scroll to find is a filter nobody uses. */
.achchips{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px;}
.achchips.cats{margin-top:-4px;}
.achchip{background:#211b2e;border:1px solid #3a3350;border-radius:999px;padding:6px 12px;
  color:#b9b3a6;font:inherit;font-size:12px;cursor:pointer;min-height:32px;}
.achchip:hover{border-color:#6b4ea8;color:#e8e2d8;}
.achchip.on{background:#2f2545;border-color:#c9a227;color:#e8c74a;}
.achchip b{color:#e8e2d8;font-weight:600;}
.achchip.on b{color:#e8c74a;}
.achempty{color:#8d8398;font-size:13px;padding:14px 4px;text-align:center;}
@media (max-width:760px){ .achchip{padding:8px 12px;min-height:38px;} }

.achsearch{margin:0 0 10px;}
.achsearch input{width:100%;box-sizing:border-box;background:#171320;border:1px solid #3a3350;
  border-radius:8px;padding:9px 12px;color:#e8e2d8;font:inherit;font-size:13px;min-height:38px;}
.achsearch input:focus{outline:none;border-color:#6b4ea8;}

/* The Wish picker now spans every rarity, so a card carries its colour and its price. */
#wishPanel .wishcard .wccost{margin-left:auto;color:#c9a227;font-size:11px;font-weight:600;}
#wishPanel .wishcard.poor{opacity:.42;}
#wishPanel .wishcard.poor:hover{border-color:#3a3350;background:#211b2e;cursor:not-allowed;}
#wishPanel .wishcard.r1{border-color:#4a6fa5;} #wishPanel .wishcard.r2{border-color:#c9a227;}
#wishPanel .wishcard.r3{border-color:#8a4fc0;} #wishPanel .wishcard.r4{border-color:#c04a3a;}

/* ⚠ THE TEMPORARY DISCARD BUTTON (index.html, 2026-08-08). Bottom-left, deliberately ugly and
   deliberately labelled TEMP: a control that deletes a character should never look like part of
   the furniture. It sits inside #hud, so it is hidden with the HUD on the title screen. */

/* A CRAFTED piece, in any grid that uses slotDiv: the rarity colour keeps its meaning and the
   EDGE says where the thing came from. Dashed, because a made item is a thing you drew rather
   than a thing you found — and because it survives every rarity colour underneath it. */
.slot.made{border-style:dashed !important;border-width:2px !important;}
.slot.made::after{content:'';position:absolute;left:3px;top:3px;width:4px;height:4px;
  border-radius:50%;background:#8fd08f;opacity:.85;}

/* The Craftsman's bench: base picker, the exact numbers, and the finished piece waiting. */
#craftPreview .crbases{display:flex;flex-wrap:wrap;gap:5px;margin:0 0 8px;}
#craftPreview .crbase{background:#241d33;border:1px solid #3a3350;border-radius:6px;color:#b9b3a6;
  font:inherit;font-size:12px;padding:5px 9px;cursor:pointer;}
#craftPreview .crbase small{color:#7a7288;margin-left:4px;}
#craftPreview .crbase.on{border-color:#8fd08f;color:#e8e2d8;background:#22301f;}
#craftPreview .crstats{display:flex;flex-direction:column;gap:3px;margin:6px 0;font-size:13px;color:#e8e2d8;}
#craftPreview .crstats span{line-height:1.4;}
#craftPreview .crmarks{margin:6px 0;padding:6px 8px;border-left:2px solid #8fd08f;
  background:rgba(143,208,143,.10);color:#cfe6cf;font-size:12px;line-height:1.5;}
#craftPreview .crwhat{margin:6px 0;padding:6px 8px;border-left:2px solid #6b4ea8;
  background:rgba(107,78,168,.12);color:#c9bfe0;font-size:12px;line-height:1.5;}
#craftPreview .crtray{margin-top:12px;border-top:1px solid #3a3350;padding-top:8px;}
#craftPreview .crtrayh{color:#8fd08f;font-size:12px;letter-spacing:.5px;margin-bottom:5px;}
#craftPreview .crtake{display:flex;align-items:center;gap:8px;width:100%;background:#1f2a1d;
  border:1px dashed #8fd08f;border-radius:8px;color:#e8e2d8;font:inherit;font-size:13px;
  padding:7px 10px;margin-bottom:5px;cursor:pointer;text-align:left;}
#craftPreview .crtake:hover{background:#2a3a27;border-style:solid;}
#craftPreview .crtake small{margin-left:auto;color:#8fd08f;font-size:11px;letter-spacing:.5px;}

/* What the hero already holds, by TYPE, on the panel that asks them to choose one. */
#convBody .cvstock{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 10px;}
#convBody .cvhave{background:#1b1626;border:1px solid #322c3e;border-radius:6px;
  padding:4px 9px;font-size:13px;color:#b9b3a6;}
#convBody .cvhave.none{opacity:.42;}
#convBody .cvhave.on{border-color:#7fb0d0;}

#gateBody .rtleap{display:block;margin:8px 0;color:#c9bfa6;font-size:12px;line-height:1.5;cursor:pointer;}
#gateBody .rtleap.off{opacity:.55;cursor:default;}

/* The gate panel's pointer to where Cinder is actually spent, and the vat's two-job tabs.
   ⚠ The board's own rules (.gtnodes/.gtnode/.gtnb/.gtnmax) went with the board on 2026-08-08 —
   the tree on the account page is the one shop now. Deleted rather than left: dead CSS for a
   removed panel is the kind of thing that gets copied forward for a year. */
#gateBody .gtround{font:700 12px Verdana,sans-serif;color:#c9a86a;letter-spacing:2px;
  text-transform:uppercase;margin-bottom:8px}
#gateBody .gtnodesay{margin:12px 0 4px;border-top:1px solid #4a3f2e;padding-top:8px;font-size:12px;line-height:1.5;}
#convBody .cvmode{background:#1b1626;border:1px solid #322c3e;border-radius:6px;color:#b9b3a6;
  font:inherit;font-size:12px;padding:6px 12px;cursor:pointer;}
#convBody .cvmode.on{border-color:#7fb0d0;color:#e8e2d8;background:#1e2a33;}

/* Options: every section is a <details> now — an arrow you can see, and closed by default, so
   the panel opens as a list of subjects rather than a wall of forty rows. */
#optionsPanel .optd{border-bottom:1px solid #2c2638;}
#optionsPanel .optd>summary{cursor:pointer;list-style:none;}
#optionsPanel .optd>summary::-webkit-details-marker{display:none;}
#optionsPanel .optd>summary::before{content:'\25B8';display:inline-block;width:14px;color:#8a7fa8;
  transition:transform .15s;}
#optionsPanel .optd[open]>summary::before{transform:rotate(90deg);}
#optionsPanel .optdbody{padding-bottom:6px;}
/* Accessibility controls */
#optionsPanel .a11ycols{display:flex;gap:6px;margin-top:6px;}
#optionsPanel .a11yc{width:26px;height:26px;border-radius:6px;border:1px solid #4a4458;cursor:pointer;
  color:#b9b3a6;font:12px Verdana,sans-serif;}
#optionsPanel .a11yc.on{border-color:#e8c74a;box-shadow:0 0 0 2px rgba(232,199,74,.25);}
#optionsPanel .a11ysel{margin-top:6px;background:#241d33;border:1px solid #3a3350;border-radius:6px;
  color:#e8e2d8;font:inherit;font-size:12px;padding:5px 8px;width:100%;}

/* The tutorial ring's page (69-tutorial.js): a manual, so it scrolls and it is readable. */
/* ⚠ WIDE, AND IN TWO COLUMNS WHERE THERE IS ROOM (owner: "možná by to mohlo být širší,
   abychom se třeba vešli na jednu stranu"). At 720px the manual was a tall ribbon that scrolled
   for four screens; a page you have to scroll four times is a page nobody finishes. Columns
   collapse to one under 900px so a phone still reads top to bottom. */
#floorOverlay .tutbox{max-width:min(1180px,96vw);text-align:left;}
#floorOverlay .tutbody{max-height:74vh;overflow-y:auto;padding-right:6px;
  column-count:2;column-gap:30px;column-rule:1px solid #2c2638;}
#floorOverlay .tutbody .tuh3{break-after:avoid;}
#floorOverlay .tutbody .tup{break-inside:avoid;}
@media (max-width:900px){ #floorOverlay .tutbody{column-count:1;} }
#floorOverlay .tuh3{color:#e8c74a;font-size:14px;letter-spacing:1px;margin:14px 0 4px;font-weight:normal;}
#floorOverlay .tup{color:#c9c3b6;font-size:13px;line-height:1.65;margin:0 0 8px;}
/* The reference table at the end of the manual. `break-inside:avoid` because the body is a
   two-column layout and a table split down the middle of a column rule is unreadable — the
   same reason .tup already carries it. */
#floorOverlay .tutnums{width:100%;border-collapse:collapse;font-size:12.5px;margin:2px 0 8px;
  break-inside:avoid;}
#floorOverlay .tutnums td{padding:3px 0;border-bottom:1px solid #241d33;color:#c9c3b6;
  vertical-align:top;}
#floorOverlay .tutnums td.tn{text-align:right;color:#e8c74a;white-space:nowrap;padding-left:10px;
  font-variant-numeric:tabular-nums;}

/* The gate's phase bar and its Cinder line (56-gate.js). */
#gateBody .gtbarwrap{position:relative;height:18px;background:#1b1626;border:1px solid #4a3f2e;
  border-radius:9px;overflow:hidden;margin:8px 0;}
#gateBody .gtbar{height:100%;background:linear-gradient(90deg,#7a5230,#ffb45a);transition:width .2s;}
#gateBody .gtbart{position:absolute;left:0;right:0;top:0;line-height:18px;text-align:center;
  font:11px Verdana,sans-serif;color:#f2e6c8;text-shadow:0 1px 2px #000;}
#gateBody .gtcinder{display:flex;gap:14px;align-items:center;margin:10px 0 6px;font-size:13px;color:#ffd06a;}

/* The Renderer's vat: a dial and a bar that visibly eats the pile (64-convert.js). */
#convBody .cvqty{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:0 0 8px;}
#convBody .cvq{background:#241d33;border:1px solid #3a3350;border-radius:6px;color:#b9b3a6;
  font:inherit;font-size:12px;padding:5px 10px;min-width:38px;cursor:pointer;}
#convBody .cvq:hover{border-color:#7fb0d0;color:#e8e2d8;}
#convBody .cvqn{color:#e8e2d8;font-size:13px;padding:0 6px;}
#convBody .cvbarwrap{position:relative;height:16px;background:#1b1626;border:1px solid #3a3350;
  border-radius:8px;overflow:hidden;margin:8px 0;}
#convBody .cvbar{height:100%;width:0;background:linear-gradient(90deg,#4a7f9e,#8fd0c0);
  transition:width .06s linear;}
#convBody .cvbart{position:absolute;left:0;right:0;top:0;line-height:16px;text-align:center;
  font:11px Verdana,sans-serif;color:#e8e2d8;text-shadow:0 1px 2px #000;}

/* The floor picker (18-world.js). A list of difficulties named as recommended levels — the
   one number a player already knows about themselves. Scrolls inside itself; the rows are
   thumb-sized because this is the screen a phone player uses most. */
#floorOverlay .fpbox{max-width:min(560px,92vw);margin:auto;background:#171320;border:1px solid #6b4ea8;
  border-radius:14px;padding:20px 18px;text-align:center;}
#floorOverlay h2{color:var(--gold);letter-spacing:2px;font-weight:normal;font-size:20px;margin:0 0 10px;}
#floorOverlay .fppitch{color:#b9b3a6;font-size:13px;line-height:1.6;margin:0 0 14px;}
#floorOverlay .fplist{display:flex;flex-direction:column;gap:6px;max-height:52vh;overflow-y:auto;margin-bottom:14px;}
#floorOverlay .fprow{display:flex;align-items:center;gap:10px;background:#211b2e;border:1px solid #3a3350;
  border-radius:8px;padding:10px 12px;color:#e8e2d8;font:inherit;font-size:13px;cursor:pointer;
  text-align:left;min-height:44px;}
#floorOverlay .fprow:hover{border-color:#c9a227;background:#2a2239;}
/* The jump box: the list is a window now (floorPickerRows), so this is how every floor
   below it stays reachable. Deliberately plain and small — it is the escape hatch, not
   the main choice, and it must not compete with the rows above it. */
#floorOverlay .fpjump{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:center;
  margin:0 0 14px;font-size:12px;color:#a79ab8;font-family:Verdana,sans-serif;}
#floorOverlay .fpjump input{width:82px;background:#211b2e;border:1px solid #3a3350;border-radius:6px;
  color:#e8e0d4;font:inherit;font-size:13px;padding:5px 8px;text-align:center;}
#floorOverlay .fpjump input:focus{outline:none;border-color:#c9a227;}
#floorOverlay .fpjump button{background:#2a2239;border:1px solid #6b4ea8;border-radius:6px;color:#d9cdf0;
  font:inherit;font-size:12px;letter-spacing:1px;padding:5px 14px;cursor:pointer;}
#floorOverlay .fpjump button:hover{border-color:#c9a227;color:#f2e6c8;}
#floorOverlay .fprow.hard{border-color:#8a6a2a;}
/* ⚠ RED READ AS "BLOCKED", NOT AS "PRESS ME". Reported: "it is not obvious I can click it
   when it has a red border" — the deep-dive rows are the whole point of the picker and they
   looked like a warning label. They keep the red (they ARE the dangerous choice) and gain the
   things that say button: a pointer, a lift on hover, and a brighter edge. */
#floorOverlay .fprow.gamble{border-color:#a53a2e;background:#241a1e;cursor:pointer;
  transition:border-color .15s,transform .15s,background .15s;}
#floorOverlay .fprow.gamble:hover{border-color:#ff6a4a;background:#301f24;transform:translateY(-2px);}
#floorOverlay .fprow.gamble::after{content:'\203A';margin-left:auto;color:#ff8a6a;font-size:18px;line-height:1;}
#floorOverlay .fpn{font-weight:600;min-width:5.5em;}
#floorOverlay .fplv{color:#b9b3a6;flex:1;}
#floorOverlay .fptag{color:#e0724a;font-size:11px;text-transform:uppercase;letter-spacing:.5px;}

/* The descent panel (66-descend.js) — the same overlay, but a FACT SHEET rather than a list:
   there is only one floor on offer, so the screen spends its room on what is down there.
   Two-column rows so the labels line up and the values can be scanned in one pass. */
#floorOverlay .dslist{display:flex;flex-direction:column;gap:6px;max-height:52vh;overflow-y:auto;
  margin:0 0 14px;text-align:left;}
#floorOverlay .dsrow{display:flex;gap:10px;align-items:baseline;background:#211b2e;
  border:1px solid #3a3350;border-radius:8px;padding:9px 12px;font-size:13px;}
#floorOverlay .dsk{color:#a79ab8;min-width:9.5em;font-size:12px;text-transform:uppercase;letter-spacing:.5px;}
#floorOverlay .dsv{color:#e8e2d8;flex:1;line-height:1.45;}
#floorOverlay .dsgo{display:block;width:100%;background:#2a2239;border:1px solid #6b4ea8;
  border-radius:8px;padding:12px 20px;margin:0 0 8px;color:#e8d8ff;font:inherit;font-size:14px;
  letter-spacing:1px;cursor:pointer;min-height:46px;transition:border-color .15s,transform .15s;}
#floorOverlay .dsgo:hover{border-color:#c9a227;color:#f2e6c8;transform:translateY(-2px);}
/* The other road. Deliberately the SAME weight as Descend rather than a lesser button: the
   panel is asking a question with two honest answers, and styling one of them as the way out
   would be the screen picking for you. Amber against the descent's violet, because that is
   already the caravan's colour everywhere else it appears. */
#floorOverlay .dshome{display:block;width:100%;background:#2e2417;border:1px solid #a5772f;
  border-radius:8px;padding:12px 20px;margin:0 0 6px;color:#f0d9a8;font:inherit;font-size:14px;
  letter-spacing:1px;cursor:pointer;min-height:46px;transition:border-color .15s,transform .15s;}
#floorOverlay .dshome:hover{border-color:#e8c74a;color:#fff3d6;transform:translateY(-2px);}
#floorOverlay .dsfare{font:11px Verdana,sans-serif;color:#c9a86a;letter-spacing:0;}
/* the wager block in the descent panel (74-wager.js) */
#floorOverlay .wgbox{margin:6px 0 12px;border-top:1px solid #3a3350;padding-top:10px}
#floorOverlay .wgh{font:700 12px Verdana,sans-serif;color:#e8c74a;letter-spacing:1.5px;margin-bottom:7px}
#floorOverlay .wgrid{display:grid;gap:6px}
#floorOverlay .wgr{display:grid;grid-template-columns:1fr auto;gap:2px 10px;text-align:left;
  background:#241d33;border:1px solid #3a3350;border-radius:7px;padding:8px 11px;cursor:pointer;
  font:inherit;color:#c9bfae}
#floorOverlay .wgr:hover:not([disabled]){border-color:#c9a227}
#floorOverlay .wgr.on{border-color:#e8c74a;background:#2e2417;color:#f0e0c0}
#floorOverlay .wgr.poor{opacity:.4;cursor:default}
#floorOverlay .wgn{font-size:13px;font-weight:700;letter-spacing:1px}
#floorOverlay .wgd{grid-column:1;font:11px Verdana,sans-serif;color:var(--dim);line-height:1.4}
#floorOverlay .wgc{grid-row:1/3;align-self:center;font:700 12px Verdana,sans-serif;color:#e8c74a;white-space:nowrap}
#floorOverlay .wgc em{font-style:normal;color:#5fd070;font-size:11px}
#floorOverlay .wgnote{font:11px Verdana,sans-serif;color:var(--dim);line-height:1.5;margin-top:8px}
#floorOverlay .dsnote{font:11px Verdana,sans-serif;color:var(--dim);line-height:1.5;margin:0 2px 12px;}

/* Back out of the floor picker. Styled like the panel Back buttons rather than as a primary
   action — leaving is not a choice the screen is asking you to make. */
#floorOverlay .fpback{background:#241d33;border:1px solid #3a3350;border-radius:8px;
  padding:10px 20px;color:#b9b3a6;font:inherit;font-size:13px;cursor:pointer;min-height:42px;}
#floorOverlay .fpback:hover{border-color:#6b4ea8;color:#e8e2d8;}

/* A lord's passives, on their own line beneath the health bar (22-ui-helpers.js). Never
   inside it: appended to the name they ran under the health numbers on a phone. Wraps
   rather than clipping — five passives is precisely when they must all be readable. */
#bosspass{position:absolute;left:0;right:0;top:100%;margin-top:3px;text-align:center;
  font:600 10.5px Verdana,sans-serif;color:#e0b0a0;text-shadow:0 1px 2px #000;
  pointer-events:none;line-height:1.35;}
@media (max-width:760px){ #bosspass{font-size:10px;} }


/* ---- THE ONE SCREEN (v4.87): bags on the left, character sheet on the right ----
   The sheet column scrolls on its own so the doll and the backpack never move under the
   cursor while you read numbers — the reason the old two-panel arrangement made comparing
   gear impossible was that you had to leave one screen to see the other. */
.invwrap{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:22px;align-items:start;}
.invmain{min-width:0;}   /* the v5.08 clip is gone: it hid the overflow by cutting slots in half, and the cause is fixed above */
/* ⚠ REPORTED AS OVERLAPPING THE BAGS AND NOT REPRODUCIBLE (v5.08). Measured at seven
   viewport widths from 956 to 1436: the gap between the backpack and this column is a
   constant 22px and never closes. Rather than keep guessing at the reporter's zoom or
   browser chrome, the column is made impossible to see through — it paints its own
   background and sits above the grid, so any overlap hides what is behind it instead of
   interleaving with it. The main column clips too, so a backpack that is somehow too wide
   is cut at its own edge rather than sliding under this one. */
.invside{min-width:0;position:sticky;top:0;z-index:2;background:rgba(14,10,20,.985);
  border-left:1px solid var(--line);padding-left:14px;}
.sidetabs{display:flex;gap:6px;margin-bottom:8px;}
.sidetab{flex:1;background:var(--panel2);border:1px solid var(--line);color:var(--dim);
  font-family:inherit;font-size:12px;letter-spacing:1px;padding:6px 4px;border-radius:5px;
  cursor:pointer;pointer-events:auto;transition:color .12s,border-color .12s,background .12s;}
.sidetab:hover{color:var(--ink);border-color:var(--ember);}
.sidetab.on{color:#1a1420;background:var(--ember);border-color:var(--ember);font-weight:bold;}
.sidestats{max-height:calc(100vh - 210px);overflow-y:auto;overflow-x:hidden;padding-right:6px;}
/* ⚠ THE SHEET MOVED INTO A 340px RAIL AND ITS TEXT NEVER LEARNED TO WRAP. In the old
   full-width Character panel a class trait ("Wildheart — healing received +25%, +6
   Vitality, +10% Area") always fitted on one line, so nothing ever wrapped and the rule
   that keeps VALUES on one line (white-space:nowrap) was harmless. In a narrow column the
   same rule pushed prose off the edge and grew a horizontal scrollbar. The label side may
   wrap now; the value side still may not, because "1 234" broken across two lines is
   worse than a long label. */
#invStats .srow{align-items:baseline;}
#invStats .srow span:first-child{white-space:normal;min-width:0;overflow-wrap:anywhere;}
#invStats .srow span:only-child{white-space:normal;overflow-wrap:anywhere;}
#invStats .rulerow,#invStats .rulehead,#invStats .shead{white-space:normal;overflow-wrap:anywhere;}
/* The comparison itself: green when the number goes up, red when it drops. Sign included,
   because "+12" and "12" are different claims and only one of them is true. */
.sdelta{margin-left:8px;font-family:Verdana,sans-serif;font-size:11px;font-weight:700;}
.srow.sup .sdelta{color:#5fc47a;}
.srow.sdown .sdelta{color:#e0402e;}
.srow.sup{background:rgba(95,196,122,.08);}
.srow.sdown{background:rgba(224,64,46,.08);}
/* Below this width the two columns stop being two columns — a 340px rail on a phone is a
   sliver, and the sheet is the half you can afford to scroll to. */
@media (max-width:900px){
  .invwrap{grid-template-columns:minmax(0,1fr);gap:14px;}
  .invside{position:static;}
  .sidestats{max-height:none;}
}
/* How many stats move in a tab you are NOT looking at — the reason a belt hovered on the
   Character tab used to look like it did nothing at all. */
.sidetab .tabdot{display:inline-block;margin-left:6px;min-width:16px;padding:0 4px;border-radius:8px;
  background:#5fc47a;color:#14210f;font:700 10px Verdana,sans-serif;line-height:15px;vertical-align:middle;}
.sidetab.on .tabdot{background:#1a1420;color:#ffd75e;}

/* The run summary is a table since v4.96 — same look, but the values line up in a column
   instead of relying on every row happening to be the same width. */
table.rsum{border-collapse:collapse;width:100%;}
table.rsum th{font-weight:normal;text-align:left;padding:3px 0;color:var(--dim);}
table.rsum td{text-align:right;padding:3px 0;color:var(--ink);white-space:nowrap;}

/* Grave / halo on a leaderboard row (v4.99). Fixed width so the values below each other
   still line up when a row has no marker at all. */
.lbrow .endmk{display:inline-block;width:20px;text-align:center;font-size:13px;opacity:.9;}

/* Daily: the day picker and that day's rules, under the class filter (v5.06). */
#lbDaySel{margin-left:8px;}
#lbDayMuts{margin:8px 0 4px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;}
#lbDayMuts .lbdayhead{color:var(--ember);font-size:11px;letter-spacing:2px;text-transform:uppercase;margin-right:4px;}
#lbDayMuts .lbdaymut{background:var(--panel2);border:1px solid var(--line);border-radius:5px;
  padding:3px 8px;font:12px Verdana,sans-serif;color:var(--dim);}

/* What kind of skill this is — the first line of a card after its name (v5.11). */
.skkind{display:inline-block;margin:2px 0 4px;padding:2px 8px;border-radius:5px;
  background:var(--panel2);border:1px solid var(--line);color:var(--dim);
  font:11px Verdana,sans-serif;letter-spacing:1px;}

/* A unique's flavour glyph, riding the corner of its base (v5.12). Small enough that the
   base still reads first, which is the whole point of putting the base back. */
.ivar{position:relative;display:inline-block;}
.ivar .iflav{position:absolute;right:-2px;bottom:-4px;font-size:.5em;font-style:normal;
  line-height:1;text-shadow:0 0 3px #000,0 0 3px #000;pointer-events:none;}

/* An earned hat states its condition instead of a price (v5.20). */
.hbtn.earn{display:block;background:none;border:1px dashed var(--line);color:var(--dim);
  font:11px Verdana,sans-serif;padding:5px 8px;border-radius:5px;cursor:default;}

/* ---- biome depth selector (openBiomePicker, 18-world.js) ----
   Rides the .fp* panel; only the two things a biome has and the hole does not need rules:
   what it yields, and what each depth grades/gambles at. */
#floorOverlay .bpyield{display:flex;flex-direction:column;gap:5px;margin:0 0 12px;}
#floorOverlay .bpmat{display:flex;align-items:center;gap:9px;background:#1d1828;
  border:1px solid #3a3350;border-radius:7px;padding:7px 10px;}
#floorOverlay .bpmi{font-size:17px;line-height:1;}
#floorOverlay .bpmn{color:#e8e0cf;font-weight:600;font-size:14px;}
#floorOverlay .bpmk{color:#8f88a0;font-size:12px;margin-left:auto;text-align:right;}
#floorOverlay .bpgr{color:#c9a227;font-size:12px;white-space:nowrap;margin-left:auto;}
@media (max-width:520px){
  #floorOverlay .bpmk{display:none;}          /* the verb is flavour; the name is not */
  #floorOverlay .bpgr{font-size:11px;}
}

/* ---- the Craftsman (53-craft.js) ---- */
#craftPanel .crrow,#gatePanel .crrow,#convPanel .crrow{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 12px;}
#craftPanel .crslot,#gatePanel .crslot,#convPanel .crslot{background:#211b2e;border:1px solid #3a3350;color:#c8c2d4;border-radius:7px;
  padding:6px 11px;font-size:13px;cursor:pointer;}
#craftPanel .crslot.on,#gatePanel .crslot.on,#convPanel .crslot.on{border-color:#c9a227;color:#e8e0cf;background:#2a2239;}
#craftPanel .crstock,#gatePanel .crstock,#convPanel .crstock{display:flex;flex-direction:column;gap:5px;max-height:36vh;overflow-y:auto;margin-bottom:12px;}
#craftPanel .crmat,#gatePanel .crmat,#convPanel .crmat{display:flex;align-items:center;gap:10px;background:#1d1828;border:1px solid #3a3350;
  border-radius:7px;padding:8px 11px;cursor:pointer;text-align:left;}
#craftPanel .crmat.on,#gatePanel .crmat.on,#convPanel .crmat.on{border-color:#8fd08f;background:#1f2a1f;}
/* Below the threshold it is shown, dimmed, rather than hidden: a player needs to see that
   the oak exists and that four is the number, not wonder where their oak went. */
#craftPanel .crmat.thin,#gatePanel .crmat.thin,#convPanel .crmat.thin{opacity:0.45;}
#craftPanel .crmn,#gatePanel .crmn,#convPanel .crmn{color:#e8e0cf;font-weight:600;font-size:14px;}
#craftPanel .crmh,#gatePanel .crmh,#convPanel .crmh{color:#8f88a0;font-size:12px;margin-left:auto;}
#craftPanel .crprev,#gatePanel .crprev,#convPanel .crprev{background:#171320;border:1px solid #6b4ea8;border-radius:9px;padding:12px 14px;}
#craftPanel .crline,#gatePanel .crline,#convPanel .crline{color:#e8e0cf;font-size:14px;margin-bottom:6px;}
#craftPanel .crwarn,#gatePanel .crwarn,#convPanel .crwarn{color:#e0a04a;font-size:13px;margin-bottom:4px;}
#craftPanel .crgood,#gatePanel .crgood,#convPanel .crgood{color:#8fd08f;font-size:13px;margin-bottom:4px;}
#craftPanel .crgo,#gatePanel .crgo,#convPanel .crgo{margin-top:10px;background:#2a2239;border:1px solid #c9a227;color:#e8e0cf;
  border-radius:7px;padding:9px 18px;font-size:14px;cursor:pointer;}
#craftPanel .crgo:hover,#gatePanel .crgo:hover,#convPanel .crgo:hover{background:#3a2f4d;}

/* The air warning. Five columns on one row already crowds a desktop and breaks a phone, so
   below 720px it drops to its own line under the depth instead of competing for width —
   it is the most important thing on the row and must never be the thing that wraps badly. */
#floorOverlay .bpair{font-size:11px;margin-left:8px;line-height:1.35;}
@media (max-width:720px){
  #floorOverlay .fprow{flex-wrap:wrap;}
  #floorOverlay .bpair{flex-basis:100%;margin:3px 0 0;order:9;}
  #floorOverlay .fptag{font-size:10px;}
}

/* Vault: the Cinder pane and the not-yet tree */
.vsoon{color:#8f88a0;font-size:14px;padding:22px;text-align:center;border:1px dashed #3a3350;border-radius:9px;}
.vcinder{color:#ffd06a;font-size:22px;margin:0 0 10px;}
.vcrow{color:#c8c2d4;font-size:13px;padding:5px 0;border-top:1px solid #2a2438;}
.vcrow span{color:#ffd06a;font-weight:700;margin-right:6px;}

/* The gathering tree, seen through frosted glass. Half-lit and pointer-events:none — a
   teaser must never look like a thing you failed to click. */
.vtree{margin-top:14px;opacity:0.38;pointer-events:none;filter:blur(0.3px);
  display:flex;flex-direction:column;gap:7px;}
.vtbranch{display:flex;align-items:center;gap:11px;background:#1b1626;border:1px solid #322b46;
  border-radius:8px;padding:9px 12px;}
.vti{font-size:17px;}
.vtn{color:#c8c2d4;font-weight:600;font-size:13px;min-width:86px;}
.vtv{color:#7d7690;font-size:12px;}
.vtnodes{margin-left:auto;display:flex;gap:7px;}
.vtnodes i{width:11px;height:11px;border-radius:50%;background:#2f2842;border:1px solid #443a5e;}
@media (max-width:560px){ .vtv{display:none;} }

/* ---- The Cindergate (56-gate.js). Ten steps shown as a ladder because "about ten runs"
   has to be something the player can SEE the end of, not a number in a sentence. ---- */
.gtprog{font-size:15px;color:#e8dcc8;margin:2px 0 10px}
.gtsteps{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
.gtstep{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:8px;
  background:#1a1526;border:1px solid #2e2740;opacity:.5;min-width:150px;flex:1 1 150px}
.gtstep.on{opacity:1;border-color:#7a5a2e;background:#241a18}
.gtstep.now{opacity:1;border-color:#ffd06a;background:#241d14;box-shadow:0 0 0 1px rgba(255,208,106,.25)}
.gtsi{width:22px;text-align:center;color:#ffd06a;font-weight:700}
.gtsn{flex:1;color:#d8cfbe;font-size:13px}
.gtsc{color:#e0a04a;font-size:13px}
.gtdone{color:#ffd06a;font-size:15px;margin-top:8px}
.crgo[disabled]{opacity:.45;cursor:not-allowed}
@media(max-width:700px){.gtstep{min-width:120px;flex:1 1 120px}}
/* The gate reuses the Craftsman's .cgmuted for "you carry none of these"; that class was only
   ever styled inside #cloudSection, so everywhere else it fell back to browser default. */
#gatePanel .cgmuted{color:var(--dim);font-size:13px;margin-bottom:10px;}
.gtkinds{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px}
.gtkind{background:#1a1526;border:1px solid #2e2740;border-radius:7px;padding:5px 9px;
  font-size:13px;color:#7d7590}
.gtkind.on{border-color:#7a5a2e;color:#e8dcc8}
.gtkind b{color:#e0a04a;margin-left:3px}
/* ⚠ WRAP THE ROW, NEVER THE WORDS. Seven controls in one flex line with no wrap squeezed the
   two TEXT buttons until their labels broke mid-button — "tuhle fázi" over two lines inside a
   32px chip, which is what the screenshot showed. A row that runs out of width should drop a
   control to the next line; a button should never fold its own label. */
.gttithe{display:flex;align-items:center;gap:10px;margin:0 0 12px;flex-wrap:wrap}
.gtt{white-space:nowrap;background:#2a2239;border:1px solid #6b4ea8;color:#e8e0cf;border-radius:7px;
  width:34px;height:32px;font-size:18px;cursor:pointer}
.gtt:hover{background:#3a2f4d}
.gttn{color:#e8e0cf;font-size:14px;min-width:90px}
.gttx{color:#8f88a0;font-size:12px}
/* Retirement lives in the gate panel — the most destructive button in the game, so it is
   walled off visually and needs two clicks. */
.rtbox{margin-top:18px;padding:14px;border:1px solid #4a2a2a;border-radius:9px;background:#1a1116}
.rtbox h3{margin:0 0 8px;color:#e0805a;font-size:15px}
.rtrows{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:8px 0 12px;font-size:13px;color:#a89f95}
.rtrows b{color:#ffd06a;font-size:15px;margin-left:auto}
.rtbtn{background:#241a1a;border:1px solid #6b3a3a;color:#e8d8cf;border-radius:7px;
  padding:9px 16px;font-size:14px;cursor:pointer;margin-right:8px}
.rtbtn:hover{background:#332323}
.rtbtn.armed{border-color:#e0402e;color:#ffd0c0;background:#3a1c18}

/* ---- The gathering web (58-grove.js). Square nodes, threads and a pinned tooltip — the
   idiom the owner asked for, and it is monospace on purpose: a constellation reads as a
   diagram, and a diagram in the body font reads as a form. ---- */
.gwwrap{width:100%;overflow:hidden}
/* Capped, because at full panel width on a monitor the web was a metre tall and the action
   row under it fell off the bottom of the screen. */
/* ⚠ THIS ONE NUMBER SETS THE ON-SCREEN SIZE OF EVERYTHING IN THE WEB — nodes, labels, the
   tooltip, the lot — because the svg geometry is in viewBox units and scales with its width.
   Raised from 600 on the owner's call: at that width the whole constellation fitted a laptop
   and every label was small enough to squint at. It is not meant to fit; the panel scrolls,
   and the only control that must stay in view is the buy button, which is why the action row
   is above the web. Do not "fix" the scrolling by shrinking this again. */
.gwwrap{max-width:1180px;margin:0 auto}
/* ⚠ touch-action:none, OR THE PHONE SCROLLS THE PAGE INSTEAD OF PANNING THE WEB. The browser
   claims a vertical drag for scrolling before the pointermove handler ever sees it; this is the
   only way to take it back. It costs the ability to scroll the panel by dragging ON the web —
   which is the trade the drag exists to make, and there is page above and below it either way. */
/* =========================================================================================
   THE WEB, IN THE GAME'S OWN LANGUAGE (owner, 2026-08-09: "a mohli bychom držet stejný
   grafický styl jako ve hře?")

   It could not, and the reason was one line: every glyph in here was ui-monospace. A console
   typeface is the single loudest way a screen can say "this is a tool, not the game" — and it
   was on the labels, the tooltip, the numbers, all of it. The rest followed from the same
   habit: flat charcoal squares with a hairline, dashed grey threads, a mint-green highlight
   band. A diagram of a skill tree rather than a thing in Gloamhold.

   Four rules taken from what the game already does, not invented here:
     · TYPE — Georgia, letter-spaced, for anything that names something (every heading in this
       game is), Verdana for small readouts. Same pairing as the panels and the HUD.
     · LIGHT COMES FROM ABOVE — 24f-menu.js says it out loud about the gate's masonry, and every
       stone block in the game is drawn with a lit top edge and a dark bottom one. Nodes are
       stone, so nodes get it too.
     · EMBER, NOT NEON — the palette is --ember/--gold/--blood over dark stone. The mint-green
       accents went; a taken node glows in its own arm's colour the way the gate's runes do.
     · BLOCKS, NOT CHIPS — no rounded corners. The masonry in this game is cut, not moulded.
   ========================================================================================= */
/* ⚠ touch-action:none, OR THE PHONE SCROLLS THE PAGE INSTEAD OF PANNING THE WEB. The browser
   claims a vertical drag for scrolling before the pointermove handler ever sees it; this is the
   only way to take it back. It costs the ability to scroll the panel by dragging ON the web —
   which is the trade the drag exists to make, and there is page above and below it either way. */
.gweb{width:100%;height:auto;display:block;font-family:Georgia,'Times New Roman',serif;
  touch-action:none;cursor:grab;user-select:none;-webkit-user-select:none}
.gweb:active{cursor:grabbing}
.gwdraghint{font:italic 22px Georgia,serif;fill:#8d8398;opacity:.7;pointer-events:none;
  letter-spacing:2px}

/* ⚠ DASHED AND THIN ON PURPOSE — see the note in 58-grove.js. Solid, these read as unlock
   paths between arms, which is a rule the game does not have. */
.gwthread{stroke:#221d2c;stroke-width:1.5;stroke-dasharray:4 9}
.gwthread.on{stroke:#3a3244}

/* The spoke is masonry too: a dark channel with the arm's light running in it once taken. */
.gwline{stroke:#2a2530;stroke-width:7;stroke-linecap:square}
.gwline.on{stroke-width:9;filter:url(#gwGlow)}

/* ---- a node is a cut block ---- */
.gwnode{cursor:pointer}
.gwnode rect{fill:#211c28;stroke:#171320;stroke-width:3}
.gwnode .gwtop{stroke:rgba(255,255,255,.10);stroke-width:3}      /* the lit top face */
.gwnode .gwbot{stroke:rgba(0,0,0,.45);stroke-width:3}            /* …and the shadowed foot */
.gwnode.far rect{fill:#1a1622;stroke:#141019}
.gwnode.far .gwic{opacity:.3}
.gwnode.far .gwtop{stroke:rgba(255,255,255,.05)}
/* The next one you may buy is lit like the gate's keystone: warm, and the only warm thing in
   an untaken arm. */
.gwnode.next rect{stroke:#8a6a34}
.gwnode.next{filter:url(#gwWarm)}
.gwnode.on rect{stroke-width:3}
.gwnode.on{filter:url(#gwGlow)}
.gwnode.sel rect{stroke:#e8c74a;stroke-width:4}
.gwnode:hover rect{stroke:#d4763c}
.gwic{font-size:30px;text-anchor:middle;fill:#e8e0cf}
/* The level, in the HUD's own small face — this is a readout, and the game sets readouts in
   Verdana (every counter on the bottom bar does). */
.gwlv{font:700 15px Verdana,sans-serif;fill:#c9bfae;text-anchor:middle;opacity:.9;
  pointer-events:none;letter-spacing:0}
.gwnode.max .gwlv{fill:#e8c74a}

/* ---- the root: the ember every arm is drawn out of ---- */
.gwroot rect{fill:#241009;stroke:#a5522a;stroke-width:4;cursor:pointer}
.gwroot{filter:url(#gwGlow)}
.gwroot.sel rect{stroke:#e8c74a}
.gwrt{font-size:44px;text-anchor:middle}

/* ---- names ---- */
.gwlabel{font:700 26px Georgia,serif;letter-spacing:4px}

/* ---- the reading plaque: an HTML popup ON the node it describes (58-grove.js) ----
   It carries the buy button, because the reading and the deciding belong to the same moment and
   the same place. Cut stone with the arm's colour down its edge, like every other readout here. */
.gwwrap{position:relative}
.gwpop{position:absolute;z-index:3;width:min(266px,72vw);
  background:linear-gradient(180deg,#1b1626,#120e19);border:1px solid var(--line);
  border-left:4px solid var(--arm,#a5522a);border-radius:3px;padding:11px 13px 12px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06),0 6px 20px rgba(0,0,0,.65);
  animation:gwPop .16s ease-out}
@keyframes gwPop{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:none}}
.gwpx{position:absolute;top:4px;right:5px;background:none;border:none;color:var(--dim);
  font:14px Verdana,sans-serif;cursor:pointer;line-height:1;padding:4px 6px}
.gwpx:hover{color:var(--ember)}
.gwpt{font:700 15px Georgia,serif;letter-spacing:1.5px;color:var(--arm,#e8c74a);
  padding-right:18px;line-height:1.3}
.gwpb{font:11px Verdana,sans-serif;color:var(--dim);letter-spacing:1px;margin-top:3px}
.gwpe{font:700 14px Verdana,sans-serif;color:#e8c74a;margin-top:7px;line-height:1.45}
.gwpn{font:11.5px Verdana,sans-serif;color:var(--dim);margin-top:4px;line-height:1.45}
.gwbuyrow{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:10px;
  border-top:1px solid var(--line);padding-top:9px}
.gwbuyrow .gwcost{font:700 13px Verdana,sans-serif;color:#e8dcc8;line-height:1.3}
.gwbuyrow .gwcost small{display:block;font-weight:400;font-size:10.5px;color:var(--dim)}
.gwpop .gwlock,.gwpop .gwown{margin-top:9px;border-top:1px solid var(--line);padding-top:9px;
  font:12px Verdana,sans-serif}
.gwfree{margin-left:auto;font:700 13px Verdana,sans-serif;color:#e8c74a;white-space:nowrap}

/* ---- the forge's quantity dial (axis 1, 53-craft.js) ----
   Only appears on a stack you have picked: a control on every row of a stock list is forty
   controls answering a question nobody has asked yet. */
.crmatwrap{display:flex;flex-direction:column;gap:0}
.crsteps{display:flex;align-items:center;justify-content:center;gap:7px;padding:4px 0 2px;
  font:700 12px Verdana,sans-serif;color:#e8dcc8}
.crstep{width:22px;height:22px;line-height:1;padding:0;border-radius:3px;cursor:pointer;
  background:var(--panel2);border:1px solid var(--line);color:var(--ink);font:700 13px Verdana,sans-serif}
.crstep:hover:not([disabled]){border-color:var(--ember);color:var(--ember)}
.crstep[disabled]{opacity:.3;cursor:default}
.crsteps em{font-style:normal;color:#5fd070;font-size:11px}

/* ---- repairs, in the smith's panel (73-wear.js) ---- */
.wearbox{margin-top:18px;border-top:1px solid var(--line);padding-top:12px}
.wtitle{font:700 14px Georgia,serif;letter-spacing:2px;color:var(--ember);margin-bottom:8px}
.wrow{display:flex;align-items:center;gap:10px;padding:7px 0;border-bottom:1px solid #241d33}
.wrow .ic{font-size:20px;width:26px;text-align:center}
.wrow .nm{flex:1;display:flex;flex-direction:column;gap:3px;font-size:13px}
.wrow .d{font:11px Verdana,sans-serif;color:var(--dim)}
.wrow.bad .d{color:#e0724a}
.wbar{height:5px;background:#241d33;border-radius:3px;overflow:hidden;max-width:220px}
.wbar i{display:block;height:100%;background:linear-gradient(90deg,#8a5a2a,#e6a24a)}
.wrow.bad .wbar i{background:linear-gradient(90deg,#7a2a1a,#e0724a)}
.wfix{min-width:74px}
.wfixall{margin-top:10px;width:100%}
.wnote{font:11px Verdana,sans-serif;color:var(--dim);line-height:1.55;margin-top:9px}
.wnone{margin-top:16px;font:12px Verdana,sans-serif;color:var(--dim);font-style:italic}
/* the forge's elemental-conversion promise (axis 4, 53-craft.js) */
/* the hat collection's filter chips and its count (33-hats.js) */
/* an unlearned pattern at the Craftsman's bench (53-craft.js) — shown, not hidden */
.crbase.unknown{opacity:.42;cursor:default;border-style:dashed}
.crbase.unknown:hover{border-color:var(--line)}

.hfilters{display:flex;flex-wrap:wrap;gap:7px;margin:10px 0 14px}
.hfilters .salvchip small{opacity:.7;font-weight:400}
.hcount{font:12px Verdana,sans-serif;color:var(--dim);letter-spacing:0;margin-left:8px}

.crconv{border-left:3px solid #c9bfae;background:rgba(255,255,255,.04);border-radius:3px;
  padding:7px 10px;margin:8px 0;font:12px Verdana,sans-serif;color:#c9bfae;line-height:1.5}

/* ---- the row under it ---- */
.gwact{display:flex;align-items:center;gap:14px;margin:0 0 8px;min-height:40px;flex-wrap:wrap}
.gwhint{color:#8f88a0;font-size:13px;font-style:italic}
.gwcost{color:#e8dcc8;font-size:15px}
.gwown{color:#8fd08f;font-size:15px}
.gwlock{color:#8f88a0;font-size:14px}
.gvbuy{background:linear-gradient(#e6a24a,#c4763c);border:1px solid var(--ember);color:#140b0b;
  font-family:inherit;font-weight:bold;letter-spacing:1px;border-radius:3px;
  padding:9px 20px;font-size:14px;cursor:pointer;text-shadow:0 1px 0 rgba(255,220,180,.45)}
.gvbuy:hover{box-shadow:0 0 18px rgba(212,118,60,.55)}
.gvbuy.poor{opacity:.4;background:#2a2239;color:#8f88a0;border-color:#4a4358;text-shadow:none}
@media(max-width:700px){.gweb{max-height:none}.gwact{margin-top:6px}}

/* ---- the shared account strip (59-profile.js) ---- */
.pfstrip{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px}
.pftab{background:#1a1526;border:1px solid #2e2740;color:#8f88a0;border-radius:8px;
  padding:8px 14px;font-size:14px;cursor:pointer;display:flex;align-items:center;gap:7px}
.pftab:hover{background:#241d33;color:#c8c2d4}
.pftab.on{border-color:#c9a227;color:#e8e0cf;background:#2a2239}
.pfi{font-size:15px}
@media(max-width:700px){.pftab{flex:1 1 auto;justify-content:center;padding:8px 8px;font-size:13px}}

/* Levels bank during a run and are spent in town (20-cards.js). The bar is the only place
   that says so, and in town it is also the button. */
#xpbar.cardsdue{box-shadow:0 0 0 1px rgba(232,199,74,.45)}
#xpbar.armed{box-shadow:0 0 0 2px #e8c74a, 0 0 14px rgba(232,199,74,.35);cursor:pointer}
#xpbar.armed:hover{box-shadow:0 0 0 2px #ffe9a0, 0 0 18px rgba(232,199,74,.5)}

/* ---- the death flipbook (61-flipbook.js) ---- */
#deathFlip{margin:0 auto 16px;max-width:min(760px,92vw)}
.flhead{color:#c9a227;font-size:13px;letter-spacing:2px;text-transform:uppercase;
  display:flex;align-items:baseline;gap:10px;margin-bottom:8px;justify-content:center;flex-wrap:wrap}
.flhint{color:#8f88a0;font-size:11px;letter-spacing:0;text-transform:none;font-style:italic}
.flbig{position:relative;border:1px solid #3a3350;border-radius:8px;overflow:hidden;background:#0b0a10}
.flbig canvas{display:block;width:100%;height:auto;image-rendering:auto}
.flcap{position:absolute;left:0;right:0;bottom:0;padding:6px 10px;font-size:12px;color:#e8dcc8;
  background:linear-gradient(transparent,rgba(8,6,12,.85))}
.flstrip{display:flex;gap:5px;margin-top:6px;overflow-x:auto;padding-bottom:4px}
.flthumb{position:relative;flex:0 0 84px;padding:0;border:1px solid #2e2740;border-radius:5px;
  background:#0b0a10;cursor:pointer;overflow:hidden;opacity:.6}
.flthumb canvas{display:block;width:100%;height:auto}
.flthumb:hover{opacity:.9}
.flthumb.on{opacity:1;border-color:#c9a227}
.flthumb.kill{border-color:#a53a2e}
.flthumb.kill.on{border-color:#e0402e}
.flt{position:absolute;left:0;right:0;bottom:0;font-size:10px;color:#cfc8dc;background:rgba(8,6,12,.75)}
@media(max-width:700px){.flthumb{flex:0 0 60px}}

/* ---- item search (63-itemsearch.js). Marks, never filters: the grid must not reflow while
   you type, or the thing you were looking at moves. ---- */
.isearch{display:flex;align-items:center;gap:10px;margin:0 0 8px}
.isearch input{flex:1;min-width:0;background:#12101a;border:1px solid #3a3350;color:#e8e0cf;
  border-radius:7px;padding:7px 11px;font-size:14px;font-family:inherit}
.isearch input:focus{outline:none;border-color:#c9a227}
.isn{color:#8f88a0;font-size:12px;white-space:nowrap}
.isearch.wide{grid-column:1/-1}
.slot.sdim{opacity:.22;filter:grayscale(.7)}
.slot.shit{box-shadow:0 0 0 2px #c9a227, 0 0 12px rgba(201,162,39,.45);z-index:1}

/* ---- The Renderer (64-convert.js) ---- */
.cvrow{display:flex;flex-wrap:wrap;gap:7px;margin:0 0 10px}
.cvfrom,.cvto{background:#1d1828;border:1px solid #3a3350;color:#c8c2d4;border-radius:8px;
  padding:8px 13px;font-size:14px;cursor:pointer;display:flex;align-items:center;gap:8px}
.cvfrom:hover,.cvto:hover{background:#241d33;color:#e8e0cf}
.cvfrom.on,.cvto.on{border-color:#7fb0d0;color:#e8e0cf;background:#1b2530}
.cvfrom b{color:#e0a04a}
.cvrate{color:#8f88a0;font-size:12px}
#convPanel .crgo{margin-right:8px}
/* The card-draft button: only in town, only when levels are owed (22-ui-helpers.js). */
/* ⚠ pointer-events:auto IS THE WHOLE FIX. #bottombar is pointer-events:none so the HUD does
   not eat clicks meant for the world, and every control in it opts back in individually —
   this one did not, so it looked like a button and swallowed nothing. It was also full-width
   and huge; it is a chip beside the bar now. */
#draftBtn{display:inline-block;margin:6px auto 0;padding:6px 14px;border-radius:8px;
  background:#2a2239;border:2px solid #e8c74a;color:#ffe9a0;font-size:13px;font-weight:700;
  cursor:pointer;pointer-events:auto;box-shadow:0 0 10px rgba(232,199,74,.3)}
#draftBtn:hover{background:#3a2f4d}
#draftBtn.hidden{display:none}
/* the count of unspent points, on the tab that spends them (65-heronav.js) */
.pfb{margin-left:7px;background:#c9a227;color:#1a1526;border-radius:9px;padding:1px 7px;
  font-size:11px;font-weight:700}

/* THE RITE (72-rite.js). Above the world and above the HUD, below nothing — for five seconds
   the gate taking a hero is the only thing on screen. `pointer-events` stays ON so a tap
   anywhere skips it; the canvas is the skip target. */
#riteCv{position:fixed;inset:0;width:100vw;height:100vh;z-index:120;cursor:pointer;
  transition:opacity .4s ease;}
#riteCv.gone{opacity:0;pointer-events:none;}

/* What the hero is carrying, above both Craftsman modes (craftCarryHtml, 53-craft.js).
   Wraps rather than scrolls: six material types on a phone is two rows, and a strip that
   scrolls sideways hides exactly the item you were looking for. */
.crcarry{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 8px;
  padding:6px 8px;background:#17121f;border:1px solid #2c2438;border-radius:8px;}
.crcarry .crcl{color:var(--dim);font-size:11px;letter-spacing:.5px;margin-right:2px;}
.crcarry .crcm{display:inline-flex;align-items:center;gap:4px;padding:2px 7px;
  background:#1e1829;border:1px solid #342b44;border-radius:6px;font-size:13px;}
.crcarry .crcm b{color:var(--gold);font-weight:600;font-variant-numeric:tabular-nums;}
.crcarry .crcm em{color:var(--dim);font-style:normal;font-size:10.5px;}
@media (max-width:560px){ .crcarry .crcm em{display:none;} }

/* The accepted totem challenge, in the descent-clock corner (totemHudLine, 49-totems.js).
   Its own colours because it is the one row there that is a CHOICE the player made — the clock
   and the events happen to you. */
#menaceReadout .tqrun{color:#e8c74a;}
#menaceReadout .tqrun b{color:#fff3c4;font-variant-numeric:tabular-nums;}
#menaceReadout .tqbad{color:#8d8398;text-decoration:line-through;}

/* The arm's own icon, small, in the node's top-right corner (58-grove.js). Six material arms
   share five rung glyphs, so without this "faster on stone" and "faster on gems" draw the same
   picture — this is the half that says WHICH. */
.gwarm{font-size:13px;text-anchor:end;fill:#e8e0cf;opacity:.85}
.gwnode.far .gwarm{opacity:.3}
/* An untaken node prints 0/n now, so it needs a colour that reads as "not yet" rather than as
   the taken ones' bright text. */
.gweb .gwnode.far .gwlv,.gweb .gwnode.next .gwlv{fill:#8d8398}

/* ---- the Elementalist (79-attune.js) ----------------------------------------------------
   ⚠ THE FIRST CUT BORROWED #floorOverlay's .dsrow/.dsk/.dsgo AND THEY ARE SCOPED TO THAT ID.
   Inside a panel they carry no styling at all, so the shop rendered as a column of unstyled
   inline text — "gold" and its number ran together into "zlato0" — and looked nothing like the
   rest of the game. Reported with a screenshot. Panel furniture lives here, in the same language
   as the Craftsman's bench next door, and the type is a size up from her: this screen is read
   standing still with money in hand, not scanned mid-fight.
   ⚠ ALL SIZES ARE ABSOLUTE, NOT INHERITED. The panel's own font-size is small so its dense
   material lists fit, and inheriting it is what made this unreadable in the first place. */
#attunePanel .atgold{display:flex;align-items:baseline;gap:12px;background:#1d1828;
  border:1px solid #3a3350;border-radius:9px;padding:11px 15px;margin:14px 0 6px;}
#attunePanel .atgk{color:#8f88a0;font-size:13px;text-transform:uppercase;letter-spacing:1.5px;}
#attunePanel .atgv{color:var(--gold);font-size:20px;font-weight:600;margin-left:auto;}
#attunePanel .athint{color:var(--dim);font-size:14px;line-height:1.6;font-style:italic;margin:10px 0 4px;}
#attunePanel h3{color:var(--ember);font-size:16px;font-weight:normal;letter-spacing:2.5px;
  text-transform:uppercase;margin:24px 0 10px;border-bottom:1px solid var(--line);padding-bottom:7px;}
#attunePanel .atnone{color:#8f88a0;font-size:14px;font-style:italic;padding:4px 2px 8px;}
/* One row per thing that can be re-elemented. Its left edge is the element it is made of, four
   pixels wide — the fastest possible read of "what am I now", before any word is processed. */
#attunePanel .atrow{display:flex;align-items:center;gap:12px;width:100%;text-align:left;
  background:#1d1828;border:1px solid #3a3350;border-left-width:4px;border-radius:8px;
  padding:12px 15px;margin-bottom:7px;cursor:pointer;transition:border-color .12s,background .12s;}
#attunePanel .atrow:hover{background:#241d33;border-color:#6b4ea8;}
#attunePanel .atrow.on{background:#241d33;border-color:#c9a227;}
#attunePanel .atname{color:#e8e0cf;font-size:16px;font-weight:600;}
#attunePanel .atel{font-size:14px;}
#attunePanel .atmeta{color:#8f88a0;font-size:14px;margin-left:auto;white-space:nowrap;}
#attunePanel .atcost{color:var(--gold);}
/* The six blades. A grid so they read as a rack of choices rather than as a list of menu items,
   which is the same thing the swords outside the door are doing. */
#attunePanel .atgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:8px;
  margin:2px 0 16px;padding:12px;background:#171320;border:1px solid #6b4ea8;border-radius:9px;}
#attunePanel .atbl{display:flex;flex-direction:column;gap:3px;align-items:flex-start;
  background:#211b2e;border:1px solid #3a3350;border-bottom-width:3px;border-radius:7px;
  padding:10px 13px;cursor:pointer;text-align:left;transition:transform .1s,border-color .12s;}
#attunePanel .atbl:hover:not(:disabled){transform:translateY(-2px);border-color:#c9a227;}
#attunePanel .atbl:disabled{opacity:.35;cursor:default;}
#attunePanel .atbn{font-size:16px;font-weight:600;}
#attunePanel .atbv{color:#8f88a0;font-size:13px;}
@media (max-width:720px){
  #attunePanel .atname,#attunePanel .atbn{font-size:15px;}
  #attunePanel .atmeta{font-size:13px;}
  /* The meta drops under the name rather than fighting it for width — the price is the thing
     that would otherwise wrap into nonsense on a phone. */
  #attunePanel .atrow{flex-wrap:wrap;}
  #attunePanel .atmeta{margin-left:0;width:100%;}
}

/* ---- the tutorial's short version (69-tutorial.js) --------------------------------------
   A manual is not read top to bottom: it is opened because something already went wrong,
   scanned, and closed. This block is the whole game in nine lines, set apart from the body so
   the eye lands on it first and so it is obvious where the summary stops and the detail begins. */
#floorOverlay .tutldr{list-style:none;margin:4px 0 22px;padding:14px 16px;
  background:#171320;border:1px solid #6b4ea8;border-radius:9px;}
#floorOverlay .tutldr li{color:#c8c2d4;font-size:15px;line-height:1.55;padding:5px 0 5px 20px;
  position:relative;}
#floorOverlay .tutldr li+li{border-top:1px solid rgba(107,78,168,0.22);}
#floorOverlay .tutldr li:before{content:'·';position:absolute;left:6px;color:#c9a227;font-weight:700;}
#floorOverlay .tutldr b{color:#e8e0cf;}
@media (max-width:720px){ #floorOverlay .tutldr li{font-size:14px;} }

/* ---- the material stock, as a grid (23-panels.js matLine) --------------------------------
   Reported with a screenshot: six types x six grades x raw-or-refined is 72 stacks, and the old
   run-on sentence wrapped over fourteen unreadable lines. A player checking what they have is
   answering "do I have four Pristine Wood", which is a lookup, and a lookup wants a table.
   ⚠ It scrolls INSIDE itself rather than widening the panel — the inventory has to survive a
   phone, and the row of grade headings is the widest thing in it. */
.matgrid{display:block;margin:8px 0 4px;overflow-x:auto;max-width:100%;}
.matgrid .mgrow{display:grid;grid-template-columns:8.5em repeat(6,minmax(4.6em,1fr));
  gap:2px;align-items:baseline;min-width:38em;}
.matgrid .mgrow+.mgrow{border-top:1px solid rgba(58,51,80,0.5);}
.matgrid .mghead{border-bottom:1px solid var(--line);margin-bottom:3px;padding-bottom:3px;}
.matgrid .mghead .mgc{font-size:11px;text-transform:uppercase;letter-spacing:.6px;opacity:.85;}
.matgrid .mgt{color:#c8c2d4;font-size:13px;font-weight:600;padding:3px 0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.matgrid .mgc{font-size:13px;padding:3px 0;text-align:right;font-variant-numeric:tabular-nums;}
.matgrid .mgnil{color:#4a4458;}
/* Refined is the one distinction the crafting economy is built on — ten raw make one refined —
   and it was invisible: a refined stack rendered identically to a raw one, which is why the
   screenshot showed "Ancient Ash" twice in a row. */
.matgrid .mgref{display:block;font-style:normal;font-size:11px;color:#b98af8;}
@media (max-width:720px){
  .matgrid .mgrow{grid-template-columns:7em repeat(6,minmax(4em,1fr));min-width:32em;}
  .matgrid .mgt,.matgrid .mgc{font-size:12px;}
}

@media (max-width:720px){
  /* The subtitle stops floating beside the title on a narrow screen — at 13px it would squeeze
     the heading into two characters a line. */
  .phint{float:none;display:block;max-width:100%;margin-top:6px;font-size:12px;}
}

/* ---- the Craftsman's batch bar (53-craft.js) ---------------------------------------------
   The bench made one piece per click; a player with materials for forty clicked forty times.
   It fills, makes one, and the next takes 90% as long as the last — the Renderer's shape, at
   the 10% step the owner asked for rather than the vat's 28%: the vat boils sludge, the bench
   makes a thing, and a slower hand there is right. */
#craftPanel .crbarwrap{height:6px;background:#171320;border:1px solid #3a3350;border-radius:4px;
  overflow:hidden;margin:12px 0 8px;}
#craftPanel .crbar{display:block;height:100%;width:0;background:linear-gradient(90deg,#6b4ea8,#c9a227);
  transition:width .05s linear;}

/* The material that would teach a locked pattern, printed on the button itself. It lived only in
   a `title` — invisible on touch, absent from a screenshot, and unreachable on a disabled
   control, which is a lock with a hidden key. */
#craftPanel .crbase .crneed{display:inline-block;margin-left:5px;font-size:11px;color:#8f88a0;
  letter-spacing:.3px;text-transform:none;}
#craftPanel .crbase.unknown{opacity:.62;}

/* ---- the rarity ladder on the Craftsman's bench (53-craft.js) ----------------------------
   The rule was knowable only by trying combinations and reading the result. It is three facts —
   how many DIFFERENT types, whether every piece is refined, whether an Ancient is among them —
   and now they are written down, with the row you are currently on marked. */
#craftPanel .crladders{background:#171320;border:1px solid #3a3350;border-radius:9px;
  padding:10px 12px;margin:10px 0;}
#craftPanel .crladdert{color:#8f88a0;font-size:11px;text-transform:uppercase;letter-spacing:1.2px;
  margin-bottom:7px;}
#craftPanel .crladder{display:grid;grid-template-columns:7.5em 1fr;gap:10px;align-items:baseline;
  padding:4px 6px;border-radius:5px;font-size:13px;}
#craftPanel .crladder span{color:#8f88a0;}
#craftPanel .crladder.on{background:#241d33;outline:1px solid #c9a227;}
#craftPanel .crladder.on span{color:#c8c2d4;}

/* Each material group states its PURPOSE. Both lists used to be headed by a noun and nothing
   else, so nothing anywhere taught that salvage is what items break into and gathered is what
   places grow — the one distinction the whole economy turns on. */
.matwhat{display:block;color:#8f88a0;font-size:12px;text-transform:uppercase;letter-spacing:1px;
  margin:10px 0 4px;}

/* ---- the Renderer's steps (64-convert.js) ------------------------------------------------
   Three unlabelled rows of buttons in a column read as three sets of inputs, so a player
   reasonably concluded the machine ate all of them — including the row that is only their own
   stock, shown to inform the choice. A row of controls with no heading is a question answered
   by experiment. */
#convPanel .cvstep{color:#8f88a0;font-size:12px;text-transform:uppercase;letter-spacing:1.1px;
  margin:14px 0 5px;}
#convPanel .cvstep.cvstock-h{color:#6f6880;text-transform:none;letter-spacing:.3px;
  font-style:italic;font-size:12px;margin-top:10px;}

/* The refined half of a pile, beside the raw. convRawStock deliberately excludes refined — it
   counts what the vat can eat — so every readout on this page was built from it and showed only
   raw. The player could not see how much they had of the thing they were making. */
#convPanel .cvhave .cvref{display:inline-block;margin-left:6px;font-style:normal;font-size:11px;
  color:#b98af8;}
/* What one turn adds, what this run adds, and what the pile ends at. A recipe alone answers none
   of those once the dial is anything but one. */
#convPanel .cvtot{color:#8fd08f;font-size:13px;margin:2px 0 8px;}

/* The three axes, printed where the decision is made. A rule a player can only learn by keeping
   notes across twenty crafts is a rule the game has not taught. */
#craftPanel .craxes .crax{display:grid;grid-template-columns:11em 1fr;gap:10px;align-items:baseline;
  padding:5px 6px;font-size:13px;}
#craftPanel .craxes .crax+.crax{border-top:1px solid rgba(58,51,80,0.5);}
#craftPanel .craxes .crax b{color:#e8e0cf;}
#craftPanel .craxes .crax span{color:#8f88a0;line-height:1.5;}
@media (max-width:720px){ #craftPanel .craxes .crax{grid-template-columns:1fr;gap:2px;} }

/* ---- target-first crafting (53-craft.js) --------------------------------------------------
   You arrive at a bench wanting a thing, not wanting to spend a particular pile. The
   seventy-two-row stock list is still reachable — it was never wrong, only wrong as the first
   thing you meet. */
#craftPanel .crtgt{background:#1d1828;border:1px solid #3a3350;border-radius:9px;padding:12px 14px;}
#craftPanel .crtgt .crladdert{color:#8f88a0;font-size:11px;text-transform:uppercase;
  letter-spacing:1.2px;margin:12px 0 6px;}
#craftPanel .crtgt .crladdert:first-child{margin-top:0;}
#craftPanel .crtake{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0 4px;}
#craftPanel .crtakes{background:#171320;border:1px solid #3a3350;border-radius:6px;
  padding:5px 10px;font-size:13px;}
#craftPanel .crmanual{margin-top:14px;opacity:.75;font-size:12px;}
#craftPanel .crslot.unknown{opacity:.4;}

/* ---- the Ancient confirmation (53-craft.js) -----------------------------------------------
   Only Ancient prompts. A confirmation on every craft is a click people learn to make without
   reading, which would cost exactly the case it exists for. */
#craftPanel .crconfirm{background:#1f1620;border:1px solid #a53a2e;border-radius:9px;
  padding:12px 14px;margin-top:10px;}
#craftPanel .crconfirmt{color:#e8e0cf;font-size:14px;margin-bottom:8px;}
#craftPanel .crtakes.crancient{border-color:#e0a04a;background:#241d14;}
#craftPanel .crancw{color:#e0a04a;font-size:11px;letter-spacing:1px;margin-left:4px;}
#craftPanel .crgoanc{border-color:#a53a2e;margin-right:8px;}
/* The line that spends is dimmer than the line that gains — a stock readout is read for what it
   produces, and the cost is the footnote to it. */
#convPanel .cvtot.cvtotraw{color:#8f88a0;}
/* The grade picker. Its own class, because .cvto is the TYPE picker's and a shared class means a
   shared handler — these two controls mean different things. */
#convPanel .cvgr{background:#211b2e;border:1px solid #3a3350;border-radius:7px;color:#c8c2d4;
  padding:6px 11px;font-size:13px;cursor:pointer;}
#convPanel .cvgr.on{border-color:#c9a227;background:#2a2239;}
#convPanel .cvgr b{margin-left:6px;}
/* The batch dial. Buttons for nudges, a slider to get near, a box to say exactly — at twelve
   thousand batches the buttons alone had two useful positions. */
#convPanel .cvqi{width:6.5em;background:#171320;border:1px solid #3a3350;border-radius:6px;
  color:#e8e0cf;padding:5px 8px;font-size:14px;font-variant-numeric:tabular-nums;text-align:right;}
#convPanel .cvqs{display:block;width:100%;margin:8px 0 4px;accent-color:#c9a227;}

/* ---- the manual material picker, as a grid (53-craft.js) ---------------------------------
   Seventy-two rows in which raw and refined looked identical: long AND ambiguous, the worst
   pair. One row per type, one column per grade, both kinds in the cell and separately clickable. */
#craftPanel .crgrid .mgrow{grid-template-columns:9em repeat(6,minmax(5.4em,1fr));}
#craftPanel .crcell{display:flex;gap:3px;justify-content:flex-end;align-items:center;}
#craftPanel .crpick{background:#1d1828;border:1px solid #3a3350;border-radius:5px;color:#c8c2d4;
  padding:3px 6px;font-size:12px;cursor:pointer;font-variant-numeric:tabular-nums;}
#craftPanel .crpick.on{border-color:#c9a227;background:#2a2239;color:#e8e0cf;}
#craftPanel .crpick.thin{opacity:.4;}
#craftPanel .crpick b{margin-left:4px;color:#c9a227;}
#craftPanel .crnil{color:#3a3448;font-style:normal;font-size:12px;padding:0 4px;}
#craftPanel .crpicked{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;}
#craftPanel .crpicked .crsteps{display:flex;align-items:center;gap:5px;background:#1d1828;
  border:1px solid #3a3350;border-radius:7px;padding:5px 9px;font-size:13px;}
#craftPanel .crpicked .crsteps em{font-style:normal;}
#craftPanel .crqty{display:flex;align-items:center;gap:6px;margin:12px 0 4px;}

/* ---- what a crafted piece may roll on top of its material marks (53-craft.js) -------------
   The panel promised "4-5 affixes" and described three. These are the ones the piece rolls for
   itself: the menu, not the meal. Dimmer than the guaranteed marks, because that is the
   distinction — one you are buying, the other you are hoping for. */
#craftPanel .crmaywrap{background:#171320;border:1px solid #3a3350;border-radius:9px;
  padding:10px 12px;margin:8px 0;display:flex;flex-wrap:wrap;gap:6px;}
#craftPanel .crmayt{width:100%;color:#8f88a0;font-size:11px;text-transform:uppercase;
  letter-spacing:1.1px;margin-bottom:2px;}
#craftPanel .crmay{background:#1d1828;border:1px solid #3a3350;border-radius:6px;
  padding:4px 9px;font-size:12px;color:#a79ab8;}
#craftPanel .crmay b{color:#c8c2d4;}
/* The larder in the inventory is folded away by default: twelve materials by six grades pushed
   the gear, the salvage controls and the search box below the fold, in a panel whose job is gear. */
.matfold{display:block;background:#1d1828;border:1px solid #3a3350;border-radius:7px;
  color:#a79ab8;padding:6px 11px;font-size:13px;cursor:pointer;margin:2px 0 6px;}
.matfold:hover{border-color:#6b4ea8;color:#c8c2d4;}
.matgrid.hidden{display:none;}

/* ---- the hero strip stays put (65-heronav.js) --------------------------------------------
   It is inserted directly under each panel's heading, which is correct — but the heading is
   sticky and the strip was not, so in a long panel it scrolled away and the player found it at
   the bottom of the page. Reported as "dole kliknes na skills, pak se ti nahore objevi dvoji
   menu": one strip pinned, one gone, and the same three names in two places. */
.panel > .heronav{position:sticky;top:34px;z-index:3;background:rgba(14,10,20,.99);
  padding:8px 0 10px;}
.panel > .heronav:empty{display:none;}
.panel > .heronav .pfstrip{margin:0;}
/* The item level a grade floor produces, on its button. It read "Roughilvl 17": a literal space
   before an inline element is collapsed by the wrap, and the number — the thing the button is
   actually chosen on — was the same weight as the label. */
#craftPanel .crslot .crilvl{margin-left:7px;opacity:.85;}
#craftPanel .crslot .crilvl b{color:#e8e0cf;font-weight:700;}

/* The World-Eater, on the finished gate (56-gate.js). It sits ABOVE the retire block and has to
   out-shout it: ten phases of stone were paid for to open this, and until now the only button on
   the finished panel was the one that gives another hero away. */
.gtwe{margin:14px 0;padding:14px 16px;border:1px solid #6a3a8a;border-radius:10px;
      background:linear-gradient(180deg,rgba(120,40,160,.20),rgba(20,8,26,.55))}
.gtwe h4{margin:0 0 6px;color:#d79bff;font:700 17px Georgia,serif;letter-spacing:.4px}
.gtwe p{margin:0 0 8px;color:#c8bcd4;font:italic 13px/1.5 Georgia,serif}
.gtwelv{color:#ffb02a;font:700 13px Verdana,sans-serif;margin-bottom:6px}
.gtwewarn{color:#e0503a;font:700 12px Verdana,sans-serif;margin-bottom:10px}
.gtwego{width:100%;padding:12px 16px;border:1px solid #a05ad0;border-radius:8px;cursor:pointer;
        background:linear-gradient(180deg,#7a2ea8,#4a1668);color:#fff;
        font:700 16px Verdana,sans-serif;letter-spacing:.5px}
.gtwego:hover{background:linear-gradient(180deg,#9040c8,#5a1c80)}
.gtwego[disabled]{opacity:.45;cursor:default}
