@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@500;700&family=EB+Garamond:ital,wght@0,400;0,600;1,400&family=Metamorphous&display=swap');

:root{
  --stone-deep:#171009;
  --stone:#221a10;
  --parchment:#e9d9b4;
  --parchment-dark:#dcc696;
  --parchment-shadow:#b89c68;
  --ink:#2b1d10;
  --ink-soft:#5a4527;
  --blood:#7c2222;
  --blood-dark:#5a1818;
  --steel:#37545c;
  --steel-dark:#263d43;
  --gold:#a97a1f;
  --gold-bright:#d3a53f;
  --border:#6b4a2b;
  --ok:#3f5f3a;
}

*{box-sizing:border-box;}

html,body{margin:0;padding:0;}

body{
  min-height:100vh;
  background:radial-gradient(ellipse at top, #2a2013 0%, var(--stone-deep) 70%);
  font-family:'EB Garamond', serif;
  color:var(--ink);
}

h1,h2,h3{font-family:'Cinzel', serif; letter-spacing:.02em;}

button{font-family:'EB Garamond', serif; cursor:pointer;}

.btn{
  border:1px solid var(--border);
  background:var(--parchment);
  color:var(--ink);
  padding:10px 18px;
  border-radius:3px;
  font-size:16px;
  font-weight:600;
  box-shadow:0 2px 0 var(--parchment-shadow), 0 3px 6px rgba(0,0,0,.4);
}
.btn:active{transform:translateY(1px); box-shadow:0 1px 0 var(--parchment-shadow);}
.btn-primary{background:var(--blood); color:var(--parchment); border-color:var(--blood-dark);}
.btn-ghost{background:transparent; color:var(--parchment); border-color:#7a6440;}
.btn-small{padding:5px 10px; font-size:13px;}
.btn-danger{background:var(--stone); color:#e0a1a1; border-color:var(--blood-dark);}
.btn[disabled]{opacity:.45; cursor:not-allowed;}

.masthead{max-width:960px; margin:0 auto; text-align:center; color:var(--parchment); padding:20px 16px 8px;}
.masthead h1{font-family:'Metamorphous', 'Cinzel', serif; font-size:clamp(24px,5.5vw,36px); letter-spacing:.03em; margin:0 0 4px; color:var(--gold-bright); text-shadow:0 2px 0 #000, 0 0 18px rgba(211,165,63,.3);}
.masthead p{margin:0; font-style:italic; color:#c9b98c; font-size:14px;}

.wrap{max-width:1480px; margin:0 auto; padding:0 12px 40px;}

.card{
  background:linear-gradient(180deg, var(--parchment) 0%, var(--parchment-dark) 100%);
  border:1px solid var(--border);
  border-radius:4px;
  padding:16px;
  box-shadow:0 6px 14px rgba(0,0,0,.45);
  position:relative;
}

.field{margin-bottom:14px;}
.field label{display:block; font-size:13px; font-weight:600; color:var(--ink-soft); margin-bottom:5px;}
.field input[type=text], .field input[type=number], .field select{
  width:100%; font-family:'EB Garamond', serif; font-size:16px; padding:8px 10px;
  border:1px solid var(--border); border-radius:3px; background:#f4ead2; color:var(--ink);
}

.class-picker{display:grid; grid-template-columns:repeat(2,1fr); gap:8px;}
.class-opt{
  border:1px solid var(--border); background:#f4ead2; border-radius:4px; padding:9px 10px;
  text-align:left; font-family:'EB Garamond', serif; display:flex; align-items:center; gap:9px;
}
.class-opt img{width:34px; height:34px; border-radius:50%; object-fit:cover; border:1px solid var(--border);}
.class-opt b{display:block; font-size:15px; color:var(--ink); font-family:'Cinzel',serif;}
.class-opt span{font-size:11.5px; color:var(--ink-soft);}
.class-opt.selected{background:var(--steel); border-color:var(--steel-dark);}
.class-opt.selected b, .class-opt.selected span{color:#f2ead6;}

.avatar-thumb{width:44px;height:44px;border-radius:50%;object-fit:cover;border:2px solid var(--border);flex-shrink:0;}
.avatar-thumb-lg{width:60px;height:60px;border-radius:50%;object-fit:cover;border:2px solid var(--border);flex-shrink:0;}

.bar-track{height:9px; background:rgba(43,29,16,.18); border-radius:5px; overflow:hidden; border:1px solid rgba(43,29,16,.3);}
.bar-fill{height:100%; border-radius:5px;}
.bar-body{background:linear-gradient(90deg, var(--blood-dark), var(--blood));}
.bar-mind{background:linear-gradient(90deg, var(--steel-dark), var(--steel));}

.pill-btn{width:30px; height:30px; border:1px solid var(--border); background:#f4ead2; border-radius:4px; font-size:15px; font-weight:700; color:var(--ink);}

svg.ic{display:block;}

/* ---------- tablero: pantalla completa de verdad ---------- */
body.on-board-screen{overflow:hidden;}
body.on-board-screen .masthead{display:none;}
body.on-board-screen .wrap{
  position:fixed; top:0; right:0; bottom:0; left:0; max-width:none; margin:0; padding:0; z-index:1;
}
.board-fullscreen{position:absolute; top:0; right:0; bottom:0; left:0; background:#000;}
/* el tablero de partida (no el del editor, que sigue con estilos normales
   de documento) vive en pantalla completa — se referencia por id para no
   afectar a #editorBoardFrame/#editorBoardGrid, que comparten las mismas
   clases pero no deben salirse del flujo normal de la página. */
#boardScroll{
  position:absolute; top:0; right:0; bottom:0; left:0;
  touch-action:none;
}
#boardFrame{box-shadow:none;}

/* el tablero del EDITOR de mazmorras, a partir de la v0.22.0, comparte la
   misma pantalla completa que el de la partida real (mismo motivo: el
   tablero es la pantalla principal, con badge/zoom/fabs/popups flotando
   encima) — antes vivía en el flujo normal de la página, dentro de un
   formulario apilado. */
#editorBoardScroll{
  position:absolute; top:0; right:0; bottom:0; left:0;
  touch-action:none;
}
#editorBoardFrame{box-shadow:none;}

.hidden{display:none !important;}

/* pequeño marcador de turno, arriba a la izquierda */
.turn-tracker-badge{
  position:absolute; top:10px; left:10px; z-index:5;
  display:flex; align-items:center; gap:8px;
  background:rgba(23,16,9,.85); border:1px solid var(--border); border-radius:24px;
  padding:4px 14px 4px 4px;
  box-shadow:0 3px 10px rgba(0,0,0,.5);
  cursor:pointer;
}
.turn-tracker-badge .avatar{width:34px; height:34px; border-radius:50%; object-fit:cover; border:2px solid var(--gold-bright); display:block;}
.turn-tracker-badge .zargon-ic{width:34px; height:34px; border-radius:50%; background:var(--blood); display:flex; align-items:center; justify-content:center; border:2px solid var(--gold-bright); font-size:16px;}
.turn-tracker-badge span{color:var(--parchment); font-family:'Cinzel',serif; font-size:12.5px;}

.mode-banner{
  position:absolute; top:54px; left:10px; right:10px; z-index:5;
  background:var(--blood); color:var(--parchment); border:1px solid var(--blood-dark);
  border-radius:6px; padding:8px 10px; font-size:12.5px;
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  box-shadow:0 3px 10px rgba(0,0,0,.5);
}
/* El editor deja este aviso siempre visible (con el modo actual, no solo
   durante puertas/monstruos como en la partida real) flotando sobre el
   tablero — así que su propio hueco vacío no debe robarle el toque a una
   ficha/puerta que quede justo debajo tras desplazar el tablero. Solo el
   texto y los botones de dentro son realmente tocables. */
#editorModeBanner{pointer-events:none;}
#editorModeBanner > *{pointer-events:auto;}

/* barra de zoom, discreta, arriba a la derecha */
.board-zoom-bar{
  position:absolute; top:10px; right:10px; z-index:5;
  display:flex; align-items:center; gap:4px;
  background:rgba(23,16,9,.85); border:1px solid var(--border); border-radius:20px;
  padding:4px 8px;
}
.board-zoom-bar .btn{padding:3px 9px; font-size:13px;}
.board-zoom-bar #zoomLevel{font-family:'Cinzel',serif; font-size:11px; min-width:34px; text-align:center; color:var(--parchment);}
/* mismo motivo que #editorModeBanner: el hueco entre botones no debe tapar
   una puerta/ficha que quede justo debajo al desplazar el tablero. */
.board-zoom-bar{pointer-events:none;}
.board-zoom-bar > *{pointer-events:auto;}
.fab-stack{pointer-events:none;}
.fab-stack > *{pointer-events:auto;}

/* pila de botones flotantes a la derecha: personaje, dado, pasar turno, registro */
.fab-stack{
  position:absolute; right:10px; bottom:16px; z-index:6;
  display:flex; flex-direction:column; gap:12px; align-items:center;
}
.fab{
  width:56px; height:56px; border-radius:50%;
  border:2px solid var(--gold-bright);
  background:var(--stone); color:var(--parchment);
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 4px 14px rgba(0,0,0,.6);
  font-size:22px; padding:0; cursor:pointer;
  position:relative;
}
.fab img{width:100%; height:100%; border-radius:50%; object-fit:cover;}
.fab.fab-move-die{background:var(--blood); border-color:#e0a1a1;}
.fab.fab-move-die.rolled{background:var(--parchment); color:var(--ink); font-family:'Cinzel',serif; font-weight:700; font-size:20px;}
.fab.fab-end-turn{background:var(--steel);}
.fab.fab-active{background:var(--blood); border-color:#e0a1a1;}
.fab[disabled]{opacity:.4; cursor:not-allowed;}
.fab-label{position:absolute; bottom:-16px; left:50%; transform:translateX(-50%); font-size:9px; color:var(--parchment); white-space:nowrap; opacity:.8;}

/* modal de ficha de personaje / herramientas de Zargon / registro:
   igual de flotante que el de dados, pero con contenido desplazable */
.sheet-modal-overlay{
  position:fixed; top:0; right:0; bottom:0; left:0; z-index:60;
  background:rgba(10,7,4,.78);
  display:flex; align-items:flex-end; justify-content:center;
}
.sheet-modal-card{
  background:linear-gradient(180deg, var(--parchment), var(--parchment-dark));
  border:1px solid var(--border); border-radius:10px 10px 0 0;
  padding:16px; width:100%; max-width:460px;
  max-height:82vh; overflow-y:auto;
  box-shadow:0 -10px 40px rgba(0,0,0,.7);
  animation:sheetSlideUp .22s ease-out;
}
@keyframes sheetSlideUp{0%{transform:translateY(30px); opacity:0;} 100%{transform:translateY(0); opacity:1;}}
.sheet-modal-card h3{margin:0 0 10px;}
.sheet-modal-close{
  display:block; margin:0 0 10px auto;
  width:32px; height:32px; padding:0; border-radius:50%; font-size:15px;
}

/* aviso de cambio de turno */
.turn-announce-card{text-align:center;}
.turn-announce-card .avatar-big{width:84px; height:84px; border-radius:50%; object-fit:cover; border:3px solid var(--gold-bright); margin:0 auto 12px; display:block;}

/* ---------- pantallas ---------- */
.screen{max-width:520px; margin:0 auto;}
.mode-buttons{display:flex; flex-direction:column; gap:12px; margin-top:18px;}
.mode-buttons .btn{width:100%; padding:16px; font-size:17px;}

.hero-slot{display:flex; gap:10px; align-items:center; margin-bottom:12px;}
.hero-slot .field{flex:1; margin-bottom:0;}

/* ---------- tablero ---------- */
.board-wrap{min-width:280px;}
.board-scroll{
  overflow:auto; -webkit-overflow-scrolling:touch;
  border-radius:4px;
  overscroll-behavior:contain;
}
.board-frame{position:relative; width:100%; border:2px solid var(--border); border-radius:4px; overflow:hidden; box-shadow:0 6px 18px rgba(0,0,0,.5);}
/* El alto del marco se fija con la propiedad "aspect-ratio" (puesta en línea
   por JS según board.cols/board.rows), NO dejando que lo determine el alto
   intrínseco de la imagen de fondo una vez cargada. Antes de este cambio,
   ".board-frame" no tenía un alto propio hasta que <img class="board-bg">
   terminaba de cargar y aplicaba su "height:auto" — en algunos móviles, al
   100% de zoom, la rejilla (".board-grid", posicionada en absoluto sobre el
   marco) y los iconos de puertas se dibujaban usando un alto de marco
   ligeramente distinto al que finalmente ocupaba la imagen, desplazando
   puertas y demás marcadores respecto a los muros reales. Con un alto
   determinado de antemano por "aspect-ratio", la rejilla y la imagen
   siempre miden exactamente lo mismo, sea cual sea el momento en que la
   imagen termine de cargar o el nivel de zoom aplicado. */
.board-frame img.board-bg{display:block; width:100%; height:100%; object-fit:fill;}
.board-grid{position:absolute; top:0; right:0; bottom:0; left:0; display:grid;}
.board-cell{border:0.5px solid rgba(0,0,0,.08);}

.editor-toolbar{display:flex;gap:6px;flex-wrap:wrap;}
#editorBoardGrid .board-cell{cursor:pointer;}
#editorBoardGrid .board-cell:hover{background:rgba(211,165,63,.35);}
/* En el editor, ningún marcador (ficha, mueble, puerta...) debe robarle
   el clic a la casilla de debajo — si no, "borrar" (y cualquier otro
   modo) no llega nunca a disparar sobre algo que ya está colocado. */
#editorMarkers, #editorMarkers *{pointer-events:none;}
.hero-start-num{
  position:absolute; inset:6%;
  border-radius:50%;
  background:var(--gold-bright);color:var(--ink);border:2px solid var(--ink);
  display:flex;align-items:center;justify-content:center;
  font-family:'Cinzel',serif;font-weight:700;font-size:13px;
}
.board-cell:hover{background:rgba(211,165,63,.18);}
.reachable-cell{position:absolute; background:rgba(90,140,80,.4); border:1px solid rgba(180,220,160,.35); pointer-events:none;}

/* Puertas y conexiones ya NO se posicionan con "position:absolute" +
   "left/top en %" — viven como hijos de una rejilla CSS (ver
   styleEdgeLayerAsGrid/edgeGridArea en app.js) colocados con grid-column/
   grid-row, exactamente el mismo sistema de coordenadas que ya usa
   ".board-grid" para las celdas visibles. Así no hay dos cálculos de
   posición (uno en % a mano, otro de la propia rejilla) que en teoría
   deberían coincidir pero que un navegador concreto podría redondear de
   forma distinta — con 26 columnas pequeñas ese desajuste, aunque sea de
   menos de un píxel por columna, se nota. */
.door-marker{
  pointer-events:none;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.9)) drop-shadow(0 0 6px rgba(211,165,63,.9));
  animation:doorGlow 2s ease-in-out infinite;
}
/* Antes la puerta ABIERTA se quedaba a opacidad .55 ("ya no hace falta
   tocarla, se queda discreta de fondo") — pero eso la hacía casi
   transparente justo cuando más precisión hace falta para tocarla (ahora
   que abrir exige tener el héroe pegado, hay muy pocos píxeles libres
   alrededor del propio token). Cerrada o abierta, se ve siempre a opacidad
   completa; la única diferencia es el brillo animado (acción disponible)
   frente al dibujo fijo de la puerta ya franqueada. */
.door-marker.door-open{opacity:1; animation:none; filter:drop-shadow(0 1px 2px rgba(0,0,0,.7));}
.door-marker.door-closed{opacity:1;}
.door-hit-area{
  pointer-events:auto; cursor:pointer;
}
@keyframes doorGlow{
  0%,100%{filter:drop-shadow(0 1px 2px rgba(0,0,0,.9)) drop-shadow(0 0 4px rgba(211,165,63,.6));}
  50%{filter:drop-shadow(0 1px 2px rgba(0,0,0,.9)) drop-shadow(0 0 10px rgba(211,165,63,1));}
}
.connection-marker{
  animation:none;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.7));
}
.connection-marker.conn-closed{opacity:1; filter:drop-shadow(0 1px 2px rgba(0,0,0,.7));}
.connection-marker.conn-open{opacity:1;}
.door-hit-area.conn-clickable:hover .connection-marker{opacity:1; filter:drop-shadow(0 0 6px rgba(211,165,63,.9));}

.fog-cell{
  position:absolute;
  background:rgba(9,6,4,.9);
  border:0.5px solid rgba(255,255,255,.02);
  pointer-events:none;
}

.sealed-cell{
  position:absolute;
  background:repeating-linear-gradient(45deg, #4a3728, #4a3728 4px, #3a2a1c 4px, #3a2a1c 8px);
  border:1px solid #2b1d10;
  pointer-events:none;
}

.trap-marker{
  position:absolute; transform:translate(-50%,-50%);
  pointer-events:none;
  filter:drop-shadow(0 1px 3px rgba(0,0,0,.8));
}

.furniture-marker{
  position:absolute; transform:translate(-50%,-50%);
  pointer-events:none;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,.6));
}
.furniture-letter{
  position:absolute; top:-6px; right:-6px;
  background:var(--gold-bright); color:var(--ink);
  font-family:'Cinzel',serif; font-weight:700; font-size:11px;
  width:18px; height:18px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  border:1.5px solid var(--ink);
}

/* #tokenLayer y #trapLayer, a diferencia de fogLayer/furnitureLayer/etc,
   necesitan ser ellos mismos un elemento POSICIONADO (position:absolute)
   y no solo un <div> normal con hijos en absoluto. El motivo: desde que
   #doorLayer/#connectionLayer pasaron a usar CSS Grid (ver el comentario
   más arriba sobre "ya NO se posicionan con position:absolute+% a mano"),
   esos dos SÍ son "position:absolute" ellos mismos. En CSS, un elemento
   posicionado siempre se pinta por encima de los elementos NO posicionados
   del mismo contexto de apilamiento, sin importar el orden en el HTML —
   así que #tokenLayer, al no estar posicionado, quedaba POR DEBAJO de
   #doorLayer/#connectionLayer aunque aparezca después en el HTML. Eso no
   solo se veía mal (fichas "debajo" de un icono de puerta) sino que además
   rompía los clics: un toque sobre una ficha que coincidiera con una puerta
   cercana llegaba a la puerta, no a la ficha, y la ficha nunca se
   seleccionaba (de ahí el fallo de "no puedo mover al héroe"). Al marcar
   estas dos capas como posicionadas también, con pointer-events:none en
   la propia capa (para no robarle el clic a las celdas vacías) y
   pointer-events:auto solo en los hijos que sí deben responder al clic
   (.token), el orden de apilamiento vuelve a coincidir con el orden real
   del HTML: fondo → rejilla → niebla/sellado/escaleras/muebles →
   alcanzables → conexiones → puertas → trampas → fichas (arriba del todo,
   como debe ser). */
#tokenLayer, #trapLayer{position:absolute; inset:0; pointer-events:none;}

.token{
  position:absolute; width:7%; padding-top:7%; transform:translate(-50%,-50%);
  border-radius:50%; display:flex; align-items:center; justify-content:center;
  min-width:22px; min-height:22px;
  pointer-events:auto; cursor:pointer;
  /* El TOKEN se sigue pintando por encima de puertas/conexiones (visto
     bien, la ficha tapa el icono de la puerta debajo, como en el tablero
     físico), pero su "caja" de clic es un cuadrado aunque se vea como un
     círculo — las cuatro esquinas de ese cuadrado, invisibles pero
     clicables, son justo donde vive la puerta pegada al héroe, y se
     comían el toque antes de que llegara a la puerta de debajo. Con
     clip-path el propio recorte del click coincide con el círculo visible,
     así que esas esquinas dejan de robarle el toque a lo que hay detrás
     sin cambiar nada del aspecto ni del orden visual. */
  clip-path: circle(50%);
}
.token-inner{position:absolute; inset:6%; border-radius:50%; overflow:hidden; border:2px solid var(--border); box-shadow:0 2px 6px rgba(0,0,0,.6); min-width:18px; min-height:18px;}
.token-inner img{width:100%; height:100%; object-fit:cover;}
.token.selected .token-inner{outline:3px solid var(--gold-bright);}
.token.hurt .token-inner{border-color:var(--blood);}
.token-monster .token-inner{background:var(--steel-dark);}
/* Monstruo con características especiales (mismas miniatura, estadísticas
   distintas — ver monsterOverridesToFields/createMonsterToken): un anillo
   de color propio para que se note a simple vista que no es un monstruo
   normal de su tipo, sin tener que abrir su ficha para comprobarlo. */
.token-monster.variant .token-inner{border-color:var(--gold-bright); border-width:3px; box-shadow:0 0 0 2px rgba(0,0,0,.55), 0 2px 6px rgba(0,0,0,.6);}

.dice-row{display:flex; justify-content:space-between; margin-top:10px; padding-top:8px; border-top:1px solid rgba(107,74,43,.35);}
.dice-block{text-align:center; flex:1;}
.dice-block .label{font-size:11px; color:var(--ink-soft);}
.dice-icons{display:flex; justify-content:center; gap:2px; margin-top:2px; flex-wrap:wrap;}

.inv-list{display:flex; flex-direction:column; gap:6px; margin:10px 0;}
.inv-item{display:flex; align-items:center; gap:8px; background:#f4ead2; border:1px solid var(--border); border-radius:4px; padding:6px 8px;}
.inv-item .info{flex:1; min-width:0;}
.inv-item .info .nm{font-size:13.5px; color:var(--ink); font-weight:600;}
.inv-item .info .meta{font-size:11px; color:var(--ink-soft);}
.inv-item .del{background:none; border:none; color:var(--blood); font-size:15px; padding:2px 6px;}

.custom-toggle{
  background:none; border:none; color:var(--steel-dark); font-size:12.5px;
  text-decoration:underline; padding:0; margin-bottom:8px; display:block;
}
.custom-box{
  background:rgba(55,84,92,.08);
  border:1px solid rgba(55,84,92,.4);
  border-radius:4px;
  padding:10px; margin-bottom:10px;
}
.custom-box .row{display:flex; gap:8px; flex-wrap:wrap; margin-bottom:8px;}
.custom-box .row:last-child{margin-bottom:0;}
.custom-box select, .custom-box input{flex:1; min-width:110px;}

.turn-banner{
  background:var(--steel); color:#f2ead6; border-radius:4px; padding:8px 12px; font-size:14px;
  display:flex; justify-content:space-between; align-items:center; gap:8px; flex-wrap:wrap;
}

.log-panel{max-height:160px; overflow-y:auto; font-size:12.5px; color:var(--ink-soft); background:rgba(43,29,16,.06); border:1px solid rgba(107,74,43,.3); border-radius:4px; padding:8px 10px;}
.log-panel div{margin-bottom:4px;}

.room-code{
  font-family:'Cinzel', serif; font-size:22px; letter-spacing:.15em; color:var(--gold-bright);
  background:var(--stone); border-radius:4px; padding:6px 14px; display:inline-block;
}

.combat-result{font-size:13px; margin-top:6px; color:var(--ink-soft);}

.dice-tray-row{display:flex; gap:8px; flex-wrap:wrap;}
.die{animation:dicePop .35s ease-out; filter:drop-shadow(0 3px 4px rgba(0,0,0,.5));}
@keyframes dicePop{
  0%{transform:scale(.3) rotate(-18deg); opacity:0;}
  100%{transform:scale(1) rotate(0); opacity:1;}
}

/* ---------- popup flotante de dados ---------- */
.dice-modal-overlay{
  position:fixed; top:0; right:0; bottom:0; left:0; z-index:80;
  background:rgba(10,7,4,.78);
  display:flex; align-items:center; justify-content:center;
  padding:20px;
}
.dice-modal-card{
  background:linear-gradient(180deg, var(--parchment), var(--parchment-dark));
  border:1px solid var(--border);
  border-radius:8px;
  padding:24px 26px;
  max-width:420px; width:100%;
  text-align:center;
  box-shadow:0 20px 60px rgba(0,0,0,.7);
  animation:modalPop .25s ease-out;
}
@keyframes modalPop{
  0%{transform:scale(.85); opacity:0;}
  100%{transform:scale(1); opacity:1;}
}
.dice-modal-card h3{margin:0 0 14px; font-size:18px; color:var(--ink);}
.dice-modal-label{margin:0 0 8px; font-size:12.5px; color:var(--ink-soft);}
.dice-modal-row{display:flex; gap:8px; justify-content:center; flex-wrap:wrap; margin-bottom:4px;}
.dice-modal-row .die{width:44px; height:44px;}
.dice-modal-total{margin:12px 0 4px; font-size:15px; color:var(--ink);}
.dice-modal-explain{margin:8px 0 14px; font-size:12px; color:var(--ink-soft); line-height:1.45;}

.footer-note{max-width:960px; margin:26px auto 0; text-align:center; color:#8a7a56; font-size:12px; line-height:1.5; padding:0 16px;}

@media (max-width:480px){
  .dice-modal-card{padding:16px 14px; max-width:94vw;}
  .dice-modal-row .die{width:36px; height:36px;}
  .dice-modal-card h3{font-size:15px;}
}

@media (max-width:600px){
  .class-picker{grid-template-columns:1fr;}
}
