/* ============================================================
   CHLOE — The Backstage Between  (game/css/game.css)
   Neon-noir nightclub. Palette per GAME_SPEC.md sec 8.
   ============================================================ */

:root{
  --bg:        #0a0a0c;
  --panel:     #141317;
  --panel-2:   #1b1a20;
  --red:       #e5173f;
  --deep-red:  #7a0c22;
  --text:      #f2eef0;
  --dim:       #9a939c;
  --ok:        #3ddc84;
  --mp:        #3fa9f5;
  --gold:      #e8c15a;
  --font-head: 'Bebas Neue','Oswald',Impact,"Arial Narrow",sans-serif;
  --font-body: system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --glow-red:  0 0 12px rgba(229,23,63,.55), 0 0 34px rgba(229,23,63,.25);
}

*{ margin:0; padding:0; box-sizing:border-box; }
html,body{ height:100%; }
body{
  background:var(--bg);
  color:var(--text);
  font-family:var(--font-body);
  font-size:clamp(14px,1.6vw,16px);
  line-height:1.45;
  overflow:hidden;
  -webkit-font-smoothing:antialiased;
  user-select:none;
}
img{ max-width:100%; }
button{
  font-family:var(--font-body);
  color:var(--text);
  background:#17151b;
  border:1px solid var(--deep-red);
  border-radius:6px;
  padding:.55em 1.1em;
  font-size:1em;
  cursor:pointer;
  transition:background .15s ease, border-color .15s ease, box-shadow .15s ease, transform .06s ease;
}
button:hover:not(:disabled){
  background:var(--red);
  border-color:var(--red);
  color:#fff;
  box-shadow:var(--glow-red);
}
button:active:not(:disabled){ transform:translateY(1px); }
button:disabled{ opacity:.38; cursor:default; }
input[type=text],input[type=password]{
  background:#0e0d11;
  border:1px solid #322e38;
  border-radius:6px;
  color:var(--text);
  padding:.55em .8em;
  font-size:1em;
  width:100%;
  outline:none;
}
input[type=text]:focus{ border-color:var(--red); box-shadow:0 0 0 2px rgba(229,23,63,.25); }
::-webkit-scrollbar{ width:8px; height:8px; }
::-webkit-scrollbar-thumb{ background:#39343f; border-radius:4px; }
::-webkit-scrollbar-track{ background:transparent; }

/* ---------- App frame & screens ---------- */
#app{ position:fixed; inset:0; overflow:hidden; }
.screen{
  position:absolute; inset:0;
  display:none;
  opacity:0;
  transition:opacity .35s ease;
}
.screen.active{ display:block; opacity:1; }

/* film grain + vignette overlay */
#fx-grain{
  position:absolute; inset:0;
  pointer-events:none;
  z-index:90;
  overflow:hidden;
  background:
    radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,.55) 100%);
}
#fx-grain::after{
  content:"";
  position:absolute; inset:-50%;
  opacity:.05;
  background-image:repeating-conic-gradient(#fff 0% .0001%, transparent .0002% .0004%);
  background-size:7px 7px;
  animation:grain 1.4s steps(4) infinite;
  will-change:transform;
}
@keyframes grain{
  0%{ transform:translate(0,0); } 25%{ transform:translate(-2%,1%); }
  50%{ transform:translate(1%,-2%); } 75%{ transform:translate(-1%,2%); } 100%{ transform:translate(2%,1%); }
}

.hidden{ display:none !important; }

h1,h2,h3,.head{
  font-family:var(--font-head);
  letter-spacing:.06em;
  font-weight:400;
  text-transform:uppercase;
}

