Leskys_Shop / ui /style.css
siigrid's picture
first push
9a097d5
Raw
History Blame Contribute Delete
18.1 kB
/* Lesky's Shop — estilos de escena (capas sobre un escenario 16:9). */
/* Gradio centra y limita el ancho por defecto: usar pantalla completa. */
.gradio-container {
max-width: 100% !important;
width: 100% !important;
padding: 0 !important;
}
/* ---- Escenario ----
SIEMPRE 16:9 (igual que el calibrador). El ancho manda (min entre el contenedor
y el 16:9 de 82vh) y la altura se deriva por aspect-ratio. Así la imagen del
tablero (object-fit) llena el stage sin bandas y las capas/rejilla en % cuadran
con lo pintado en CUALQUIER tamaño de ventana. (Antes: height fija 82vh ->
en ventanas estrechas el stage salía más alto que 16:9 y la rejilla bailaba.) */
.stage {
position: relative !important;
/* Caja 16:9. width manda (min entre contenedor y el 16:9 de 82vh); la altura
sale por aspect-ratio. flex:0 0 auto evita que el flex de Gradio estire la
caja y la deje "chata". --sw también disponible por si hace falta calc. */
--sw: min(100vw, calc(82vh * 16 / 9));
width: min(100%, calc(82vh * 16 / 9)) !important;
aspect-ratio: 16 / 9 !important;
height: auto !important;
flex: 0 0 auto !important;
align-self: center !important;
margin: 0 auto;
overflow: hidden;
}
/* Neutralizar los wrappers que Gradio mete dentro de .stage (.block tiene
position:relative + fondo + padding). Así .stage es el único ancestro
posicionado y las capas absolutas se miden respecto a él. */
.stage .block,
.stage .form,
.stage .html-container,
.stage > .column,
.stage > .row {
position: static !important;
background: transparent !important;
border: none !important;
box-shadow: none !important;
padding: 0 !important;
margin: 0 !important;
min-width: 0 !important;
overflow: visible !important;
}
/* Capas: fondo / personaje / marco, apiladas sobre el escenario. */
.stage .layer {
position: absolute !important;
inset: 0;
width: 100%;
height: 100%;
object-fit: contain;
pointer-events: none; /* no roban clicks */
}
/* Personaje: más pequeño y anclado abajo-centro, para quedar detrás de la mesa
delantera (.layer.front, que va después en el DOM y lo tapa por abajo). */
.stage .layer.sprite {
inset: auto;
left: 50%;
bottom: 1%;
transform: translateX(-50%);
width: 46%;
height: 82%;
object-fit: contain;
object-position: center bottom;
}
/* Flash de revelación (monster_reveal): destello blanco que cubre el stage una vez. */
.stage .flash {
position: absolute !important;
inset: 0;
z-index: 20;
background: #fff;
pointer-events: none;
animation: revealflash 0.65s ease-out forwards;
}
@keyframes revealflash {
0% { opacity: 0; }
12% { opacity: 0.96; }
100% { opacity: 0; }
}
/* Pantalla loading: gris con spinner mientras el LLM calcula el saludo. */
.stage.loading-stage {
background: #2b2b2b;
display: flex;
align-items: center;
justify-content: center;
}
.loading-box { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.loading-spinner {
width: 46px; height: 46px;
border: 5px solid rgba(255, 255, 255, 0.18);
border-top-color: #e8e8e8;
border-radius: 50%;
animation: lspin 0.9s linear infinite;
}
@keyframes lspin { to { transform: rotate(360deg); } }
.loading-text { color: #cfcfcf; font-size: 1.15rem; letter-spacing: 2px; }
/* Brazo del jugador entrando al tablero. Encima de la rejilla (z>5) pero sin
robar clicks (.layer ya trae pointer-events:none). Anclado arriba, reaching in. */
.stage .layer.hand {
inset: auto;
left: 50%;
top: 0;
transform: translateX(-50%);
width: 100%;
height: 100%;
object-fit: contain;
object-position: center top;
z-index: 6;
}
/* Texto del LLM dentro del pergamino de CHAT.PNG (anclado abajo-derecha). */
/* Texto del LLM dentro del papel del pergamino (CHAT.PNG, lado derecho).
Zona estrecha -> fuente pequeña + scroll vertical. Ajustar % a ojo. */
.stage .chat-text {
position: absolute;
left: 78%;
top: 33%;
width: 14.5%;
height: 38%;
overflow-y: auto;
padding: 2px 6px;
color: #2e2113;
font-size: 0.7rem;
line-height: 1.25;
text-align: left;
z-index: 7;
}
/* Listas/briefing compactos dentro del pergamino. Forzar color OSCURO en TODOS
los descendientes: Gradio (tema oscuro) pinta <li>/<p> casi blancos por defecto. */
.stage .chat-text,
.stage .chat-text li,
.stage .chat-text p,
.stage .chat-text span,
.stage .chat-text i,
.stage .chat-text em,
.stage .chat-text ul { color: #2e2113 !important; }
.stage .chat-text b,
.stage .chat-text strong { color: #4a2e10 !important; }
.stage .chat-text ul { margin: 3px 0 5px 14px; padding: 0; }
.stage .chat-text li { margin-bottom: 2px; }
/* monster_reveal: TODAS las letras negro puro (máx. contraste) incl. divs/b. */
.stage .chat-text.reveal-text,
.stage .chat-text.reveal-text * { color: #000 !important; }
/* Barra de scroll fina y discreta dentro del pergamino. */
.stage .chat-text::-webkit-scrollbar { width: 5px; }
.stage .chat-text::-webkit-scrollbar-thumb {
background: rgba(70, 50, 25, 0.5); border-radius: 3px;
}
/* Bloque de entrada (nombre / chat) sobre la tabla de madera de CHAT.PNG. */
.stage .wood-input {
position: absolute !important;
left: 76.5%;
top: 79.5%;
width: 20%;
z-index: 8;
gap: 3px !important;
flex-direction: column !important; /* 2 filas: textbox arriba, botón abajo */
align-items: stretch !important;
}
.stage .wood-input > * { width: 100% !important; }
.stage .wood-input button { width: 100% !important; flex: 0 0 auto !important; }
/* Forzar ancho 100% por toda la cadena interna de Gradio (colapsa a 0 si no). */
.stage .wood-input .block,
.stage .wood-input .form,
.stage .wood-input .container,
.stage .wood-input .input-container,
.stage .wood-input .scroll-hide {
width: 100% !important;
min-width: 0 !important;
}
/* Gradio deja el .container interno en display:none y los wrappers a alto 0. */
.stage .wood-input .container { display: block !important; }
.stage .wood-input .form,
.stage .wood-input .input-container,
.stage .wood-input .scroll-hide {
height: auto !important;
min-height: 1.9rem !important;
overflow: visible !important;
}
.stage .wood-input label { display: none !important; } /* sin etiqueta, ahorra alto */
.stage .wood-input input,
.stage .wood-input textarea {
width: 100% !important;
/* Crema translúcido sobre la madera (se mimetiza) + texto OSCURO legible. */
background: rgba(232, 218, 188, 0.45) !important;
border: 1px solid rgba(70, 50, 25, 0.5) !important;
color: #2e2113 !important;
font-size: 0.9rem !important;
text-align: center;
min-height: 2.1rem !important; /* evita que Gradio lo colapse a 0 */
height: 2.1rem !important;
padding: 3px 6px !important;
}
.stage .wood-input input::placeholder,
.stage .wood-input textarea::placeholder { color: rgba(60, 42, 22, 0.6) !important; }
.stage .wood-input button { min-height: 1.8rem !important; padding: 2px 8px !important; }
/* GIF "tap to start" animado, centrado abajo sobre la portada. */
.stage .tap-gif {
position: absolute;
bottom: 6%;
left: 50%;
transform: translateX(-50%);
width: 82%;
pointer-events: none;
z-index: 6;
}
/* Host de la música (img oculta que dispara __setMusic): sin hueco en el layout.
La img igual carga y su onload se ejecuta aunque el contenedor esté display:none. */
.music-host { display: none !important; }
/* Botón "tap to start" invisible cubriendo toda la portada.
OJO: gr.Button pone elem_classes en el <button> mismo -> .tap ES el botón. */
.stage .tap {
position: absolute !important;
inset: 0;
z-index: 10;
width: 100% !important;
height: 100% !important;
min-height: 0 !important;
background: transparent !important;
border: none !important;
box-shadow: none !important;
}
/* Rejilla NxN de botones sobre la rejilla pintada del TABLERO. La geometría
(left/top/width/HEIGHT/gap) se INYECTA por rival desde ui/grid_layout.py
(ver board.py -> grid_style_css). Aquí solo el layout: caja flex que las
celdas rellenan, así calibras 4 números por tablero. Defaults = Lesky. */
.stage .grid3 {
position: absolute !important;
left: 37.9%;
top: 29.1%;
width: 21%;
/* SIN height: las celdas son cuadradas (aspect-ratio:1) y el alto sale solo.
Imponer height las deformaba (chatas) cuando el stage no era 16:9 exacto. */
display: flex;
flex-direction: column;
gap: 6px;
z-index: 5;
}
.grid3 .grid-row { display: flex; gap: 6px; min-height: 0 !important; }
/* .cell ES el <button> (elem_classes va en el botón). Botones INVISIBLES: sin
fondo ni borde; la ficha la pinta una moneda png (coin-player / coin-opp).
Sin alto fijo: la celda rellena la caja (flex), el encaje lo da grid_layout. */
.grid3 .cell {
flex: 1 1 0;
min-width: 0;
min-height: 0;
aspect-ratio: 1 / 1; /* casilla SIEMPRE cuadrada (alto = ancho), no chata */
/* OJO: usar background-color (NO el shorthand background) para no borrar la
background-image de la moneda que inyecta board.py. */
background-color: transparent !important;
background-repeat: no-repeat !important;
background-position: center !important;
background-size: 130% 130% !important; /* moneda algo mayor que la casilla (PNG con margen) */
border: none !important;
box-shadow: none !important;
color: #fff !important;
font-size: 1rem;
font-weight: 700;
border-radius: 6px;
text-shadow: 0 1px 3px #000, 0 0 2px #000;
}
/* Casilla vacía y jugable: leve realce solo al pasar el ratón. */
.grid3 .cell:not(.coin-player):not(.coin-opp):not(:disabled):hover {
background-color: rgba(255, 255, 255, 0.18) !important;
}
/* Casillas con ficha: la moneda (url inyectada en board.py) ya va de fondo. */
.grid3 .cell.coin-player, .grid3 .cell.coin-opp { opacity: 1 !important; }
.grid3 .cell:disabled { opacity: 1; cursor: default; }
/* (La geometría de la rejilla por rival —incluido el monstruo 4x4— se inyecta
desde ui/grid_layout.py, no se fija aquí.) */
/* Crónica / log lateral. */
.chronicle { font-size: 0.85rem; opacity: 0.9; }
/* Briefing (shop) and scroll panel (board sidebar). */
.briefing, .scroll-panel {
background: rgba(0,0,0,0.35);
border-left: 3px solid #c8a84b;
border-radius: 6px;
padding: 0.5rem 0.75rem;
margin-bottom: 0.6rem;
font-size: 0.85rem;
}
.briefing ul, .scroll-panel ul { margin: 0.3rem 0 0 1rem; padding: 0; }
.briefing p { margin: 0.3rem 0 0; }
/* Chat panel */
.chat-row { margin-top: 0.75rem; border-top: 1px solid rgba(200,168,75,0.3); padding-top: 0.5rem; }
.chat-log {
min-height: 80px;
max-height: 160px;
overflow-y: auto;
background: rgba(0,0,0,0.3);
border-radius: 6px;
padding: 0.4rem 0.6rem;
font-size: 0.83rem;
}
.chat-msg { margin-bottom: 0.3rem; line-height: 1.4; }
.chat-player { color: #f87171; }
.chat-lesky { color: #86efac; }
.chat-empty { opacity: 0.4; font-style: italic; }
/* Streaming typing box */
.lesky-typing textarea {
color: #86efac !important;
background: rgba(0,0,0,0.3) !important;
border: 1px solid rgba(134,239,172,0.3) !important;
font-size: 0.85rem;
resize: none;
}
/* ---- Board: panel de info a la izquierda (estado + leyes + misión) ---- */
/* Panel de info/leyes sobre un TABLÓN de madera (NORMA-CORTADO, url inline en
board.py). El tablón se estira a la caja (100% 100%); el marco tallado queda en
el borde. Texto OSCURO para leerse sobre la madera clara; padding generoso para
no pisar el marco. */
.stage .board-info {
position: absolute;
left: 1.5%;
top: 3%;
width: 29%;
max-height: 74%;
overflow-y: auto;
z-index: 7;
background-repeat: no-repeat;
background-size: 100% 100%;
padding: 26px 30px 30px;
font-size: 0.74rem;
line-height: 1.3;
}
/* TODO el texto del tablón en NEGRO (incl. negritas y descendientes). */
.stage .board-info,
.stage .board-info * { color: #000 !important; }
.stage .board-info ul { margin: 2px 0 4px 14px; padding: 0; }
.stage .board-info li { margin-bottom: 2px; }
.stage .board-info .bi-map { margin-bottom: 3px; }
.stage .board-info::-webkit-scrollbar { width: 5px; }
.stage .board-info::-webkit-scrollbar-thumb { background: rgba(70,50,25,0.5); border-radius: 3px; }
/* round_over: controles (legislar/acusar/siguiente) en panel overlay arriba-izq.
round-panel ES un gr.Column -> position:absolute !important para ganar al
neutralizador `.stage > .column { position:static }` (igual que wood-input). */
.stage .round-panel {
position: absolute !important;
left: 1.5%;
top: 3%;
width: 31%;
/* Sliding window: alto máx = casi el del stage; el resto SCROLLEA dentro del panel.
overflow-y y max-height con !important: el neutralizador .stage>.column pone
overflow:visible !important y rompía el scroll. vh (no %) resuelve seguro. */
max-height: 80vh !important;
overflow-y: auto !important;
overflow-x: hidden !important;
z-index: 8;
flex-direction: column !important;
gap: 6px !important;
align-items: stretch !important;
background: rgba(10, 8, 4, 0.78) !important; /* !important: gana al neutralizador de .stage>.column */
border-radius: 10px;
padding: 12px 14px;
}
/* flex:0 0 auto -> los hijos NO se encogen (mantienen su tamaño); el exceso
scrollea en el panel en vez de deformar los botones. */
.stage .round-panel > * { width: 100% !important; flex: 0 0 auto !important; }
.stage .round-panel .rp-clever { color: #f0e6d0; font-size: 0.78rem; margin-bottom: 2px; }
.stage .round-panel .rp-title { color: #bfe6a8; font-weight: 700; font-size: 0.82rem; }
.stage .round-panel .rp-hint { color: #c8b89a; font-size: 0.72rem; margin-top: -2px; margin-bottom: 2px; }
.stage .round-panel .rp-lie-catches { color: #a8e6a0; font-size: 0.74rem; margin-top: 1px; margin-bottom: 3px; font-style: italic; }
.stage .round-panel .rp-accuse-result {
background: rgba(0,0,0,0.55); border: 1px solid #7a6a4a;
border-radius: 6px; padding: 6px 8px;
color: #f0e6d0; font-size: 0.76rem; white-space: pre-wrap; line-height: 1.4;
}
.stage .round-panel button {
width: 100% !important; min-height: 0 !important;
font-size: 0.7rem !important; padding: 5px 7px !important;
}
/* Plegable "Ideas & limits" compacto: encoge el bloque de límites (tiene
font-size inline 0.9rem -> hace falta !important) y sus listas. */
.stage .round-panel .gap > div[style*="border-left"],
.stage .round-panel div[style*="border-left"] {
font-size: 0.6rem !important;
line-height: 1.28 !important;
padding: 0.45rem 0.55rem !important;
}
.stage .round-panel div[style*="border-left"] ul { margin: 0.25rem 0 0 1rem !important; }
.stage .round-panel div[style*="border-left"] li { margin-bottom: 1px !important; }
/* Botones de sugerencia (dentro del plegable) aún más pequeños. */
.stage .round-panel .accordion button,
.stage .round-panel [class*="accordion"] button { font-size: 0.64rem !important; padding: 4px 6px !important; }
/* Forzar ancho por la cadena interna de Gradio (colapsa a 0 si no), como wood-input. */
.stage .round-panel .block,
.stage .round-panel .form,
.stage .round-panel .container,
.stage .round-panel .input-container,
.stage .round-panel .scroll-hide,
.stage .round-panel .wrap { width: 100% !important; min-width: 0 !important; }
.stage .round-panel .container { display: block !important; }
.stage .round-panel input,
.stage .round-panel textarea {
background: rgba(232, 218, 188, 0.92) !important;
color: #2e2113 !important;
border: 1px solid rgba(70, 50, 25, 0.5) !important;
font-size: 0.8rem !important;
}
.stage .round-panel::-webkit-scrollbar { width: 5px; }
.stage .round-panel::-webkit-scrollbar-thumb { background: rgba(70,50,25,0.5); border-radius: 3px; }
/* Cleverness Shop: overlay izquierda-abajo. board-shop ES un gr.Column (la clase
va en la columna), así que necesita position:absolute !important para ganar al
neutralizador `.stage > .column { position:static }` (igual que .wood-input). */
.stage .board-shop {
position: absolute !important;
left: 2%;
bottom: 3%;
width: 22%;
z-index: 8;
flex-direction: column !important;
gap: 4px !important;
align-items: stretch !important;
background: rgba(10, 8, 4, 0.6);
border-left: 3px solid #6fae5a;
border-radius: 6px;
padding: 6px 8px;
}
.stage .board-shop > * { width: 100% !important; }
.stage .board-shop .shop-title { color: #bfe6a8; font-weight: 700; font-size: 0.72rem; margin-bottom: 2px; }
.stage .board-shop .shop-hint { color: #f0e6d0; font-size: 0.66rem; line-height: 1.25; }
.stage .board-shop button {
width: 100% !important; flex: 0 0 auto !important;
font-size: 0.7rem !important; min-height: 0 !important; padding: 4px 6px !important;
}
/* Forzar ancho por la cadena interna de Gradio (colapsa a 0 si no), como wood-input. */
.stage .board-shop .block,
.stage .board-shop .form,
.stage .board-shop .container,
.stage .board-shop .input-container,
.stage .board-shop .scroll-hide,
.stage .board-shop .wrap { width: 100% !important; min-width: 0 !important; }
.stage .board-shop .container { display: block !important; }
/* Chat log DENTRO del pergamino: hereda .chat-text (posición+scroll) y anula la
caja oscura del chat de abajo antiguo. */
.stage .chat-text.chat-log {
background: transparent !important;
min-height: 0 !important;
max-height: none !important;
padding: 2px 6px !important;
border-radius: 0 !important;
}
.stage .chat-text .chat-msg { margin-bottom: 4px; line-height: 1.3; }
.stage .chat-text .chat-player { color: #8a2b2b !important; }
.stage .chat-text .chat-lesky { color: #2f6b34 !important; }
.stage .chat-text .chat-empty { color: #6b5a3a !important; font-style: italic; opacity: 0.8; }