File size: 12,426 Bytes
22a027e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | /* Self-contained layout for the gr.Server frontend.
game.css styles all render.py internals (battle-frame, sprites, meters,
character-sheet, overlays' inner HTML, keyframes) and provides :root tokens.
This file owns ONLY the custom shell: page chrome, setup screens, the
gameplay shell, the action decks, and overlay wrappers — using tw-* class
names so the Gradio-tuned rules in game.css never apply to them. */
* { box-sizing: border-box; }
[hidden] { display: none !important; }
body {
margin: 0;
background: radial-gradient(1200px 600px at 50% -10%, #161228 0%, #0a0910 60%);
color: var(--ink, #ddd9e8);
font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
}
#app { max-width: 1500px; margin: 0 auto; padding: .7rem 1.1rem 2.2rem; }
/* ---------- title ---------- */
.tw-title {
max-width: 560px; margin: 7vh auto; text-align: center; padding: 2.6rem 2.2rem;
border: 1px solid #3e3553; background: #12101aee; border-radius: 16px;
box-shadow: 0 0 50px #00000080, inset 0 0 30px #08060e;
}
.tw-title p { color: #c7bee0; line-height: 1.5; }
.tw-hint { font-size: .74rem; color: #8a83a3; margin-top: 1.2rem; }
.tw-hint code { color: #b8a6db; }
/* ---------- buttons ---------- */
.tw-primary {
padding: .7rem 1.8rem; font-size: 1rem; font-weight: 700; color: #1a130a;
background: linear-gradient(180deg, #e0c084, #c79a4f); border: 0; border-radius: 10px;
cursor: pointer; letter-spacing: .03em; box-shadow: 0 6px 18px #00000066;
}
.tw-primary:hover:not(:disabled) { filter: brightness(1.08); }
.tw-primary:disabled { opacity: .45; cursor: not-allowed; }
.tw-secondary {
padding: .6rem 1.3rem; font-weight: 600; color: #d7cdf0; background: #1a1626;
border: 1px solid #3e3553; border-radius: 10px; cursor: pointer;
}
.tw-secondary:hover { border-color: var(--violet, #8669c4); }
/* ---------- setup panels ---------- */
.tw-panel { max-width: 1180px; margin: 2vh auto; padding: 1.4rem 1.6rem;
border: 1px solid #3e3553; background: #12101aee; border-radius: 14px; }
.tw-setup-actions { display: flex; gap: .8rem; justify-content: center; margin-top: 1.2rem; flex-wrap: wrap; }
.tw-alloc-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: .8rem; margin-top: 1.2rem; }
.tw-alloc-grid .stat-card { text-align: center; padding: .8rem .5rem;
background: var(--card-bg, #12101a); border: 1px solid var(--card-border, #30283f); border-radius: 10px; }
.tw-alloc-grid .stat-card strong { display: block; margin-bottom: .5rem; color: #e2d9f3; }
.stat-stepper { display: flex; align-items: center; justify-content: center; gap: .6rem; }
.stat-stepper button { width: 32px; height: 32px; font-size: 1.2rem; font-weight: 700;
background: #1a1626; color: #e2d9f3; border: 1px solid #3e3553; border-radius: 8px; cursor: pointer; }
.stat-stepper button:hover:not(:disabled) { border-color: var(--violet, #8669c4); }
.stat-stepper button:disabled { opacity: .35; cursor: not-allowed; }
.stat-value { font-size: clamp(.95rem, 2.5vw, 1.3rem); font-weight: 700; min-width: 2ch; }
.alloc-remaining { grid-column: 1 / -1; text-align: center; color: #b8a6db; margin-top: .4rem; }
.alloc-remaining b { color: var(--gold, #e0c084); }
.tw-diff-row { display: flex; gap: .8rem; justify-content: center; margin: 1.2rem 0; flex-wrap: wrap; }
.diff-btn { padding: .6rem 1.2rem; background: var(--card-bg, #171522); color: #cfc6e6;
border: 1px solid var(--card-border, #30283f); border-radius: 10px; cursor: pointer; }
.diff-btn.selected { border-color: #c79a4f; color: #f0e3c4; background: #1f1830; }
.diff-btn:disabled { opacity: .6; cursor: default; }
.tw-starter-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: .55rem; margin-top: 1rem; }
.starter-card { white-space: pre-line; text-align: left; padding: .55rem .6rem; min-height: 84px;
background: var(--card-bg, #12101a); color: #eef3fb; border: 1px solid var(--card-border, #30283f);
border-radius: 8px; cursor: pointer; font-size: .8rem; line-height: 1.18; }
.starter-card:hover { border-color: var(--violet, #8669c4); background: #191522; }
@media (max-width: 900px) { .tw-starter-grid { grid-template-columns: repeat(2, 1fr); } .tw-alloc-grid { grid-template-columns: repeat(2, 1fr); } }
/* ---------- gameplay shell: sidebar LEFT, main right (matches original) ---------- */
.tw-shell { display: flex; align-items: flex-start; gap: 1rem; }
.tw-sidebar { flex: 0 0 300px; max-width: 320px; min-width: 270px;
position: sticky; top: .5rem; max-height: calc(100vh - 1rem); overflow-y: auto;
background: var(--card-bg, #12101a); border: 1px solid #3e3553; border-radius: 12px; padding: .5rem .7rem; }
.tw-sidebar-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.tw-sidebar-head h2 { margin: 0; font-size: clamp(.85rem, 2.5vw, 1.1rem); }
.tw-main { flex: 1; min-width: 0; }
.tw-toggle { padding: .25rem .6rem; font-size: .78rem; color: #cfc6e6; background: #1a1626;
border: 1px solid #3e3553; border-radius: 7px; cursor: pointer; }
.tw-toggle:hover { border-color: var(--violet, #8669c4); }
#show-sidebar { margin-bottom: .5rem; }
/* stage = positioning context for the action decks (mirrors original .stage-stack) */
.tw-stage { position: relative;
width: min(100%, 1250px, calc((100dvh - 300px) * 16 / 9)); margin: 0 auto;
padding-bottom: clamp(3.8rem, 7vh, 4.8rem); }
#stage-narration { position: absolute; z-index: 16; top: 8%; left: 18%; width: 50%; pointer-events: none; }
.tw-log { margin: .5rem 0; min-height: 2rem; padding: .5rem .8rem;
background: #111019; border-left: 3px solid var(--violet, #8669c4); color: #f1e4b9; font-size: clamp(.72rem, 1.8vw, .85rem); }
.tw-fulllog { margin-top: .4rem; }
.tw-fulllog summary { cursor: pointer; color: #b8a6db; font-size: clamp(.72rem, 1.8vw, .85rem); }
/* ---------- action decks (overlay the bottom of the frame, original look) ---------- */
.tw-deck { position: absolute; bottom: 0; z-index: 8; padding: .55rem;
border: 1px solid var(--card-border, #30283f); background: var(--deck-bg, #12101ae8);
box-shadow: 0 10px 28px #0009, inset 0 1px #8490a31a; }
.tw-deck-basic { left: 2%; width: 34%; height: 72px;
display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .45rem; }
.tw-deck-right { right: 2%; width: min(59%, 720px); }
.tw-deck-right.tw-deck-open { min-height: clamp(184px, 25vh, 224px); }
.tw-deck-toggles { display: grid; grid-template-columns: 1fr 1fr; gap: .45rem; height: 72px; }
.tw-deck-title { color: #d9c7ff; font-size: clamp(.6rem, 1.2vw, .78rem); font-weight: 800; letter-spacing: .1em;
text-transform: uppercase; margin-bottom: .35rem; }
.tw-deck-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .4rem; }
.tw-deck .tw-back { margin-top: .4rem; width: 100%; text-align: center; min-height: 2rem; }
.tw-empty { color: var(--card-muted, #aaa2bd); font-size: .85rem; padding: .4rem; }
.tw-thinking { right: 2%; width: min(59%, 720px); padding: .7rem; color: #d9c7ff; text-align: center; }
.tw-thinking p { margin: .3rem 0 0; font-size: .8rem; color: var(--card-muted, #aaa2bd); }
.tw-narrating .tw-card { opacity: 0.42; cursor: not-allowed !important; pointer-events: none; }
/* action cards — reproduce original .action-card look */
.tw-card { min-height: 0; min-width: 0; padding: .42rem .55rem;
white-space: pre-line; text-align: left; font-weight: 600; line-height: 1.14;
font-size: clamp(.72rem, .82vw, .88rem); color: #eef3fb;
background: var(--card-bg, #12101a); border: 1px solid var(--card-border, #30283f);
border-radius: 0; cursor: pointer; }
.tw-deck-basic .tw-card { height: 100%; }
.tw-card:hover:not(:disabled) { background: #191522; border-color: var(--violet, #8669c4); }
.tw-card:disabled { color: #746d80; background: #0f0d15cc; border-color: #292333; cursor: not-allowed; }
/* ---------- overlays (victory / evolution / defeat / ascension / preview) ---------- */
.tw-overlay { position: absolute; inset: 0; z-index: 20; display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: .7rem; padding: 1rem;
background: #07060bd9; }
.tw-overlay-card { max-width: 92%; max-height: 90%; overflow: auto; padding: 1rem 1.2rem;
background: var(--card-bg, #12101a); border: 1px solid #4a3f63; border-radius: 12px;
box-shadow: 0 12px 40px #000a; text-align: center; }
.tw-overlay .reward-actions, .tw-overlay .level-skill-actions, .tw-overlay .replacement-actions {
display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: .5rem; margin-top: .6rem; }
.tw-overlay .reward-footer, .tw-overlay .heal-actions, .tw-overlay .preview-actions {
display: flex; gap: .6rem; align-items: center; justify-content: center; margin-top: .7rem; flex-wrap: wrap; }
.tw-overlay .reward-count { color: #b8a6db; font-size: .85rem; }
.tw-card.primary { background: linear-gradient(180deg, #e0c084, #c79a4f); color: #1a130a; border: 0; font-weight: 700; }
.tw-card.primary:hover:not(:disabled) { filter: brightness(1.08); }
.reward-icon { width: 26px; height: 26px; vertical-align: middle; margin-right: .4rem; image-rendering: pixelated; }
/* ---------- tutorial overlay ---------- */
.tw-tutorial { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center;
background: #06050aee; padding: 1rem; }
.tw-tutorial-card { width: min(720px, 100%); max-height: 88vh; display: flex; flex-direction: column;
background: #12101a; border: 1px solid #4a3f63; border-radius: 14px;
box-shadow: 0 16px 50px #000b; overflow: hidden; }
#tutorial-content { flex: 1; overflow-y: auto; padding: 1.4rem 1.6rem; }
.tw-tutorial-nav { flex: 0 0 auto; display: flex; gap: .6rem; align-items: center; justify-content: center;
padding: .7rem 1rem; border-top: 1px solid #2e2840; background: #0e0c17; }
.tw-tutorial-nav .tw-card { min-width: 90px; text-align: center; padding: .45rem .8rem; }
.tw-tutorial-nav .tw-card.primary { background: linear-gradient(180deg,#e0c084,#c79a4f); color:#1a130a; border:0; font-weight:700; }
.tw-tutorial-nav .tw-card:disabled { opacity: .35; cursor: not-allowed; }
/* heal preview line in evolution-healing overlay */
.tw-heal-preview { margin: .5rem 0 1rem; font-size: 1rem; color: #d9c7ff; }
.tw-heal-preview b { color: #e0c084; }
.tw-heal-gain { color: #9fd7ba; font-size: .9rem; }
/* How to Play button spacing on title screen */
.tw-title .tw-secondary { display: block; margin: .6rem auto 0; }
/* ---------- loading overlay (no backdrop-filter — keeps screenshots working) ---------- */
.tw-loading { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center;
background: #06050aee; }
.tw-loading-card { display: flex; flex-direction: column; align-items: center; gap: 1rem;
padding: 2rem 2.5rem; border: 1px solid #3e3553; background: #12101a; border-radius: 14px; }
.tw-loading-card span { color: #d9c7ff; letter-spacing: .04em; }
.tw-rune { width: 42px; height: 42px; border: 3px solid #3e3553; border-top-color: #c79a4f;
border-radius: 50%; animation: tw-spin .9s linear infinite; }
.tw-rune-sm { width: 20px; height: 20px; border-width: 2px; margin: 0 auto .4rem; }
@keyframes tw-spin { to { transform: rotate(360deg); } }
/* ---------- bgm mute button (fixed top-left) ---------- */
.tw-mute-btn {
position: fixed; top: .6rem; left: .6rem; z-index: 500;
padding: .25rem .5rem; font-size: .85rem; line-height: 1;
color: #d9c7ff; background: #1a162699; border: 1px solid #3e3553;
border-radius: 7px; cursor: pointer;
}
.tw-mute-btn:hover { border-color: var(--violet, #8669c4); }
.tw-mute-off { opacity: .45; text-decoration: line-through; }
@media (max-width: 900px) {
.tw-shell { flex-direction: column; }
.tw-sidebar { flex: none; width: 100%; max-width: none; min-width: 0; position: static; max-height: none; }
}
@media (max-width: 600px) {
#app { padding: .4rem .5rem 1.2rem; }
.tw-title { margin: 2vh auto; padding: 1.4rem 1rem; }
.tw-panel { padding: .8rem .9rem; }
.tw-stage { padding-bottom: clamp(2.4rem, 7vh, 3.8rem); }
.tw-deck-right.tw-deck-open { min-height: clamp(110px, 25vh, 184px); }
.tw-starter-grid { grid-template-columns: repeat(2, 1fr); }
.tw-alloc-grid { grid-template-columns: repeat(2, 1fr); }
}
|