/* ---------- Title screen ---------- */
#screen-title{
  background:#050507;
  display:none;
  align-items:center; justify-content:center;
}
#screen-title.active{ display:flex; }
.title-bg{
  position:absolute; inset:0;
  background-size:cover; background-position:center 20%;
  opacity:.35;
  filter:saturate(.8) contrast(1.1);
}
.title-bg::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(180deg, rgba(5,5,7,.2) 0%, rgba(5,5,7,.85) 78%, #050507 100%);
}
.title-inner{
  position:relative; z-index:2;
  text-align:center;
  padding:2rem;
  animation:titleRise 1s ease both;
}
@keyframes titleRise{ from{ opacity:0; transform:translateY(18px); } to{ opacity:1; transform:none; } }
.title-logo{
  font-family:var(--font-head);
  font-size:clamp(4rem,16vw,9rem);
  line-height:.9;
  color:var(--red);
  text-shadow:var(--glow-red);
  letter-spacing:.12em;
}
.title-sub{
  font-family:var(--font-head);
  font-size:clamp(1.1rem,3.5vw,1.7rem);
  letter-spacing:.42em;
  color:var(--dim);
  margin:.6rem 0 2.4rem;
}
.title-start{
  font-family:var(--font-head);
  font-size:clamp(1.2rem,3vw,1.6rem);
  letter-spacing:.2em;
  padding:.5em 1.6em;
  animation:pulse 2.2s ease-in-out infinite;
}
@keyframes pulse{ 0%,100%{ box-shadow:0 0 0 rgba(229,23,63,0);} 50%{ box-shadow:var(--glow-red);} }
.title-foot{
  position:absolute; bottom:1rem; left:0; right:0;
  text-align:center; color:#565059; font-size:.75rem; z-index:2;
}
.title-notes{
  position:relative; z-index:2;
  max-width:28rem; margin:0 auto 1.2rem;
  padding:.65rem 1rem;
  background:rgba(255,255,255,.04);
  border:1px solid rgba(255,255,255,.06);
  border-radius:6px;
  font-size:.72rem; line-height:1.55;
  color:#888088; letter-spacing:.02em;
  text-transform:none; text-align:left;
}
.title-notes b{ color:#b0a0a8; text-transform:uppercase; letter-spacing:.06em; }
.title-notes li{ margin:.15rem 0 .15rem .8rem; }

/* ---------- Scene screen ---------- */
#screen-scene{ background:#000; }
.scene-stage{
  position:absolute; inset:0;
  display:flex; align-items:center; justify-content:center;
  overflow:hidden;
}
.scene-imgbox{
  position:relative;
  width:100%; height:100%;
}
.scene-bg{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover; object-position:center 30%;
  animation:sceneIn .55s ease both;
}
@keyframes sceneIn{ from{ opacity:0; transform:scale(1.03); } to{ opacity:1; transform:none; } }
.scene-bg-fallback{
  position:absolute; inset:0;
  background:radial-gradient(900px 500px at 50% 30%, #2a0d18 0%, #0a0a0c 70%);
}
.scene-name{
  position:absolute; left:50%; top:12%;
  transform:translateX(-50%);
  font-family:var(--font-head);
  font-size:clamp(1.4rem,4vw,2.3rem);
  letter-spacing:.3em;
  color:var(--text);
  text-shadow:0 0 18px rgba(229,23,63,.8), 0 2px 8px #000;
  opacity:0;
  pointer-events:none;
  z-index:6;
  animation:sceneName 3s ease .3s both;
}
@keyframes sceneName{
  0%{ opacity:0; transform:translateX(-50%) translateY(8px); }
  12%,70%{ opacity:1; transform:translateX(-50%); }
  100%{ opacity:0; transform:translateX(-50%) translateY(-6px); }
}
/* hotspots */
.hotspot{
  position:absolute;
  z-index:5;
  border:1px solid rgba(229,23,63,0);
  border-radius:8px;
  cursor:pointer;
  transition:border-color .2s, background .2s, box-shadow .2s;
  background:rgba(229,23,63,.0);
}
.hotspot::before{ /* soft idle shimmer so hotspots are findable */
  content:"";
  position:absolute; inset:0;
  border-radius:8px;
  box-shadow:inset 0 0 22px rgba(229,23,63,.16);
  opacity:.55;
  animation:hsIdle 2.6s ease-in-out infinite;
}
@keyframes hsIdle{ 0%,100%{ opacity:.15; } 50%{ opacity:.6; } }
.hotspot:hover{
  border-color:rgba(229,23,63,.85);
  background:rgba(229,23,63,.10);
  box-shadow:var(--glow-red);
}
.hotspot .hs-label{
  position:absolute; left:50%; bottom:calc(100% + 8px);
  transform:translateX(-50%) translateY(4px);
  background:rgba(10,10,12,.92);
  border:1px solid var(--deep-red);
  color:var(--text);
  font-size:.8rem;
  letter-spacing:.06em;
  padding:.3em .7em;
  border-radius:5px;
  white-space:nowrap;
  opacity:0; pointer-events:none;
  transition:opacity .18s, transform .18s;
}
.hotspot:hover .hs-label{ opacity:1; transform:translateX(-50%); }
/* HUD */
.hud{
  position:absolute; top:0; left:0; right:0;
  display:flex; align-items:center; justify-content:space-between;
  padding:.7rem .9rem;
  z-index:8;
  background:linear-gradient(180deg, rgba(5,5,7,.75), transparent);
}
.hud-shards{
  font-family:var(--font-head);
  font-size:1.25rem; letter-spacing:.1em;
  color:var(--gold);
  text-shadow:0 0 10px rgba(232,193,90,.4);
}
.hud-right{ display:flex; gap:.5rem; }
.hud button{ padding:.35em .9em; font-size:.9rem; }

/* ---------- Dialog box ---------- */
#dialog-layer{
  position:absolute; left:0; right:0; bottom:0;
  z-index:40;
  padding:0 clamp(.5rem,3vw,2.5rem) clamp(.6rem,2.5vh,1.6rem);
  cursor:pointer;
}
.dialog-box{
  display:flex; gap:1rem;
  max-width:900px; margin:0 auto;
  background:rgba(16,14,19,.94);
  border:1px solid #35303c;
  border-left:3px solid var(--red);
  border-radius:10px;
  padding:.9rem 1.1rem;
  min-height:108px;
  box-shadow:0 12px 44px rgba(0,0,0,.7);
  animation:dlgIn .25s ease both;
}
@keyframes dlgIn{ from{ opacity:0; transform:translateY(14px); } to{ opacity:1; transform:none; } }
.dialog-portrait{
  flex:0 0 74px; height:74px;
  border-radius:8px; overflow:hidden;
  border:1px solid var(--deep-red);
  background:#0d0c10;
  align-self:flex-start;
}
.dialog-portrait img{ width:100%; height:100%; object-fit:cover; object-position:center 12%; }
.dialog-portrait .avatar-fallback{ width:100%; height:100%; }
.dialog-main{ flex:1; min-width:0; }
.dialog-speaker{
  font-family:var(--font-head);
  color:var(--red);
  font-size:1.1rem;
  letter-spacing:.14em;
  margin-bottom:.15rem;
}
.dialog-text{ color:var(--text); min-height:2.6em; }
.dialog-next{
  text-align:right; color:var(--dim); font-size:.78rem;
  animation:blink 1.2s steps(2) infinite;
}
@keyframes blink{ 50%{ opacity:.15; } }

/* avatar fallback (missing portrait / enemy silhouette base) */
.avatar-fallback{
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-head);
  font-size:1.8rem;
  color:var(--red);
  background:radial-gradient(circle at 50% 32%, #33101c 0%, #120a0f 75%);
  text-shadow:var(--glow-red);
  width:100%; height:100%;
}

/* ---------- Battle screen ---------- */
#screen-battle{
  background:
    radial-gradient(1100px 600px at 70% 12%, #2b0d1a 0%, transparent 60%),
    radial-gradient(800px 500px at 15% 95%, #190a12 0%, transparent 55%),
    var(--bg);
  display:none;
  flex-direction:column;
}
#screen-battle.active{ display:flex; }
#screen-battle::after{ /* CRT scanlines */
  content:"";
  position:absolute; inset:0;
  pointer-events:none;
  z-index:60;
  background:repeating-linear-gradient(180deg,
    rgba(255,255,255,.028) 0px, rgba(255,255,255,.028) 1px,
    transparent 1px, transparent 4px);
  mix-blend-mode:overlay;
}
#screen-battle.shake{ animation:screenShake .42s ease; will-change:transform; }
@keyframes screenShake{
  0%,100%{ transform:translate(0,0); }
  15%{ transform:translate(-10px,4px); } 30%{ transform:translate(9px,-5px); }
  45%{ transform:translate(-7px,-3px); } 60%{ transform:translate(6px,4px); }
  75%{ transform:translate(-4px,2px); } 90%{ transform:translate(2px,-1px); }
}
.battle-top{
  flex:1 1 55%;
  display:flex;
  align-items:center;
  justify-content:flex-end;
  padding:clamp(.8rem,3vh,2rem) clamp(1rem,6vw,5rem) 0;
  position:relative;
  min-height:0;
  overflow:hidden;
}
.enemy-wrap{
  position:relative;
  text-align:center;
  margin-right:clamp(0px,4vw,3rem);
  animation:enemyIn .5s ease both;
}
@keyframes enemyIn{ from{ opacity:0; transform:translateX(40px);} to{ opacity:1; transform:none; } }
.enemy-imgbox{
  width:clamp(150px,32vh,300px);
  height:clamp(150px,32vh,300px);
  margin:0 auto .6rem;
  border-radius:12px;
  overflow:hidden;
  border:1px solid #3a3340;
  box-shadow:0 0 40px rgba(229,23,63,.22), 0 16px 40px rgba(0,0,0,.6);
  position:relative;
  background:#0d0c10;
}
.enemy-imgbox img{ width:100%; height:100%; object-fit:cover; display:block; }
.enemy-silhouette{
  position:absolute; inset:0;
  display:flex; align-items:flex-end; justify-content:center;
  background:radial-gradient(circle at 50% 35%, #3a1020 0%, #0d0b10 72%);
}
.enemy-silhouette::before{
  content:"";
  width:58%; height:74%;
  margin-bottom:-6%;
  background:#050507;
  border-radius:48% 48% 22% 22% / 62% 62% 14% 14%;
  box-shadow:0 0 34px rgba(229,23,63,.5);
}
.enemy-silhouette .sil-eyes{
  position:absolute; top:34%; left:50%; transform:translateX(-50%);
  display:flex; gap:14px;
}
.enemy-silhouette .sil-eyes i{
  width:9px; height:9px; border-radius:50%;
  background:var(--red);
  box-shadow:0 0 12px var(--red);
  animation:pulse 2s ease-in-out infinite;
}
.enemy-hit{ animation:enemyHit .35s ease; }
@keyframes enemyHit{
  0%,100%{ filter:none; transform:none; }
  30%{ filter:brightness(2.4) saturate(2); transform:translateX(7px); }
  60%{ transform:translateX(-5px); }
}
.enemy-dead{ animation:enemyDie .9s ease forwards; }
@keyframes enemyDie{ to{ opacity:0; transform:translateY(16px) scale(.94); filter:saturate(0) brightness(2); } }
.enemy-name{
  font-family:var(--font-head);
  font-size:1.35rem; letter-spacing:.14em;
}
.enemy-name .lv{ color:var(--dim); font-size:.95rem; margin-left:.5em; }
.enemy-hpbar{ width:min(240px,80%); margin:.35rem auto 0; }

/* bars */
.bar{
  height:12px;
  background:#0c0b0f;
  border:1px solid #38323e;
  border-radius:6px;
  overflow:hidden;
  position:relative;
}
.bar .fill{
  height:100%;
  background:linear-gradient(90deg, var(--deep-red), var(--red));
  border-radius:5px;
  transition:width .45s cubic-bezier(.2,.8,.3,1);
  box-shadow:0 0 8px rgba(229,23,63,.5);
}
.bar.mp .fill{
  background:linear-gradient(90deg,#144a74,var(--mp));
  box-shadow:0 0 8px rgba(63,169,245,.45);
}
.bar.hp-ok .fill{ background:linear-gradient(90deg,#1d7a45,var(--ok)); box-shadow:0 0 8px rgba(61,220,132,.4); }
.bar.hp-warn .fill{ background:linear-gradient(90deg,#8a6b12,var(--gold)); }
.bar-txt{ font-size:.72rem; color:var(--dim); display:flex; justify-content:space-between; gap:.4em; margin-top:2px; white-space:nowrap; }

/* bottom battle panel */
.battle-bottom{
  flex:0 0 auto;
  display:grid;
  grid-template-columns:minmax(230px,300px) minmax(180px,240px) minmax(0,1fr);
  gap:.8rem;
  padding:.8rem clamp(.6rem,2vw,1.4rem) calc(.8rem + env(safe-area-inset-bottom));
  background:linear-gradient(180deg, transparent, rgba(8,8,10,.92) 22%);
  align-items:stretch;
  z-index:5;
  min-width:0;
}
.bpanel{
  background:var(--panel);
  border:1px solid #2b2731;
  border-radius:10px;
  padding:.7rem .8rem;
  min-height:150px;
  min-width:0;
}
.member-panel{ display:flex; gap:.7rem; position:relative; }
.member-portrait{
  flex:0 0 84px; height:110px;
  border-radius:8px; overflow:hidden;
  border:1px solid var(--deep-red);
  background:#0d0c10;
  position:relative;
}
.member-portrait img{ width:100%; height:100%; object-fit:cover; object-position:center 10%; }
.member-info{ flex:1; min-width:0; display:flex; flex-direction:column; gap:.25rem; }
.member-name{
  font-family:var(--font-head);
  font-size:1.2rem; letter-spacing:.1em;
  display:flex; justify-content:space-between; align-items:baseline;
  flex-wrap:wrap; gap:0 .45em; white-space:nowrap;
}
.member-name .lv{ color:var(--dim); font-size:.85rem; }
.member-hit{ animation:memberHit .4s ease; }
@keyframes memberHit{
  0%,100%{ box-shadow:none; }
  30%{ box-shadow:inset 0 0 0 200px rgba(229,23,63,.35); }
}
/* commands */
.cmd-panel{ display:flex; flex-direction:column; gap:.4rem; justify-content:center; }
.cmd-panel button{
  font-family:var(--font-head);
  letter-spacing:.14em;
  font-size:1.02rem;
  padding:.42em .5em;
  text-align:center;
}
.cmd-title{
  font-family:var(--font-head); color:var(--dim);
  letter-spacing:.16em; font-size:.85rem; text-align:center;
  margin-bottom:.1rem;
}
.cmd-list{
  display:flex; flex-direction:column; gap:.4rem;
  max-height:170px; overflow-y:auto;
}
.cmd-list button{ display:flex; justify-content:space-between; gap:.6rem; font-family:var(--font-body); font-size:.9rem; text-align:left; }
.cmd-list .cost{ color:var(--mp); font-size:.8rem; white-space:nowrap; }
.cmd-list .cost.free{ color:var(--dim); }
/* log */
.log-panel{
  overflow-y:auto;
  font-size:.86rem;
  color:var(--dim);
  display:flex; flex-direction:column; gap:.28rem;
  max-height:190px;
}
.log-panel .ln{ animation:logIn .25s ease both; }
.log-panel .ln.hot{ color:var(--text); }
.log-panel .ln.sys{ color:var(--red); }
@keyframes logIn{ from{ opacity:0; transform:translateY(5px);} to{ opacity:1; transform:none; } }

/* damage pop numbers */
.dmg-pop{
  position:absolute;
  z-index:55;
  font-family:var(--font-head);
  font-size:clamp(1.6rem,4vw,2.6rem);
  color:#fff;
  text-shadow:0 0 10px var(--red), 0 2px 4px #000;
  pointer-events:none;
  animation:dmgPop 1s ease-out forwards;
  transform:translate(-50%,-50%);
}
.dmg-pop.heal{ color:var(--ok); text-shadow:0 0 10px rgba(61,220,132,.7), 0 2px 4px #000; }
.dmg-pop.mp{ color:var(--mp); text-shadow:0 0 10px rgba(63,169,245,.7), 0 2px 4px #000; }
.dmg-pop.weak{ font-size:clamp(2rem,5vw,3.2rem); color:#ffd23e; text-shadow:0 0 14px #ff9d00,0 2px 4px #000; }
.dmg-pop.resist{ font-size:clamp(1.2rem,3vw,1.9rem); opacity:.85; }
@keyframes dmgPop{
  0%{ opacity:0; transform:translate(-50%,-30%) scale(.6); }
  18%{ opacity:1; transform:translate(-50%,-60%) scale(1.15); }
  100%{ opacity:0; transform:translate(-50%,-150%) scale(1); }
}

/* battle end panels */
.battle-panel-veil{
  position:absolute; inset:0;
  z-index:65;
  display:flex; align-items:center; justify-content:center;
  background:rgba(5,5,7,.78);
  animation:veilIn .4s ease both;
}
@keyframes veilIn{ from{ opacity:0; } to{ opacity:1; } }
.result-card{
  width:min(430px,92vw);
  background:var(--panel);
  border:1px solid #2b2731;
  border-top:2px solid var(--red);
  border-radius:12px;
  padding:1.5rem 1.4rem;
  text-align:center;
  box-shadow:0 20px 70px rgba(0,0,0,.8);
}
.result-card h2{
  font-size:2.3rem; letter-spacing:.2em;
  color:var(--red); text-shadow:var(--glow-red);
  margin-bottom:.7rem;
}
.result-card.defeat h2{ color:var(--dim); text-shadow:none; }
.result-lines{ color:var(--dim); margin-bottom:1.1rem; display:flex; flex-direction:column; gap:.3rem; }
.result-lines .big{ color:var(--gold); font-family:var(--font-head); font-size:1.3rem; letter-spacing:.1em; }
.result-lines .lvl{ color:var(--ok); }

/* ---------- Menu overlay ---------- */
#overlay-menu{
  position:absolute; inset:0;
  z-index:70;
  background:rgba(5,5,7,.82);
  display:flex; align-items:center; justify-content:center;
  animation:veilIn .25s ease both;
}
.menu-card{
  width:min(640px,94vw);
  max-height:88vh;
  display:flex; flex-direction:column;
  background:var(--panel);
  border:1px solid #2b2731;
  border-top:2px solid var(--red);
  border-radius:12px;
  overflow:hidden;
  box-shadow:0 20px 70px rgba(0,0,0,.8);
}
.menu-tabs{
  display:flex;
  border-bottom:1px solid #2b2731;
  background:#100f13;
}
.menu-tabs button{
  flex:1;
  border:none; border-radius:0;
  border-bottom:2px solid transparent;
  background:none;
  font-family:var(--font-head);
  letter-spacing:.12em;
  font-size:1rem;
  padding:.7em .2em;
  color:var(--dim);
}
.menu-tabs button:hover:not(:disabled){ background:#1a161d; color:var(--text); box-shadow:none; }
.menu-tabs button.on{ color:var(--red); border-bottom-color:var(--red); }
.menu-body{ padding:1rem 1.1rem 1.2rem; overflow-y:auto; }
.party-card{
  display:flex; gap:.9rem;
  background:var(--panel-2);
  border:1px solid #2b2731;
  border-radius:10px;
  padding:.8rem;
  margin-bottom:.8rem;
}
.party-card.active-member{ border-color:var(--red); box-shadow:0 0 14px rgba(229,23,63,.25); }
.party-portrait{
  flex:0 0 76px; height:100px;
  border-radius:8px; overflow:hidden;
  border:1px solid var(--deep-red);
  background:#0d0c10;
}
.party-portrait img{ width:100%; height:100%; object-fit:cover; object-position:center 10%; }
.party-info{ flex:1; min-width:0; }
.party-head{ display:flex; justify-content:space-between; align-items:baseline; gap:.6rem; flex-wrap:wrap; }
.party-head .nm{ font-family:var(--font-head); font-size:1.3rem; letter-spacing:.1em; }
.party-head .el{ font-size:.75rem; color:var(--dim); text-transform:uppercase; letter-spacing:.12em; }
.stat-grid{
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:.15rem .8rem;
  font-size:.8rem; color:var(--dim);
  margin:.45rem 0;
}
.stat-grid b{ color:var(--text); font-weight:500; }
.party-info .bar{ margin-top:.3rem; }
.inv-row{
  display:flex; align-items:center; gap:.8rem;
  background:var(--panel-2);
  border:1px solid #2b2731;
  border-radius:8px;
  padding:.6rem .8rem;
  margin-bottom:.55rem;
}
.inv-icon{ font-size:1.5rem; flex:0 0 auto; }
.inv-main{ flex:1; min-width:0; }
.inv-main .nm{ font-weight:600; }
.inv-main .ds{ color:var(--dim); font-size:.8rem; }
.inv-count{ font-family:var(--font-head); font-size:1.2rem; color:var(--gold); }
.inv-empty,.menu-note{ color:var(--dim); text-align:center; padding:1rem 0; }
.howto{ color:var(--dim); font-size:.92rem; display:flex; flex-direction:column; gap:.7rem; }
.howto b{ color:var(--text); }
.howto .k{ color:var(--red); font-family:var(--font-head); letter-spacing:.1em; }

/* mini member picker (item targets etc.) */
.picker-row{ display:flex; flex-direction:column; gap:.45rem; margin-top:.6rem; }
.picker-row button{ text-align:left; }

/* ---------- Toasts ---------- */
#toast-layer{
  position:absolute; top:3.4rem; left:0; right:0;
  z-index:80;
  display:flex; flex-direction:column; align-items:center; gap:.4rem;
  pointer-events:none;
}
.toast{
  background:rgba(16,14,19,.95);
  border:1px solid var(--deep-red);
  border-left:3px solid var(--red);
  color:var(--text);
  border-radius:8px;
  padding:.55em 1.1em;
  font-size:.9rem;
  box-shadow:0 8px 30px rgba(0,0,0,.6);
  animation:toastIn .3s ease both;
}
.toast.out{ animation:toastOut .4s ease both; }
@keyframes toastIn{ from{ opacity:0; transform:translateY(-10px);} to{ opacity:1; transform:none; } }
@keyframes toastOut{ from{ opacity:1; } to{ opacity:0; transform:translateY(-8px); } }

/* ---------- Responsive ---------- */
@media (max-width:820px){
  .battle-bottom{
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    grid-template-areas:"member cmds" "log log";
  }
  .member-panel{ grid-area:member; }
  .cmd-panel{ grid-area:cmds; }
  .log-panel{ grid-area:log; max-height:110px; min-height:70px; }
  .bpanel{ min-height:0; }
}
@media (max-width:560px){
  .battle-top{ justify-content:center; padding-right:1rem; }
  .enemy-wrap{ margin-right:0; }
  .enemy-imgbox{ width:clamp(120px,26vh,200px); height:clamp(120px,26vh,200px); }
  .battle-bottom{ gap:.5rem; padding:.5rem .5rem calc(.6rem + env(safe-area-inset-bottom)); }
  .member-portrait{ flex-basis:64px; height:88px; }
  .cmd-panel button{ font-size:.9rem; padding:.32em .3em; letter-spacing:.08em; }
  .cmd-panel{ gap:.3rem; }
  .log-panel{ max-height:88px; }
  .member-info{ gap:.15rem; }
  .dialog-portrait{ flex-basis:58px; height:58px; }
  .stat-grid{ grid-template-columns:repeat(2,1fr); }
}

/* ============================================================
   Combat v2 — phases, moves, loadouts, hotspot glints
   (appended per GAME_SPEC.md sec 10 + 11)
   ============================================================ */

/* ---------- phase badges (spec sec 10 colors) ---------- */
:root{
  --ph-neutral:   #9a939c;
  --ph-aggressive:#e5173f;
  --ph-guarded:   #3d9bdc;
  --ph-staggered: #d8a31a;
  --ph-charged:   #a44ce0;
}
.bar-row, .enemy-hprow{
  display:flex; align-items:center; gap:.45rem;
  min-width:0;
}
.bar-row .bar{ flex:1 1 auto; min-width:0; }
.enemy-hprow{ justify-content:center; margin:.35rem auto 0; width:min(300px,92%); }
.enemy-hprow .enemy-hpbar{ flex:1 1 auto; margin:0; }
.phase-badge{
  flex:0 0 auto;
  font-family:var(--font-head);
  font-size:.72rem;
  letter-spacing:.12em;
  text-transform:uppercase;
  line-height:1;
  padding:.32em .55em .26em;
  border-radius:999px;
  border:1px solid var(--ph-neutral);
  color:var(--ph-neutral);
  background:rgba(10,10,12,.72);
  cursor:help;
  white-space:nowrap;
  transition:color .25s, border-color .25s, box-shadow .25s;
}
.phase-badge.phase-neutral{    color:var(--ph-neutral);    border-color:var(--ph-neutral); }
.phase-badge.phase-aggressive{ color:var(--ph-aggressive); border-color:var(--ph-aggressive); box-shadow:0 0 10px rgba(229,23,63,.45); }
.phase-badge.phase-guarded{    color:var(--ph-guarded);    border-color:var(--ph-guarded);    box-shadow:0 0 10px rgba(61,155,220,.4); }
.phase-badge.phase-staggered{  color:var(--ph-staggered);  border-color:var(--ph-staggered);  box-shadow:0 0 10px rgba(216,163,26,.4); animation:badgeWobble .5s ease; }
.phase-badge.phase-charged{    color:var(--ph-charged);    border-color:var(--ph-charged);    box-shadow:0 0 12px rgba(164,76,224,.55); animation:badgeCharge 1.4s ease-in-out infinite; }
@keyframes badgeWobble{
  0%,100%{ transform:rotate(0); } 25%{ transform:rotate(-4deg); } 65%{ transform:rotate(3deg); }
}
@keyframes badgeCharge{
  0%,100%{ box-shadow:0 0 6px rgba(164,76,224,.35); }
  50%{ box-shadow:0 0 16px rgba(164,76,224,.8); }
}

/* ---------- move buttons: cat icon + element dot + MP chip ---------- */
.cmd-phase{ cursor:help; }
.move-list{ max-height:150px; }
.move-btn{
  display:flex; align-items:center; gap:.45rem;
  font-family:var(--font-body); font-size:.9rem;
  text-align:left; padding:.42em .55em;
}
.move-btn .mcat{
  flex:0 0 auto; font-size:.95em; width:1.25em; text-align:center;
  filter:grayscale(35%);
}
.move-btn .mname{
  flex:1 1 auto; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* utility commands under the move list */
.cmd-util{
  display:grid; grid-template-columns:1fr 1fr;
  gap:.35rem;
  margin-top:.45rem;
  border-top:1px solid #2b2731;
  padding-top:.45rem;
}
.cmd-util button{
  font-family:var(--font-head);
  letter-spacing:.1em;
  font-size:.85rem;
  padding:.4em .3em;
}

/* ---------- floating SUPER / BLOCKED / STAGGERED! labels ---------- */
.float-label{
  position:absolute;
  z-index:56;
  font-family:var(--font-head);
  font-size:clamp(1.1rem,3vw,1.7rem);
  letter-spacing:.22em;
  pointer-events:none;
  transform:translate(-50%,-50%);
  animation:floatLabel 1.2s ease-out forwards;
  white-space:nowrap;
}
.float-label.super{
  color:#ffd23e;
  text-shadow:0 0 14px #ff9d00, 0 2px 4px #000;
}
.float-label.blocked{
  color:#8fd0ff;
  text-shadow:0 0 12px rgba(61,155,220,.9), 0 2px 4px #000;
}
.float-label.stagger{
  color:var(--ph-staggered);
  text-shadow:0 0 12px rgba(216,163,26,.9), 0 2px 4px #000;
}
@keyframes floatLabel{
  0%{ opacity:0; transform:translate(-50%,-20%) scale(.7) rotate(-3deg); }
  16%{ opacity:1; transform:translate(-50%,-55%) scale(1.12) rotate(1deg); }
  70%{ opacity:1; }
  100%{ opacity:0; transform:translate(-50%,-130%) scale(1) rotate(0); }
}

/* ---------- loadout editor ---------- */
.lo-card .lo-titlebar{ align-items:center; justify-content:space-between; padding:0 .3rem 0 .9rem; }
.lo-title{ font-size:1.15rem; color:var(--red); letter-spacing:.14em; padding:.55em 0; }
.lo-titlebar button{ flex:0 0 auto; border:none; background:none; color:var(--dim); font-size:1.05rem; padding:.6em .8em; }
.lo-titlebar button:hover:not(:disabled){ color:var(--red); background:none; box-shadow:none; }
.loadout-wrap{ display:flex; flex-direction:column; gap:.7rem; }
.lo-readonly{
  color:var(--ph-staggered);
  border:1px dashed rgba(216,163,26,.5);
  border-radius:8px;
  padding:.45em .8em;
  font-size:.82rem;
  text-align:center;
}
.lo-chars{ display:flex; gap:.5rem; flex-wrap:wrap; }
.lo-char{
  display:flex; align-items:center; gap:.55rem;
  padding:.35em .8em .35em .35em;
  border-radius:999px;
}
.lo-char.on{
  border-color:var(--red);
  box-shadow:0 0 12px rgba(229,23,63,.35);
  background:#1d1218;
}
.lo-char-portrait{
  width:34px; height:34px;
  border-radius:50%; overflow:hidden;
  border:1px solid var(--deep-red);
  background:#0d0c10;
  flex:0 0 auto;
  display:block;
}
.lo-char-portrait img{ width:100%; height:100%; object-fit:cover; object-position:center 12%; display:block; }
.lo-char-portrait .avatar-fallback{ font-size:1rem; }
.lo-char-meta{ display:flex; flex-direction:column; align-items:flex-start; line-height:1.15; }
.lo-char-meta .nm{ font-family:var(--font-head); letter-spacing:.1em; font-size:1rem; }
.lo-char-meta .lv{ color:var(--dim); font-size:.7rem; }
/* phase tabs */
.lo-tabs{
  display:flex; gap:.3rem; flex-wrap:wrap;
}
.lo-tab{
  flex:1 1 auto;
  display:flex; align-items:center; justify-content:center; gap:.4rem;
  font-family:var(--font-head);
  font-size:.85rem; letter-spacing:.1em;
  padding:.45em .4em;
  color:var(--dim);
  border-color:#2b2731;
}
.lo-tab .dot{ width:8px; height:8px; border-radius:50%; background:currentColor; flex:0 0 auto; }
.lo-tab .cnt{
  font-size:.68rem; color:inherit; opacity:.85;
  border:1px solid currentColor; border-radius:999px;
  padding:.1em .45em; line-height:1.2;
}
.lo-tab.tab-neutral.on,   .lo-tab.tab-neutral:hover:not(:disabled){    color:var(--ph-neutral);    border-color:var(--ph-neutral);    background:#16151a; box-shadow:none; }
.lo-tab.tab-aggressive.on,.lo-tab.tab-aggressive:hover:not(:disabled){ color:var(--ph-aggressive); border-color:var(--ph-aggressive); background:#1c1015; box-shadow:0 0 10px rgba(229,23,63,.25); }
.lo-tab.tab-guarded.on,   .lo-tab.tab-guarded:hover:not(:disabled){    color:var(--ph-guarded);    border-color:var(--ph-guarded);    background:#101720; box-shadow:0 0 10px rgba(61,155,220,.22); }
.lo-tab.tab-staggered.on, .lo-tab.tab-staggered:hover:not(:disabled){  color:var(--ph-staggered);  border-color:var(--ph-staggered);  background:#1b1610; box-shadow:0 0 10px rgba(216,163,26,.22); }
.lo-tab.tab-charged.on,   .lo-tab.tab-charged:hover:not(:disabled){    color:var(--ph-charged);    border-color:var(--ph-charged);    background:#171021; box-shadow:0 0 10px rgba(164,76,224,.25); }
.lo-countrow{
  display:flex; align-items:baseline; justify-content:space-between; gap:.8rem;
  flex-wrap:wrap;
}
.lo-count{
  font-family:var(--font-head);
  letter-spacing:.14em;
  font-size:1.05rem;
  color:var(--text);
}
.lo-count.full{ color:var(--gold); text-shadow:0 0 10px rgba(232,193,90,.4); }
.lo-tip{ color:var(--dim); font-size:.78rem; }
/* move grid */
.lo-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(200px,1fr));
  gap:.5rem;
}
.lo-cell{
  position:relative;
  display:flex; flex-direction:column; align-items:stretch; gap:.3rem;
  text-align:left;
  padding:.55em .65em;
  background:var(--panel-2);
  border:1px solid #2b2731;
  border-radius:9px;
  min-height:64px;
}
.lo-cell:hover:not(:disabled){
  background:#221521;
  border-color:var(--red);
  color:var(--text);
  box-shadow:0 0 10px rgba(229,23,63,.25);
}
.lo-cell.on{
  border-color:var(--red);
  background:#1d1116;
  box-shadow:inset 0 0 0 1px var(--red), 0 0 12px rgba(229,23,63,.25);
}
.lo-cell.invalid{ opacity:.4; }
.lo-cell.capped:not(.on){ opacity:.55; }
.lo-cell-head{
  display:flex; align-items:center; gap:.45rem;
  font-size:.92rem;
  min-width:0;
}
.lo-cell-head .mcat{ flex:0 0 auto; width:1.2em; text-align:center; }
.lo-cell-head .mname{
  flex:1 1 auto; min-width:0;
  font-weight:600;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.lo-cell-desc{
  color:var(--dim);
  font-size:.75rem;
  line-height:1.35;
  display:block;
}
.lo-check{
  position:absolute; top:-7px; right:-6px;
  width:20px; height:20px;
  display:flex; align-items:center; justify-content:center;
  background:var(--red);
  color:#fff;
  font-size:.72rem;
  border-radius:50%;
  box-shadow:0 0 10px rgba(229,23,63,.6);
}

/* ---------- hotspot glint markers (spec sec 11 — items read as ITEMS) ---------- */
.hs-glint{
  position:absolute;
  left:50%; top:50%;
  transform:translate(-50%,-50%);
  width:14px; height:14px;
  pointer-events:none;
  z-index:2;
}
.hs-glint i{
  position:absolute; inset:3px;
  border-radius:50%;
  background:radial-gradient(circle, #ffdfe6 0%, var(--red) 55%, rgba(229,23,63,0) 78%);
  box-shadow:0 0 8px rgba(229,23,63,.95), 0 0 18px rgba(229,23,63,.5);
  animation:glintPulse 2.1s ease-in-out infinite;
}
.hs-glint::after{ /* expanding ring */
  content:"";
  position:absolute; inset:0;
  border-radius:50%;
  border:1px solid rgba(229,23,63,.8);
  animation:glintRing 2.1s ease-out infinite;
}
@keyframes glintPulse{
  0%,100%{ opacity:.55; transform:scale(.8); }
  50%{ opacity:1; transform:scale(1.15); }
}
@keyframes glintRing{
  0%{ opacity:.7; transform:scale(.5); }
  70%{ opacity:0; transform:scale(1.9); }
  100%{ opacity:0; transform:scale(1.9); }
}
/* stronger outline + label on hover AND tap */
.hotspot:hover, .hotspot.hs-touch{
  border-color:rgba(229,23,63,.95);
  background:rgba(229,23,63,.12);
  box-shadow:var(--glow-red), inset 0 0 18px rgba(229,23,63,.22);
}
.hotspot:hover .hs-glint i, .hotspot.hs-touch .hs-glint i{
  animation-duration:.9s;
}
.hotspot.hs-touch .hs-label{ opacity:1; transform:translateX(-50%); }

/* ---------- combat v2 responsive tweaks ---------- */
@media (max-width:820px){
  .move-list{ max-height:132px; }
  .lo-grid{ grid-template-columns:repeat(auto-fill, minmax(160px,1fr)); }
}
@media (max-width:560px){
  .phase-badge{ font-size:.62rem; padding:.3em .45em .24em; letter-spacing:.08em; }
  .move-btn{ font-size:.82rem; gap:.35rem; }
  .cmd-util button{ font-size:.78rem; letter-spacing:.06em; }
  .move-list{ max-height:118px; }
  .lo-grid{ grid-template-columns:1fr; }
  .lo-tab{ font-size:.74rem; padding:.4em .25em; gap:.25rem; }
  .lo-tab .cnt{ display:none; }
  .lo-chars{ gap:.35rem; }
  .hs-glint{ width:12px; height:12px; }
}

/* ============================================================
   Progression v3 (spec sec 12) — types, resources, statuses,
   character sheet, skill tree screen.  (Appended; earlier rules
   of equal specificity lose to these by order.)
   ============================================================ */

/* ---------- 11 damage-type dots ---------- */
.t-dot{
  width:10px; height:10px; border-radius:50%;
  flex:0 0 auto; display:inline-block;
  background:#5a5560;
}
.t-dot.t-physical{   background:#b8b2b9; box-shadow:0 0 6px rgba(184,178,185,.7); }
.t-dot.t-magical{    background:#8f7ff0; box-shadow:0 0 6px rgba(143,127,240,.8); }
.t-dot.t-lightning{  background:#f2d024; box-shadow:0 0 6px rgba(242,208,36,.8); }
.t-dot.t-fire{       background:#ff5a2c; box-shadow:0 0 6px rgba(255,90,44,.8); }
.t-dot.t-occult{     background:#a44ce0; box-shadow:0 0 6px rgba(164,76,224,.8); }
.t-dot.t-blood{      background:#c1121f; box-shadow:0 0 6px rgba(193,18,31,.8); }
.t-dot.t-poison{     background:#3fae4a; box-shadow:0 0 6px rgba(63,174,74,.8); }
.t-dot.t-divine{     background:#ffe9a8; box-shadow:0 0 7px rgba(255,233,168,.9); }
.t-dot.t-virus{      background:#2ec4a6; box-shadow:0 0 6px rgba(46,196,166,.8); }
.t-dot.t-ghost{      background:#9ad7e8; box-shadow:0 0 6px rgba(154,215,232,.8); }
.t-dot.t-biological{ background:#96b23c; box-shadow:0 0 6px rgba(150,178,60,.8); }

/* ---------- cost chips (sta / mp / faith) ---------- */
.cost-chips{ display:inline-flex; gap:3px; margin-left:auto; flex:0 0 auto; }
.cost-chip{
  font-size:.62rem; letter-spacing:.04em; white-space:nowrap;
  padding:.14em .38em; border-radius:8px;
  border:1px solid; background:rgba(0,0,0,.28);
  font-family:var(--font-head);
}
.cost-chip.c-sta{   color:#58d07c; border-color:rgba(88,208,124,.5); }
.cost-chip.c-mp{    color:#5db4f7; border-color:rgba(63,169,245,.5); }
.cost-chip.c-faith{ color:#e8c15a; border-color:rgba(232,193,90,.5); }
.cost-chip.free{    color:var(--dim); border-color:#38323e; background:transparent; }
button:disabled .cost-chip{ opacity:.7; }

/* ---------- effectiveness arrows on move buttons ---------- */
.eff-arrow{ font-size:.72rem; line-height:1; flex:0 0 auto; }
.eff-arrow.eff-up{   color:#3ddc84; text-shadow:0 0 7px rgba(61,220,132,.85); }
.eff-arrow.eff-down{ color:#8a5cf5; opacity:.8; }

/* ---------- battle mini resource bars (player side) ---------- */
.mini-res{ display:flex; flex-direction:column; gap:3px; margin-top:5px; }
.mini-row{ display:flex; align-items:center; gap:5px; min-width:0; }
.mini-lbl{
  font-size:.58rem; letter-spacing:.09em; color:var(--dim);
  font-family:var(--font-head); width:2.4em; flex:0 0 auto;
}
.bar.mini{ height:6px; flex:1 1 auto; min-width:0; border-radius:4px; }
.bar.mini .fill{ border-radius:3px; }
.mini-val{ font-size:.6rem; color:var(--dim); min-width:3.6em; text-align:right; flex:0 0 auto; }
.bar.res-life .fill{
  background:linear-gradient(90deg, var(--deep-red), var(--red));
  box-shadow:0 0 6px rgba(229,23,63,.5);
}
.bar.res-sta .fill{
  background:linear-gradient(90deg,#1d7a45,#3ddc84);
  box-shadow:0 0 6px rgba(61,220,132,.45);
}
.bar.res-mag .fill{
  background:linear-gradient(90deg,#144a74,#3fa9f5);
  box-shadow:0 0 6px rgba(63,169,245,.45);
}
.bar.res-faith .fill{
  background:linear-gradient(90deg,#8a6b12,#e8c15a);
  box-shadow:0 0 6px rgba(232,193,90,.5);
}

/* ---------- status chips (buildup ring + active turns) ---------- */
.status-row{
  display:flex; flex-wrap:wrap; gap:6px;
  margin-top:6px; min-height:0;
}
.enemy-status{ justify-content:center; }
.status-chip{
  position:relative; width:26px; height:26px; flex:0 0 auto;
  border-radius:50%;
}
.status-ring{ position:absolute; inset:0; border-radius:50%; }
.status-chip::after{
  content:''; position:absolute; inset:3px; border-radius:50%;
  background:#16141a; border:1px solid rgba(255,255,255,.14);
}
.status-chip.on::after{
  border-color:currentColor;
  box-shadow:0 0 8px currentColor, inset 0 0 6px rgba(0,0,0,.6);
}
.status-icn{
  position:absolute; inset:0; z-index:1;
  display:flex; align-items:center; justify-content:center;
  font-size:.7rem; line-height:1;
  filter:saturate(.9);
}
.status-chip.on .status-icn{ filter:none; }
.status-turns{
  position:absolute; right:-5px; top:-5px; z-index:2;
  font-size:.56rem; line-height:1; font-family:var(--font-head);
  background:#0c0b0f; border:1px solid currentColor; border-radius:8px;
  padding:1px 4px 0;
}
.float-label.status-pop{
  color:#ffb14e;
  text-shadow:0 0 10px rgba(255,177,78,.9), 0 0 26px rgba(255,120,40,.5), 0 2px 4px #000;
}

/* ---------- character sheet (menu -> Party -> member) ---------- */
.sheet-back{ margin-bottom:.6rem; }
.sheet-wrap{ display:flex; flex-direction:column; gap:.55rem; max-width:560px; }
.sheet-head{ display:flex; gap:.7rem; align-items:center; }
.sheet-portrait{
  width:58px; height:58px; flex:0 0 auto; border-radius:8px; overflow:hidden;
  border:1px solid var(--deep-red); background:#0e0d11;
}
.sheet-portrait img{ width:100%; height:100%; object-fit:cover; display:block; }
.sheet-portrait .avatar-fallback{
  width:100%; height:100%; display:flex; align-items:center; justify-content:center;
  font-family:var(--font-head); font-size:1.6rem; color:var(--red);
}
.sheet-head-info{ min-width:0; }
.sheet-name{ display:flex; align-items:baseline; gap:.5rem; }
.sheet-name .nm{ font-family:var(--font-head); font-size:1.35rem; letter-spacing:.12em; }
.sheet-name .lv{ color:var(--dim); font-size:.85rem; }
.sheet-tags{ display:flex; flex-wrap:wrap; gap:.4rem; margin-top:.15rem; }
.sheet-tag{
  display:inline-flex; align-items:center; gap:.35em;
  font-size:.72rem; color:var(--dim);
  border:1px solid #2b2731; border-radius:10px; padding:.15em .55em;
  background:var(--panel-2);
}
.sheet-bars{ display:flex; flex-direction:column; gap:5px; }
.sheet-bar-row{ display:flex; align-items:center; gap:.5rem; min-width:0; }
.sheet-bar-lbl{
  width:3em; flex:0 0 auto; text-align:right;
  font-size:.66rem; letter-spacing:.1em; color:var(--dim); font-family:var(--font-head);
}
.sheet-bar-row .bar{ flex:1 1 auto; min-width:0; }
.sheet-bar-val{ font-size:.68rem; color:var(--dim); min-width:4.6em; text-align:right; flex:0 0 auto; }
.sheet-sec-title{
  font-family:var(--font-head); letter-spacing:.16em; font-size:.8rem;
  color:var(--dim); text-transform:uppercase; margin-top:.35rem;
}
.sheet-stats{
  display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:5px;
}
.stat-cell{
  display:flex; flex-direction:column; align-items:center; gap:1px;
  border:1px solid #2b2731; border-radius:6px; padding:.35em .2em;
  background:var(--panel-2);
}
.stat-cell .sl{ font-size:.6rem; letter-spacing:.12em; color:var(--dim); font-family:var(--font-head); }
.stat-cell .sv{ font-size:.95rem; }
.rs-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(76px,1fr)); gap:4px;
}
.rs-cell{
  display:flex; align-items:center; gap:4px;
  font-size:.66rem; padding:.28em .42em;
  border:1px solid #26222c; border-radius:5px;
  color:var(--dim); background:transparent; opacity:.75;
}
.rs-cell .rs-nm{ font-family:var(--font-head); letter-spacing:.08em; }
.rs-cell .rs-x{ margin-left:auto; }
.rs-cell.weak{
  color:#ff8398; border-color:rgba(229,23,63,.6);
  background:rgba(122,12,34,.18); opacity:1;
}
.rs-cell.res{
  color:#7cc6ff; border-color:rgba(61,155,220,.55);
  background:rgba(20,74,116,.16); opacity:1;
}
.rs-cell.immune{
  color:#d9c9f5; border-color:rgba(164,76,224,.55);
  background:rgba(80,30,120,.18); opacity:1;
}
.phase-chips{ display:flex; flex-wrap:wrap; gap:5px; }
.pchip{
  font-size:.66rem; letter-spacing:.06em; font-family:var(--font-head);
  border:1px solid; border-radius:10px; padding:.2em .6em;
}
.pchip.p-neutral{    color:var(--ph-neutral, #9a939c); border-color:var(--ph-neutral, #9a939c); }
.pchip.p-aggressive{ color:var(--ph-aggressive, #e5173f); border-color:var(--ph-aggressive, #e5173f); }
.pchip.p-guarded{    color:var(--ph-guarded, #3d9bdc); border-color:var(--ph-guarded, #3d9bdc); }
.pchip.p-staggered{  color:var(--ph-staggered, #d8a31a); border-color:var(--ph-staggered, #d8a31a); }
.pchip.p-charged{    color:var(--ph-charged, #a44ce0); border-color:var(--ph-charged, #a44ce0); }
.sheet-points{ display:flex; align-items:center; gap:.7rem; margin-top:.2rem; }
.points-pill{
  display:inline-flex; align-items:center;
  font-family:var(--font-head); letter-spacing:.1em; font-size:.85rem;
  color:var(--gold); border:1px solid rgba(232,193,90,.55); border-radius:12px;
  padding:.22em .75em; background:rgba(138,107,18,.12);
  white-space:nowrap;
}
.party-portrait.clickable{ cursor:pointer; }
.party-portrait.clickable:hover{ box-shadow:0 0 10px rgba(229,23,63,.5); }
.party-actions{ display:flex; gap:.5rem; margin-top:.5rem; flex-wrap:wrap; }

/* ---------- skill tree screen ---------- */
.tree-root{
  position:absolute; inset:0;
  display:flex; flex-direction:column;
  background:var(--bg);
}
.tree-head{
  display:flex; align-items:center; flex-wrap:wrap; gap:.5rem;
  padding:.55rem .8rem;
  background:var(--panel);
  border-bottom:2px solid var(--red);
  z-index:4;
}
.tree-title{
  font-family:var(--font-head); font-size:1.25rem; letter-spacing:.2em;
  color:var(--red); text-shadow:var(--glow-red); text-transform:uppercase;
}
.tree-chars{ display:flex; gap:.35rem; flex-wrap:wrap; }
.tree-char{ font-size:.82rem; padding:.4em .8em; }
.tree-char.on{
  border-color:var(--red); color:var(--red);
  box-shadow:0 0 10px rgba(229,23,63,.35);
  background:#17151b;
}
.tree-points{ margin-left:auto; }
.tree-respec{ font-size:.82rem; }
.tree-scroll{
  flex:1 1 auto; overflow:auto; position:relative;
  -webkit-overflow-scrolling:touch;
  touch-action:pan-x pan-y;
  background:
    radial-gradient(ellipse 70% 40% at 50% 0%, rgba(122,12,34,.18), transparent 70%),
    var(--bg);
}
.tree-canvas{
  position:relative;
  min-height:1400px;
  min-width:640px;
  width:100%;
}
.tree-note{ position:absolute; left:50%; top:120px; transform:translateX(-50%); white-space:nowrap; }
.tree-edges{
  position:absolute; inset:0; width:100%; height:100%;
  pointer-events:none;
}
.tree-edges line{ stroke-width:2; opacity:.16; }
.tree-edges line.e-avail{ opacity:.45; }
.tree-edges line.e-on{ opacity:.9; stroke-width:2.5; }
.tree-node{
  position:absolute; transform:translate(-50%,-50%);
  width:44px; height:44px; padding:0; border-radius:50%;
  border:2px solid var(--bc, #9a939c);
  background:#141317; color:var(--text);
  display:flex; align-items:center; justify-content:center;
  z-index:1;
}
.tree-node:hover:not(:disabled){
  background:#141317; color:var(--text);
  border-color:var(--bc); box-shadow:0 0 14px var(--bc);
}
.tree-node .glyph{ font-size:1rem; line-height:1; pointer-events:none; }
.tree-node.k-keystone{ width:52px; height:52px; border-width:3px; }
.tree-node .ncost{
  position:absolute; right:-7px; top:-7px;
  font-size:.58rem; line-height:1; font-family:var(--font-head);
  background:#0c0b0f; border:1px solid #38323e; border-radius:8px;
  padding:2px 4px 1px; color:var(--dim); pointer-events:none;
}
.tree-node.locked{ opacity:.35; filter:saturate(.35); }
.tree-node.avail{ animation:nodePulse 1.7s ease-in-out infinite; }
@keyframes nodePulse{
  0%,100%{ box-shadow:0 0 5px var(--bc, #9a939c); }
  50%{ box-shadow:0 0 18px var(--bc, #9a939c); }
}
.tree-node.owned{
  background:var(--bc, #9a939c); color:#0a0a0c;
  box-shadow:0 0 12px var(--bc, #9a939c);
}
.tree-node.owned:hover:not(:disabled){ background:var(--bc); color:#0a0a0c; }
.tree-node.sel{ outline:2px solid #fff; outline-offset:3px; }

/* selected-node card pinned at the bottom */
.tree-card{
  position:absolute; left:.6rem; right:.6rem;
  bottom:calc(.6rem + env(safe-area-inset-bottom));
  background:var(--panel);
  border:1px solid var(--bc, #2b2731);
  border-left:4px solid var(--bc, var(--red));
  border-radius:10px;
  padding:.65rem .85rem;
  z-index:6;
  box-shadow:0 10px 34px rgba(0,0,0,.65);
  max-width:640px; margin:0 auto;
}
.tc-top{ display:flex; align-items:baseline; gap:.6rem; flex-wrap:wrap; }
.tc-name{
  font-family:var(--font-head); font-size:1.15rem; letter-spacing:.1em;
  color:var(--bc, var(--text));
}
.tc-kind{
  font-size:.64rem; letter-spacing:.12em; text-transform:uppercase;
  color:var(--dim); border:1px solid #2b2731; border-radius:8px; padding:.12em .5em;
}
.tc-cost{ font-size:.78rem; color:var(--gold); font-family:var(--font-head); letter-spacing:.08em; }
.tc-x{
  margin-left:auto; padding:.2em .6em; font-size:.85rem;
  border-color:#38323e; background:transparent;
}
.tc-grant{ margin-top:.3rem; font-size:.85rem; color:var(--text); }
.tc-desc{ margin-top:.25rem; font-size:.78rem; color:var(--dim); }
.tc-req{ margin-top:.3rem; font-size:.74rem; color:var(--dim); }
.tc-req-n{ color:#c04a5e; }
.tc-req-n.got{ color:#3ddc84; }
.tc-req-or{ color:var(--dim); }
.tc-foot{ display:flex; align-items:center; gap:.7rem; margin-top:.55rem; flex-wrap:wrap; }
.tc-reason{ font-size:.74rem; color:var(--dim); font-style:italic; }
.tc-owned{ color:#3ddc84; font-family:var(--font-head); letter-spacing:.1em; }
.tc-buy{ margin-left:auto; }
.tc-buy:not(:disabled){ border-color:var(--red); }

/* respec confirm veil */
.tree-confirm-veil{
  position:absolute; inset:0; z-index:8;
  background:rgba(6,6,8,.72); backdrop-filter:blur(2px);
  display:flex; align-items:center; justify-content:center;
  padding:1rem;
}
.tree-confirm{
  background:var(--panel);
  border:1px solid var(--red); border-radius:10px;
  padding:1rem 1.2rem;
  max-width:360px; width:100%;
  box-shadow:0 0 40px rgba(229,23,63,.25), 0 14px 40px rgba(0,0,0,.7);
}
.tree-confirm h3{
  font-family:var(--font-head); letter-spacing:.12em; font-size:1.2rem;
  color:var(--red); margin-bottom:.4rem;
}
.tc-shards{ margin-top:.5rem; font-size:.85rem; color:var(--gold); }
.tc-confirm-row{ display:flex; gap:.6rem; margin-top:.8rem; flex-wrap:wrap; }

/* ---------- v3 responsive ---------- */
@media (max-width:820px){
  .tree-canvas{ min-width:600px; }
}
@media (max-width:560px){
  .cost-chip{ font-size:.56rem; padding:.12em .3em; }
  .mini-val{ min-width:3.1em; }
  .status-chip{ width:22px; height:22px; }
  .status-icn{ font-size:.6rem; }
  .sheet-stats{ grid-template-columns:repeat(4, minmax(0,1fr)); }
  .rs-grid{ grid-template-columns:repeat(auto-fill, minmax(68px,1fr)); }
  .tree-head{ padding:.45rem .5rem; gap:.35rem; }
  .tree-title{ font-size:1rem; letter-spacing:.14em; }
  .tree-char{ font-size:.72rem; padding:.35em .6em; }
  .tree-points{ font-size:.72rem; }
  .tree-respec{ font-size:.72rem; }
  .tree-node{ width:38px; height:38px; }
  .tree-node.k-keystone{ width:46px; height:46px; }
  .tree-canvas{ min-width:560px; }
  .tree-card{ left:.4rem; right:.4rem; padding:.55rem .65rem; }
}

/* ============================================================
   Room3D — first-person mode HUD (spec sec 13, palette sec 8)
   ============================================================ */
#screen-room3d{ background:var(--bg); }
#room3d-canvas{
  position:absolute; inset:0;
  width:100%; height:100%;
  display:block;
  background:#050406;
  cursor:crosshair;
}
/* soft red-black vignette over the room */
.r3d-vignette{
  position:absolute; inset:0;
  pointer-events:none;
  z-index:4;
  background:
    radial-gradient(ellipse at center, transparent 52%, rgba(10,3,5,.62) 100%),
    linear-gradient(180deg, rgba(122,12,34,.06), transparent 22%, transparent 80%, rgba(0,0,0,.35));
}
.r3d-hud{ z-index:10; }
.r3d-level{
  align-self:center;
  font-family:var(--font-head);
  font-size:.95rem; letter-spacing:.12em;
  color:var(--dim);
  padding:.2em .7em;
  border:1px solid rgba(122,12,34,.55);
  border-radius:999px;
  background:rgba(20,19,23,.55);
  white-space:nowrap;
}

/* center crosshair dot */
.r3d-crosshair{
  position:absolute; left:50%; top:50%;
  width:7px; height:7px;
  margin:-3.5px 0 0 -3.5px;
  border-radius:50%;
  background:rgba(242,238,240,.85);
  box-shadow:0 0 6px rgba(0,0,0,.8), 0 0 2px rgba(242,238,240,.6);
  z-index:12;
  pointer-events:none;
  transition:background .12s ease, transform .12s ease, box-shadow .12s ease;
}
.r3d-crosshair.in-range{
  background:var(--red);
  transform:scale(1.7);
  box-shadow:var(--glow-red);
  animation:r3dCrossPulse 1s ease-in-out infinite;
}
@keyframes r3dCrossPulse{
  0%,100%{ transform:scale(1.55); }
  50%    { transform:scale(1.95); }
}
/* TV hovered — crosshair stays white, just brightens + grows a touch */
.r3d-crosshair.tv-range{
  background:var(--text);
  transform:scale(1.4);
  box-shadow:0 0 10px rgba(242,238,240,.75), 0 0 3px rgba(242,238,240,.9);
}
/* engage hint under the crosshair */
.r3d-hint{
  position:absolute; left:50%; top:50%;
  transform:translate(-50%, 1.6rem);
  z-index:12;
  pointer-events:none;
  font-family:var(--font-head);
  font-size:1.05rem; letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--red);
  text-shadow:0 0 10px rgba(229,23,63,.7), 0 1px 3px rgba(0,0,0,.9);
  animation:r3dHintPulse 1.2s ease-in-out infinite;
}
@keyframes r3dHintPulse{
  0%,100%{ opacity:.65; }
  50%    { opacity:1; }
}
/* TV variant of the hint — calm white, keeps the exact "TV — ..." casing */
.r3d-hint.tv{
  color:var(--text);
  text-transform:none;
  letter-spacing:.08em;
  font-size:.95rem;
  text-shadow:0 0 8px rgba(242,238,240,.4), 0 1px 3px rgba(0,0,0,.9);
  animation:r3dHintPulse 1.8s ease-in-out infinite;
}

/* bottom control hints line */
.r3d-controls{
  position:absolute; left:0; right:0; bottom:0;
  z-index:10;
  pointer-events:none;
  text-align:center;
  padding:.55rem .9rem .7rem;
  font-size:.78rem; letter-spacing:.06em;
  color:var(--dim);
  text-shadow:0 1px 3px rgba(0,0,0,.9);
  background:linear-gradient(0deg, rgba(5,5,7,.7), transparent);
}

/* lock overlay — informational; clicks pass through to the canvas */
.r3d-lock-overlay{
  position:absolute; inset:0;
  z-index:14;
  pointer-events:none;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(ellipse at center, rgba(5,4,6,.25), rgba(5,4,6,.6) 100%);
  transition:opacity .25s ease;
}
.r3d-lock-overlay.hidden{ display:none; }
.r3d-lock-card{
  text-align:center;
  padding:1.1rem 1.6rem 1.2rem;
  border:1px solid var(--deep-red);
  border-radius:10px;
  background:rgba(20,19,23,.82);
  box-shadow:0 0 30px rgba(229,23,63,.18), 0 12px 36px rgba(0,0,0,.65);
  max-width:min(88vw, 30rem);
}
.r3d-lock-title{
  font-family:var(--font-head);
  font-size:clamp(1.4rem, 3.6vw, 2rem);
  letter-spacing:.2em;
  color:var(--red);
  text-shadow:var(--glow-red);
  margin-bottom:.35rem;
}
.r3d-lock-line{
  color:var(--dim);
  font-size:clamp(.78rem, 1.8vw, .95rem);
  letter-spacing:.05em;
  animation:r3dHintPulse 1.8s ease-in-out infinite;
}

@media (max-width:560px){
  .r3d-level{ font-size:.72rem; }
  .r3d-controls{ font-size:.66rem; }
}

/* ============================================================
   Arena battles — 3D church, spec §15
   (screen, HUD plates, move panel, telegraph prompt, splashes)
   ============================================================ */
#screen-battle3d{ background:#05050a; }
#battle3d-canvas{
  position:absolute; inset:0; width:100%; height:100%;
  display:block; cursor:crosshair;
}
.b3d-enemy-plate{
  position:absolute; top:calc(.8rem + env(safe-area-inset-top)); left:50%;
  transform:translateX(-50%);
  width:min(420px, 72vw);
  padding:.45rem .8rem .55rem;
  background:rgba(10,10,12,.72);
  border:1px solid #2a2630; border-top:2px solid var(--red);
  border-radius:9px; z-index:4;
}
.b3d-enemy-name{
  font-family:var(--font-head); letter-spacing:.14em;
  color:var(--text); font-size:1.05rem; margin-bottom:.3rem;
  text-align:center;
}
.b3d-party{
  position:absolute; left:.8rem; bottom:calc(.8rem + env(safe-area-inset-bottom));
  display:flex; flex-direction:column; gap:.5rem; z-index:4;
  width:min(230px, 38vw);
}
.b3d-member{
  padding:.4rem .6rem .5rem;
  background:rgba(10,10,12,.72);
  border:1px solid #2a2630; border-left:3px solid #4a4550;
  border-radius:8px;
}
.b3d-member.body{ border-left-color:var(--red); box-shadow:0 0 14px rgba(229,23,63,.22); }
.b3d-member.down{ opacity:.45; filter:grayscale(.8); }
.b3d-member-head{
  display:flex; justify-content:space-between; align-items:baseline;
  margin-bottom:.25rem;
}
.b3d-member-head .nm{ font-family:var(--font-head); letter-spacing:.1em; font-size:.92rem; }
.b3d-member-head .hp{ color:var(--dim); font-size:.75rem; }
.b3d-member-res{
  display:flex; gap:.6rem; margin-top:.25rem; font-size:.68rem; letter-spacing:.04em;
}
.b3d-member-res .sta{ color:#7fd08a; }
.b3d-member-res .mp{ color:#7fb3e8; }
.b3d-member-res .faith{ color:#e8cd7f; }
.b3d-prompt{
  position:absolute; top:26%; left:50%; transform:translateX(-50%);
  font-family:var(--font-head); text-align:center;
  font-size:clamp(1.5rem, 4.5vw, 2.6rem); letter-spacing:.18em;
  color:var(--text); text-shadow:0 0 18px rgba(229,23,63,.8);
  z-index:5; pointer-events:none; white-space:nowrap;
}
.b3d-prompt.hidden{ display:none; }
.b3d-prompt.telegraph{ color:#ffd7de; animation:b3dTelegraph .5s ease-in-out infinite; }
.b3d-prompt.banner{ color:var(--red); }
/* §22: every telegraph carries its evade kind as `ev-<kind>`. 'backoff'
   (ground_slam's shockwave rolls out from his feet) is the one dodge about
   distance rather than lanes, so it gets its own colour — at the size and
   speed these flash by, an identical-looking warning reads as "sidestep" and
   walks you straight into the ring. */
.b3d-prompt.ev-backoff{ color:#ffc27a; text-shadow:0 0 18px rgba(255,150,40,.85); }
@keyframes b3dTelegraph{
  0%,100%{ transform:translateX(-50%) scale(1); opacity:1; }
  50%{ transform:translateX(-50%) scale(1.07); opacity:.75; }
}
.b3d-log{
  position:absolute; bottom:calc(9.3rem + env(safe-area-inset-bottom)); left:50%;
  transform:translateX(-50%);
  max-width:min(560px, 86vw);
  color:var(--dim); font-size:.85rem; letter-spacing:.03em;
  text-align:center; text-shadow:0 1px 3px #000;
  z-index:4; pointer-events:none;
}
.b3d-panel{
  position:absolute; bottom:calc(1.6rem + env(safe-area-inset-bottom)); left:50%;
  transform:translateX(-50%);
  width:min(560px, 92vw);
  padding:.6rem .7rem .7rem;
  background:rgba(10,10,12,.82);
  border:1px solid #2a2630; border-top:2px solid var(--red);
  border-radius:10px; z-index:6;
}
.b3d-panel.hidden{ display:none; }
.b3d-panel-title{
  font-family:var(--font-head); letter-spacing:.12em;
  color:var(--text); font-size:.95rem; margin-bottom:.45rem; text-align:center;
}
.b3d-moves{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr));
  gap:.4rem; margin-bottom:.5rem;
}
.b3d-move{
  display:flex; align-items:center; gap:.4rem;
  text-align:left; padding:.42em .55em; font-size:.82rem;
}
.b3d-move .dot{ width:9px; height:9px; border-radius:50%; flex:0 0 auto; }
.b3d-move .nm{ flex:1 1 auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.b3d-move .cost{ color:var(--dim); font-size:.68rem; flex:0 0 auto; }
.b3d-move .eff.up{ color:#7fd08a; }
.b3d-move .eff.down{ color:#e8a97f; }
.b3d-panel-row{ display:flex; gap:.5rem; }
.b3d-panel-row button{ flex:1; }
.b3d-empty{ color:var(--dim); text-align:center; padding:.6rem; }
.b3d-splash{
  position:absolute; top:38%; left:50%;
  transform:translate(-50%,-50%);
  font-family:var(--font-head);
  font-size:clamp(2rem, 6vw, 3.4rem); letter-spacing:.1em;
  z-index:5; pointer-events:none;
  animation:b3dSplash 1.15s ease-out forwards;
}
.b3d-splash.dmg{ color:#fff; text-shadow:0 0 16px rgba(229,23,63,.9); }
.b3d-splash.super{ color:#ffd23e; text-shadow:0 0 18px rgba(255,180,40,.9); }
.b3d-splash.hurt{ color:var(--red); text-shadow:0 0 18px rgba(229,23,63,1); }
.b3d-splash.evade{ color:#7fd08a; text-shadow:0 0 16px rgba(90,220,120,.8); }
.b3d-splash.miss{ color:var(--dim); }
@keyframes b3dSplash{
  0%{ opacity:0; transform:translate(-50%,-30%) scale(.7); }
  18%{ opacity:1; transform:translate(-50%,-50%) scale(1.06); }
  70%{ opacity:1; }
  100%{ opacity:0; transform:translate(-50%,-90%) scale(1); }
}

/* ---------- §23 "STUNNED", floated over the knight the asteroid caught ------
   Deliberately NOT the amber "STAGGERED!" of §22. That one is a punish window
   you earned with a single heavy hit; this is crowd control you bought with a
   key and it lands on a whole crater at once. Cold blue-white, heavier and
   wider, and it shudders where the stagger label rises and tilts — so at a
   glance the two never read as the same event. Positioned in per-cent by
   ui/battle3d.js, so a resize mid-float cannot strand it. */
.b3d-float{
  position:absolute; z-index:7; pointer-events:none; white-space:nowrap;
  transform:translate(-50%,-50%); font-family:var(--font-head);
}
.b3d-float.stunned{
  font-size:clamp(1rem,2.8vw,1.7rem);
  letter-spacing:.3em; font-weight:700; color:#dff2ff;
  text-shadow:0 0 10px rgba(96,190,255,.95), 0 0 26px rgba(40,120,220,.75), 0 2px 4px #000;
  animation:b3dStun 1.4s ease-out forwards;
}
@keyframes b3dStun{
  0%{ opacity:0; transform:translate(-50%,-40%) scale(.8); }
  12%{ opacity:1; transform:translate(-50%,-52%) scale(1.1); }
  20%{ transform:translate(-53%,-50%) scale(1.04); }
  28%{ transform:translate(-47%,-52%) scale(1.04); }
  36%{ transform:translate(-51%,-50%) scale(1.02); }
  75%{ opacity:1; transform:translate(-50%,-56%) scale(1); }
  100%{ opacity:0; transform:translate(-50%,-72%) scale(1); }
}
.b3d-controls{
  position:absolute; right:.9rem; bottom:calc(.55rem + env(safe-area-inset-bottom));
  color:#565059; font-size:.68rem; letter-spacing:.05em;
  z-index:3; pointer-events:none;
}
@media (max-width:560px){
  .b3d-party{ width:44vw; }
  .b3d-controls{ display:none; }
  .b3d-log{ bottom:calc(10.2rem + env(safe-area-inset-bottom)); font-size:.75rem; }
}

/* ============================================================
   Combat v3 — real-time HUD, hotbar, bind screen (spec §17)
   ============================================================ */
.b3d-hurt{
  position:absolute; inset:0; pointer-events:none; z-index:7; opacity:0;
  background:radial-gradient(ellipse at center, rgba(229,23,63,0) 45%, rgba(229,23,63,.55) 100%);
}
.b3d-hurt.on{ animation:b3dHurt .5s ease-out; }
@keyframes b3dHurt{ 0%{opacity:0;} 15%{opacity:1;} 100%{opacity:0;} }

.b3d-cross{
  position:absolute; top:50%; left:50%; width:8px; height:8px;
  transform:translate(-50%,-50%); border-radius:50%;
  background:rgba(255,255,255,.55); box-shadow:0 0 5px rgba(0,0,0,.9);
  z-index:5; pointer-events:none; transition:background .12s, transform .12s;
}
.b3d-cross.in-reach{ background:var(--red); transform:translate(-50%,-50%) scale(1.6); }

/* resource bars, bottom-left */
.b3d-res{
  position:absolute; left:.9rem; bottom:calc(5.6rem + env(safe-area-inset-bottom));
  width:min(260px, 42vw); display:flex; flex-direction:column; gap:.28rem; z-index:6;
}
.b3d-res-row{ display:flex; align-items:center; gap:.4rem; }
.b3d-res-row .lbl{
  font-size:.55rem; letter-spacing:.12em; color:var(--dim); width:52px; flex:0 0 auto;
}
.b3d-res-bar{
  flex:1 1 auto; height:9px; border-radius:5px; overflow:hidden;
  background:rgba(0,0,0,.55); border:1px solid #2a2630;
}
.b3d-res-bar .fill{ height:100%; width:100%; transition:width .12s linear; }
.b3d-res-row.hp .fill{ background:linear-gradient(90deg,#e5173f,#ff5c78); }
.b3d-res-row.mana .fill{ background:linear-gradient(90deg,#2f6fd0,#7fb3e8); }
.b3d-res-row.sta .fill{ background:linear-gradient(90deg,#2f9b57,#7fd08a); }
.b3d-res-row .num{ font-size:.6rem; color:var(--dim); width:56px; text-align:right; flex:0 0 auto; }

/* hotbar */
/* §31: the strip is now up to THIRTEEN tiles — 9 keys, 2 buttons, 2 wheel
   directions — and 13 x 66px plus gaps is ~935px, which hangs off both edges
   of a laptop and off the bottom of a phone. It wraps rather than shrinks:
   a tile that scales down loses the icon before it loses the number, and the
   icon is what you actually aim at mid-fight. `max-width` keeps it inside the
   viewport with the same 50%/translateX centring it always had, and
   `justify-content:center` keeps a wrapped second row centred under the
   first instead of hugging the left edge. */
.b3d-hotbar{
  position:absolute; left:50%; bottom:calc(1.1rem + env(safe-area-inset-bottom));
  transform:translateX(-50%); display:flex; gap:.4rem; z-index:6;
  max-width:min(96vw, 960px); flex-wrap:wrap; justify-content:center;
}
.b3d-slot{
  position:relative; width:66px; height:66px; overflow:hidden;
  border:1px solid #2a2630; border-radius:9px; background:rgba(10,10,12,.8);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  cursor:pointer; user-select:none; transition:border-color .12s, box-shadow .12s;
}
.b3d-slot.empty{ opacity:.45; }
.b3d-slot.ready{ border-color:var(--red); box-shadow:0 0 12px rgba(229,23,63,.3); }
.b3d-slot .key{
  position:absolute; top:2px; left:5px; font-size:.6rem; color:var(--dim);
  font-family:var(--font-head); letter-spacing:.08em;
}
.b3d-slot .icon{ font-size:1.5rem; line-height:1; }
.b3d-slot .nm{
  font-size:.52rem; color:var(--dim); letter-spacing:.04em; margin-top:.15rem;
  max-width:92%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.b3d-slot .ch{ position:absolute; top:2px; right:5px; font-size:.62rem; color:#ffd166; }
/* §18: cost chip + cooldown readout on every hotbar slot */
.b3d-slot .cost{
  position:absolute; bottom:2px; left:0; right:0; text-align:center;
  font-size:.5rem; letter-spacing:.04em; color:#7fd08a;
}
.b3d-slot .cost.mana{ color:#7fb3e8; }
.b3d-slot .cd{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-family:var(--font-head); font-size:1.15rem; color:#fff;
  text-shadow:0 2px 6px #000; pointer-events:none; z-index:2;
}
.b3d-slot.broke{ opacity:.5; }
.b3d-slot.broke .cost{ color:var(--red); }
.b3d-slot .sweep{
  position:absolute; left:0; bottom:0; width:100%; height:0%;
  background:rgba(0,0,0,.66); pointer-events:none; transition:height .1s linear;
}
/* §23 pockets: a key holding a consumable. The count badge takes the strip the
   cost chip owns on an ability — same place, opposite question ("how many
   left" rather than "what does it cost"), so the two never share a corner.
   `dim` is the shared consumable lockout OR an empty pocket; `out` is empty
   specifically, and it keeps the icon and the key because the bind SURVIVES
   running out — the slot re-arms the moment you pick another one up. */
.b3d-slot.item .cost.count{ color:var(--gold); font-size:.62rem; letter-spacing:.06em; }
.b3d-slot.item.ready{ border-color:var(--gold); box-shadow:0 0 12px rgba(232,193,90,.28); }
.b3d-slot.item.dim{ opacity:.45; }
.b3d-slot.item.out .icon{ filter:grayscale(1); }
.b3d-slot.item.out .cost.count{ color:var(--red); }

/* §27B: the two mouse slots. They sit at the END of the strip so the nine
   number keys keep the positions the hand already knows, and a hairline gap
   plus a cooler border says "this one is a button, not a key" without a second
   row. The label is 'LMB'/'RMB' — never a 10 or an 11, which would be a lie
   about how you press it — so the key corner needs the room for three glyphs. */
.b3d-slot.mouse{ margin-left:.28rem; border-color:#3a4152; }
/* The wider gap that separates the number keys from the mouse family. This
   was `.mouse:first-of-type`, which never matched anything: :first-of-type
   means "first <div> among its siblings" and buildHotbar appends the nine
   key tiles first, so the hotbar's first div is never a .mouse one. The
   adjacent-sibling form says what was meant — the first .mouse tile that
   FOLLOWS a key tile — and it matters more now that four tiles share that
   side of the divide instead of two. */
.b3d-slot:not(.mouse) + .b3d-slot.mouse{ margin-left:.55rem; }
.b3d-slot.mouse .key{ font-size:.52rem; color:#8fa2c0; letter-spacing:.04em; }
.b3d-slot.mouse.ready{ border-color:var(--red); }

/* §27C: the revive potion. ARMED is not READY and must not look like it —
   a steady ring that says "this is standing by", never the pressable glow,
   because the one thing the player must not learn is to press it. Spent, it
   drops to the same dim as an empty pocket. */
.b3d-slot.item.passive{ cursor:default; }
.b3d-slot.item.passive.armed{
  border-color:var(--gold); box-shadow:inset 0 0 0 1px rgba(232,193,90,.45), 0 0 10px rgba(232,193,90,.2);
  opacity:1;
}
.b3d-slot.item.passive.armed .cost.count{ color:var(--gold); }
.b3d-slot.item.passive.out{ opacity:.4; }
.b3d-slot.item.passive .sweep{ display:none; }   /* it has no cooldown to sweep */

/* evade pip */
.b3d-evade{
  position:absolute; right:.9rem; bottom:calc(1.4rem + env(safe-area-inset-bottom));
  padding:.4rem .7rem; border-radius:9px; text-align:center; z-index:6;
  border:1px solid #2a2630; background:rgba(10,10,12,.8); opacity:.5;
  transition:opacity .12s, border-color .12s, box-shadow .12s;
}
.b3d-evade b{ display:block; font-family:var(--font-head); letter-spacing:.1em; font-size:.85rem; }
.b3d-evade span{ display:block; font-size:.55rem; color:var(--dim); letter-spacing:.1em; }
.b3d-evade.ready{ opacity:1; border-color:#7fd08a; box-shadow:0 0 12px rgba(127,208,138,.25); }
.b3d-evade.iframe{ border-color:#fff; box-shadow:0 0 18px rgba(255,255,255,.5); }

/* cast bar */
.b3d-cast{
  position:absolute; left:50%; top:58%; transform:translateX(-50%);
  width:min(240px,40vw); height:6px; border-radius:4px; z-index:6;
  background:rgba(0,0,0,.6); border:1px solid #2a2630; overflow:hidden;
}
.b3d-cast.hidden{ display:none; }
.b3d-cast .fill{ height:100%; width:0%; background:linear-gradient(90deg,#e5a017,#ffd166); }

/* ---------- bind screen (Menu -> Moves) ---------- */
.bind-slots{ display:flex; flex-wrap:wrap; gap:.4rem; margin:.7rem 0; }
.bind-slot{
  width:74px; height:70px; border:1px solid #2a2630; border-radius:9px;
  background:#141317; display:flex; flex-direction:column;
  align-items:center; justify-content:center; cursor:pointer; position:relative;
}
.bind-slot.sel{ border-color:var(--red); box-shadow:0 0 12px rgba(229,23,63,.3); }
.bind-slot.locked{ opacity:.38; cursor:not-allowed; }
.bind-slot .key{ position:absolute; top:3px; left:6px; font-size:.6rem; color:var(--dim); }
.bind-slot .icon{ font-size:1.4rem; }
.bind-slot .nm{
  font-size:.52rem; color:var(--dim); max-width:92%;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.bind-head{
  font-family:var(--font-head); letter-spacing:.1em; color:var(--text);
  margin:.8rem 0 .4rem; font-size:.95rem;
}
.bind-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(210px,1fr)); gap:.5rem; }
.bind-card{
  border:1px solid #2a2630; border-radius:9px; background:#141317;
  padding:.5rem .6rem; cursor:pointer; transition:border-color .12s;
}
.bind-card:hover{ border-color:var(--deep-red); }
.bind-card.on{ border-color:var(--red); box-shadow:0 0 10px rgba(229,23,63,.22); }
.bind-card-head{ display:flex; align-items:center; gap:.4rem; }
.bind-card-head .icon{ font-size:1.15rem; }
.bind-card-head .nm{ font-family:var(--font-head); letter-spacing:.06em; }
.bind-card-head .at{ margin-left:auto; font-size:.58rem; color:var(--red); }
.bind-card .ds{ color:var(--dim); font-size:.72rem; margin:.3rem 0; }
.bind-meta{ display:flex; flex-wrap:wrap; gap:.5rem; font-size:.6rem; color:#7f7885; }
/* §23 pockets in the Moves tab. The consumables group reuses the ability card
   wholesale — same shape, same gesture, because it binds to the same kind of
   key. Only the carried count is new. A key holding an item is NOT drawn as a
   special "pocket" key: any slot takes either, and marking two of them apart
   would teach a rule the game does not have. */
.bind-slot .ct{ position:absolute; bottom:3px; right:6px; font-size:.58rem; color:var(--gold); }
.bind-slot.out{ opacity:.55; }
.bind-slot.out .ct{ color:var(--red); }
.bind-card.item .ct{ color:var(--gold); }
.bind-card.item.out{ opacity:.6; }
.bind-card.item.out .ct{ color:var(--red); }
/* a refused bind has to say why, and it must not read as the calm grey note */
.menu-note.warn{ color:#ffc27a; }

@media (max-width:560px){
  .b3d-slot{ width:52px; height:52px; }
  .b3d-slot .icon{ font-size:1.1rem; }
  .b3d-slot .nm{ display:none; }
  .b3d-res{ width:46vw; }
}

/* ---------------------------------------------- §21 loading gate
   Sits over everything while a 3D scene streams in and warms its shaders.
   Deliberately CSS-only animation: this is on screen exactly when the main
   thread is busy parsing a 26MB church, so it must not ask for JS frames. */
.loading-veil{
  position:fixed; inset:0; z-index:120;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(ellipse at 50% 45%, #1a0d12 0%, #08060a 70%);
  opacity:1; transition:opacity .3s ease;
}
.loading-veil.out{ opacity:0; pointer-events:none; }
.loading-card{ width:min(420px,84vw); text-align:center; }
.loading-title{
  font-family:var(--font-head); font-size:2.6rem; letter-spacing:.34em;
  color:var(--red); text-shadow:0 0 26px rgba(229,23,63,.5);
  animation:loadPulse 2.6s ease-in-out infinite;
}
@keyframes loadPulse{ 0%,100%{ opacity:.82; } 50%{ opacity:1; } }
.loading-label{ color:var(--dim); font-size:.8rem; margin:.7rem 0 1rem; min-height:1.1em; }
.loading-track{
  height:4px; border-radius:3px; background:rgba(255,255,255,.08); overflow:hidden;
}
.loading-bar{
  height:100%; width:0%; border-radius:3px;
  background:linear-gradient(90deg,#8c1028,var(--red),#ff7a44);
  transition:width .28s ease;
}
.loading-embers{ position:relative; height:44px; margin-top:.5rem; }
.loading-embers span{
  position:absolute; bottom:0; left:50%; width:4px; height:4px; border-radius:50%;
  background:#ff7a44; box-shadow:0 0 8px #ff5a1a;
  animation:ember 1.65s ease-in-out infinite;
}
.loading-embers span:nth-child(1){ margin-left:-26px; }
.loading-embers span:nth-child(2){ margin-left:0; }
.loading-embers span:nth-child(3){ margin-left:26px; }
@keyframes ember{
  0%{ transform:translateY(0) scale(.7); opacity:0; }
  35%{ opacity:1; }
  100%{ transform:translateY(-34px) scale(1.15); opacity:0; }
}
.loading-tip{
  color:#6e6774; font-size:.7rem; font-style:italic; margin-top:.6rem;
  min-height:2.4em; line-height:1.5;
}

/* ------------------------------------------- §21 level ladder (Moves tab)
   Replaces the Skill Tree screen. Progression is a ladder with nothing to
   spend, so it lives next to the keys it unlocks rather than on its own page. */
.moves-who{ display:flex; flex-wrap:wrap; gap:.4rem; margin:.5rem 0 .2rem; }
.moves-who button{ font-size:.7rem; padding:.28rem .6rem; }
.moves-who button.on{ border-color:var(--red); color:var(--txt); }
.ladder-now{ display:flex; align-items:center; gap:.6rem; margin:.4rem 0 .7rem; }
.ladder-now .lv{ font-family:var(--font-head); font-size:1.1rem; color:var(--red); letter-spacing:.08em; }
.ladder-now .xp{ font-size:.65rem; color:var(--dim); white-space:nowrap; }
.ladder-xp{ flex:1; height:5px; border-radius:3px; background:rgba(255,255,255,.08); overflow:hidden; }
.ladder-xp-fill{ height:100%; background:linear-gradient(90deg,var(--deep-red),var(--red)); border-radius:3px; }
.ladder-list{ display:flex; flex-direction:column; gap:.3rem; }
.ladder-row{
  display:flex; align-items:center; gap:.6rem;
  border:1px solid #24212a; border-left:3px solid #24212a; border-radius:7px;
  background:#121116; padding:.4rem .6rem; opacity:.55;
}
.ladder-row.got{ opacity:1; border-left-color:var(--deep-red); }
.ladder-row.here{ border-color:var(--red); border-left-color:var(--red); background:#191218; }
.ladder-row .l{
  font-family:var(--font-head); font-size:.95rem; color:var(--dim);
  min-width:1.6rem; text-align:center;
}
.ladder-row.got .l{ color:var(--red); }
.ladder-row .b{ flex:1; min-width:0; }
.ladder-row .nm{ font-family:var(--font-head); letter-spacing:.05em; font-size:.82rem; }
.ladder-row .ds{ color:var(--dim); font-size:.68rem; line-height:1.4; }
.ladder-row .give{ font-size:.68rem; color:#c8c2cc; white-space:nowrap; text-align:right; }
@media (max-width:560px){
  .ladder-row{ flex-wrap:wrap; }
  .ladder-row .give{ width:100%; text-align:left; padding-left:2.2rem; }
}

/* §23/build stamp — the version shown inside the menu card. Deliberately
   quiet: it is a reference you go looking for, not something competing with
   the tabs. Same dim token as .title-foot so the two readings of the version
   look like the same fact stated twice, not two different UI elements. */
.menu-version{
  margin-top:.55rem; padding-top:.5rem;
  border-top:1px solid rgba(255,255,255,.07);
  text-align:right; color:var(--dim);
  font-size:.72rem; letter-spacing:.06em;
  font-variant-numeric:tabular-nums;   /* the build digit changes often; stop the line jittering */
}

/* ---------- §27D The shop (the giftbox) ----------
   Deliberately built ON TOP of the menu overlay's rules rather than beside
   them: .shop-card carries .menu-card and .shop-body carries .menu-body, so
   the veil, the card frame and the scroll behaviour are the SAME rules, not a
   second copy that drifts a border-radius away over time. Only what a shop
   needs that a menu does not — a balance, a price, a shortfall — is new here. */
#overlay-shop{
  position:absolute; inset:0;
  z-index:70;                 /* same plane as #overlay-menu; the two are never open together */
  background:rgba(5,5,7,.82);
  display:flex; align-items:center; justify-content:center;
  animation:veilIn .25s ease both;
}
.shop-card{ width:min(660px,94vw); }

.shop-head{
  display:flex; align-items:center; gap:.8rem;
  padding:.6rem .7rem .6rem 1.1rem;
  border-bottom:1px solid #2b2731;
  background:#100f13;         /* matches .menu-tabs — the header band reads as the same strip */
}
.shop-title{
  flex:1; min-width:0;
  font-family:var(--font-head); letter-spacing:.14em;
  font-size:1.25rem; color:var(--text);
}
/* The balance the player is doing arithmetic against. Gold like every other
   shard count in the game (.inv-count, the result panel), tabular so buying
   three bandages does not make the header twitch. */
.shop-balance{
  font-family:var(--font-head); font-size:1.25rem; letter-spacing:.08em;
  color:var(--gold);
  font-variant-numeric:tabular-nums;
  white-space:nowrap;
}
.shop-balance .sym{ margin-right:.25em; opacity:.85; }
.shop-close{
  border:none; background:none; color:var(--dim);
  font-size:1.1rem; padding:.35em .6em; border-radius:6px;
}
.shop-close:hover:not(:disabled){ background:#1a161d; color:var(--red); box-shadow:none; }

.shop-body{ padding:.9rem 1.1rem 1.1rem; }

/* Feedback for the last click. Inline under the header instead of a toast:
   the toast layer sits above this overlay but the player's eyes are on the
   row they just pressed, and "◆ 7 short" is information they act on, not a
   notification they dismiss. */
.shop-feedback{
  border-radius:8px; padding:.45rem .7rem; margin-bottom:.7rem;
  font-size:.86rem; border:1px solid #2b2731; background:var(--panel-2);
  color:var(--dim);
}
.shop-feedback.good{ color:var(--ok); border-color:rgba(61,220,132,.35); }
.shop-feedback.bad{ color:var(--red); border-color:rgba(229,23,63,.4); }

.shop-row{
  display:flex; align-items:center; gap:.8rem;
  background:var(--panel-2);
  border:1px solid #2b2731;
  border-radius:8px;
  padding:.6rem .8rem;
  margin-bottom:.55rem;
  transition:border-color .15s ease, background .15s ease, opacity .15s ease;
}
.shop-icon{ font-size:1.6rem; flex:0 0 auto; width:1.6em; text-align:center; }
.shop-main{ flex:1; min-width:0; }
.shop-main .nm{ font-weight:600; }
.shop-main .fx{ color:var(--mp); font-size:.8rem; }   /* what it DOES, in the resource blue */
.shop-main .ds{ color:var(--dim); font-size:.78rem; }

.shop-right{ flex:0 0 auto; text-align:right; line-height:1.25; }
.shop-price{
  font-family:var(--font-head); font-size:1.15rem; letter-spacing:.06em;
  color:var(--gold); font-variant-numeric:tabular-nums; white-space:nowrap;
}
.shop-price .sym{ margin-right:.2em; opacity:.85; }
.shop-short{ color:var(--red); font-size:.72rem; white-space:nowrap; }
.shop-have{ color:var(--dim); font-size:.72rem; white-space:nowrap; }
.shop-buy{ flex:0 0 auto; min-width:5.2em; }

/* Can't afford it. Dimmed but still READABLE — the row has to stay a price
   you are saving toward, so the name and the shortfall keep their contrast
   while the icon and flavour fade back. */
.shop-row.poor{ opacity:.62; border-color:#241f28; }
.shop-row.poor .shop-icon{ opacity:.5; }
.shop-row.poor .shop-price{ color:#8a7a4e; }
.shop-row.poor .shop-short{ opacity:1; }
/* The row is already at .62 and the global button:disabled is .38 — left to
   compound, the Buy fades to ~.24 and the row reads as broken rather than
   unaffordable. Lift the button back so it still says "Buy", greyed. */
.shop-row.poor .shop-buy:disabled{ opacity:.7; }

/* One pulse on the row you just bought, so a purchase is visible even when
   the only number that changed is a "carrying" count further down the row. */
.shop-row.bought{ border-color:var(--ok); background:#171d19; animation:shopBuy .5s ease both; }
/* Buying the last one you could afford leaves the row both .bought and .poor.
   The confirmation has to win: a green pulse at .62 opacity reads as a glitch,
   and the row already says "need ◆ N more" for the next one. */
.shop-row.poor.bought{ opacity:1; }
@keyframes shopBuy{
  from{ box-shadow:0 0 0 rgba(61,220,132,0); }
  35%{ box-shadow:0 0 16px rgba(61,220,132,.45); }
  to{ box-shadow:0 0 0 rgba(61,220,132,0); }
}

.shop-foot{
  padding:.55rem 1.1rem .7rem;
  border-top:1px solid #2b2731;
  color:var(--dim); font-size:.72rem; letter-spacing:.04em;
}

/* Narrow: the price column drops under the name rather than squeezing the
   Buy button off the card. */
@media (max-width:560px){
  .shop-row{ flex-wrap:wrap; }
  .shop-right{ text-align:left; }
  .shop-buy{ margin-left:auto; }
}
@media (prefers-reduced-motion:reduce){
  #overlay-shop{ animation:none; }
  .shop-row.bought{ animation:none; }
}

/* ============================================================
   The Ring — deathmatch lobby + the hub's score line, spec §32
   ============================================================
   Built ON TOP of the menu overlay's rules, exactly the way §27D's shop is:
   .lobby-card carries .menu-card and .lobby-body carries .menu-body, so the
   card frame, the max-height and the scroll behaviour are the SAME rules —
   not a second copy that drifts a border-radius away over time. Only what a
   lobby needs and a menu does not (a transport line, a selectable room code,
   eight seats with ready ticks) is new below. */

/* .screen.active is display:BLOCK only, so any screen that wants to centre a
   card has to say so itself — #screen-title has carried this same pair since
   §8. Without it the lobby renders anchored to the top-left corner. */
#screen-lobby{
  background:var(--bg);
  display:none;
  align-items:center; justify-content:center;
  padding:1rem;
}
#screen-lobby.active{ display:flex; }
.lobby-card{ width:min(560px,94vw); }

/* ---------- head: the title and the transport sentence ---------- */
.lobby-head{
  display:flex; align-items:flex-start; gap:.8rem;
  padding:.6rem .7rem .65rem 1.1rem;
  border-bottom:1px solid #2b2731;
  background:#100f13;        /* matches .menu-tabs / .shop-head — one header band */
}
.lobby-titles{ flex:1; min-width:0; }
.lobby-title{
  font-family:var(--font-head); letter-spacing:.14em;
  font-size:1.25rem; color:var(--text);
}
/* "8 players" means something completely different on each transport, so the
   line that says which one is running sits in the header where it cannot
   scroll away — and it is coloured by ANSWER, not by severity: local is a
   working mode, not a warning. Only a browser with neither transport gets
   the red. */
.lobby-transport{ font-size:.74rem; letter-spacing:.04em; color:var(--dim); }
.lobby-transport.relay{ color:var(--ok); }
.lobby-transport.local{ color:var(--mp); }
.lobby-transport.none{ color:var(--red); }
.lobby-close{
  border:none; background:none; color:var(--dim);
  font-size:1.1rem; padding:.35em .6em; border-radius:6px;
}
.lobby-close:hover:not(:disabled){ background:#1a161d; color:var(--red); box-shadow:none; }

/* ---------- body ---------- */
.lobby-body{ padding:.9rem 1.1rem 1.1rem; }
.lobby-note{ color:var(--dim); font-size:.86rem; margin-bottom:.9rem; }
.lobby-hint{ color:var(--dim); font-size:.72rem; margin-top:.35rem; }

.lobby-field{ margin-bottom:.9rem; }
.lobby-field label{
  display:block; margin-bottom:.3rem;
  font-family:var(--font-head); letter-spacing:.12em;
  font-size:.8rem; color:var(--dim);
}

/* Host on the left, join on the right, "or" between them: the two ways in are
   a choice, and stacking them would make the second look like a step. */
.lobby-split{ display:flex; align-items:flex-start; gap:.8rem; }
.lobby-half{ flex:1; min-width:0; }
.lobby-half button{ width:100%; }
.lobby-or{
  flex:0 0 auto; align-self:center;
  font-family:var(--font-head); letter-spacing:.1em;
  color:var(--dim); font-size:.8rem;
}
.lobby-joinrow{ display:flex; gap:.4rem; }
.lobby-codein{
  flex:1; min-width:0;
  font-family:var(--font-head); letter-spacing:.28em;
  text-align:center; text-transform:uppercase;
}
.lobby-join{ flex:0 0 auto; }

/* ---------- the room code ---------- */
.lobby-code-row{
  display:flex; align-items:center; gap:.7rem;
  background:var(--panel-2);
  border:1px solid #2b2731;
  border-radius:8px;
  padding:.55rem .7rem;
  margin-bottom:.8rem;
}
.lobby-code-label{
  font-family:var(--font-head); letter-spacing:.12em;
  font-size:.78rem; color:var(--dim);
  white-space:nowrap;
}
/* THE RULE THIS SCREEN CANNOT SHIP WITHOUT.
   body{user-select:none} is global (top of this file). Without the override
   here a player physically cannot drag over the room code — and a room code
   nobody can copy is a multiplayer mode nobody can be invited to. The Copy
   button beside it works through document.execCommand('copy'), which needs a
   REAL selection to copy, so this rule is load-bearing on both routes, not
   just the manual one. */
.lobby-code{
  -webkit-user-select:text;
  user-select:text;
  cursor:text;
  flex:1; min-width:0;
  font-family:var(--font-head);
  font-size:1.5rem; letter-spacing:.36em;
  text-align:center;
  color:var(--text);
  text-shadow:0 0 12px rgba(229,23,63,.28);
}
.lobby-code::selection{ background:var(--deep-red); color:#fff; }
.lobby-copy{ flex:0 0 auto; padding:.35em .9em; font-size:.85rem; }

/* The score on the card, when the lobby is opened over a match this client is
   already out of. Same reading as .r3d-standing in the top bar — one fact,
   stated the same way in both places. */
.lobby-standing{
  font-family:var(--font-head);
  font-size:1.6rem; letter-spacing:.14em;
  text-align:center;
  color:var(--red);
  text-shadow:0 0 14px rgba(229,23,63,.35);
  font-variant-numeric:tabular-nums;
}

/* ---------- the eight seats ----------
   The empty seats are DRAWN, not omitted: five dim rows under three lit ones
   is the same fact as "3 of 8" and you can read it without counting. */
.lobby-roster{ display:flex; flex-direction:column; gap:.35rem; }
.lobby-seat{
  display:flex; align-items:center; gap:.6rem;
  background:var(--panel-2);
  border:1px solid #2b2731;
  border-radius:8px;
  padding:.42rem .7rem;
  transition:border-color .15s ease, background .15s ease;
}
/* Identity is the seat TINT — the same colour data/pvp.js hands the body in
   the arena, so the name you read here is the body you are looking at there.
   The dot's colour is set inline from that data; this only shapes it. */
.seat-dot{
  flex:0 0 auto;
  width:.7rem; height:.7rem;
  border-radius:50%;
  background:#3a3540;
  box-shadow:0 0 8px rgba(0,0,0,.6);
}
.lobby-seat .nm{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.lobby-seat .tag{
  flex:0 0 auto;
  font-family:var(--font-head); font-size:.66rem; letter-spacing:.14em;
  padding:.05em .5em; border-radius:999px;
  border:1px solid var(--deep-red); color:var(--red);
}
.lobby-seat .tag.you{ border-color:#3a3540; color:var(--dim); }
.lobby-seat .lv{
  flex:0 0 auto;
  color:var(--gold); font-size:.75rem;
  font-variant-numeric:tabular-nums;   /* levels move mid-match; stop the row twitching */
}
/* Always present, lit or dim. A tick that appears and disappears makes the
   row jump, and a row that jumps while people are readying up is the one
   thing a lobby must not do. */
.lobby-seat .tick{
  flex:0 0 auto; width:1.1em; text-align:center;
  color:#3a3540; font-size:.95rem;
}
.lobby-seat.ready{ border-color:rgba(61,220,132,.35); }
.lobby-seat.ready .tick{ color:var(--ok); }
.lobby-seat.me{ border-color:var(--red); box-shadow:0 0 14px rgba(229,23,63,.18); }
.lobby-seat.empty{ opacity:.42; border-style:dashed; }
.lobby-seat.empty .nm{ color:var(--dim); font-style:italic; }
.lobby-seat.out{ opacity:.5; }
.lobby-seat.out .nm{ text-decoration:line-through; }

/* ---------- foot: the status line and the three buttons ---------- */
.lobby-foot{
  padding:.55rem 1.1rem .8rem;
  border-top:1px solid #2b2731;
}
/* Inline, not a toast: "type the code you were given" is something the player
   acts on in the field two inches above it, not a notification to dismiss.
   Reserved height so the buttons never jump when a message comes and goes. */
.lobby-msg{
  min-height:1.2em;
  color:var(--dim); font-size:.78rem; letter-spacing:.03em;
  margin-bottom:.5rem;
}
.lobby-msg.good{ color:var(--ok); }
.lobby-msg.bad{ color:var(--red); }
.lobby-btns{ display:flex; gap:.5rem; }
.lobby-btns button{ flex:1; }
.lobby-ready.on{ border-color:var(--ok); color:var(--ok); }
.lobby-ready.on:hover:not(:disabled){ background:var(--ok); color:var(--bg); border-color:var(--ok); box-shadow:none; }
/* The only loud button on the card: pressing it drops eight people onto the
   Ring, and it is lit only while pvp.canStart() agrees. */
.lobby-start{ border-color:var(--red); background:#25101a; }
.lobby-leave{ flex:0 0 auto; color:var(--dim); }

/* ---------- the hub's score line (ui/room3d.js top bar) ----------
   Same pill lineage as .r3d-level, so the top bar stays one row of facts
   rather than growing a badge someone bolted on. Red rather than dim because
   it is a fight in progress you are watching, not a stat you own. */
.r3d-standing{
  align-self:center;
  font-family:var(--font-head);
  font-size:.95rem; letter-spacing:.12em;
  color:var(--red);
  padding:.2em .7em;
  border:1px solid rgba(229,23,63,.45);
  border-radius:999px;
  background:rgba(20,19,23,.55);
  text-shadow:0 0 10px rgba(229,23,63,.3);
  white-space:nowrap;
}
.r3d-ring{ letter-spacing:.06em; }

/* Narrow: the two ways in stack, and the "or" reads as a divider between
   them rather than a squeezed column. */
@media (max-width:560px){
  .lobby-split{ flex-direction:column; align-items:stretch; }
  .lobby-or{ align-self:center; }
  .lobby-code{ font-size:1.2rem; letter-spacing:.28em; }
  .lobby-btns{ flex-wrap:wrap; }
  .r3d-standing{ font-size:.72rem; }
  .r3d-ring{ font-size:.8rem; }
}

/* The title screen's second door (§32). Quieter than .title-start on
   purpose: starting a run is the primary act and keeps the pulse, while this
   one is for the player who already has a code and knows what they came for. */
.title-join{
  margin-top:.7rem;
  font-family:var(--font-head);
  font-size:clamp(.85rem,2vw,1rem);
  letter-spacing:.18em;
  padding:.45em 1.3em;
  opacity:.86;
}
.title-join:hover{ opacity:1; }
