style.css (13690B)
1 /* semif-api web UI — no framework, so the layout is written out. 2 System fonts only: this page is served by the API itself and must work 3 with no network. */ 4 5 :root { 6 --bg: #10131a; 7 --bg-panel: #171b24; 8 --bg-raised: #1e232e; 9 --line: #2a3140; 10 --fg: #dbe1ea; 11 --fg-dim: #8b95a7; 12 --accent: #69c0ff; 13 --win: #56d364; 14 --warn: #e3a008; 15 --err: #f85149; 16 --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; 17 } 18 19 * { box-sizing: border-box; } 20 21 /* JS hides panels with the hidden attribute. An author-level `display` on the 22 same element (below: .panel) beats the UA sheet's [hidden] rule no matter how 23 specific it is, so hide it here or both tabs render at once. */ 24 [hidden] { display: none !important; } 25 26 body { 27 margin: 0; 28 background: var(--bg); 29 color: var(--fg); 30 font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; 31 } 32 33 code, .mono, pre { font-family: var(--mono); font-size: 0.9em; } 34 35 header { 36 display: flex; 37 flex-wrap: wrap; 38 gap: 1rem; 39 align-items: flex-end; 40 justify-content: space-between; 41 padding: 1.25rem 1.5rem 1rem; 42 border-bottom: 1px solid var(--line); 43 } 44 45 h1 { margin: 0; font-size: 1.15rem; letter-spacing: 0.02em; } 46 .tagline { margin: 0.15rem 0 0; color: var(--fg-dim); font-size: 0.85rem; } 47 48 .health { 49 display: flex; 50 align-items: center; 51 flex-wrap: wrap; 52 gap: 0.5rem; 53 font-size: 0.8rem; 54 color: var(--fg-dim); 55 max-width: 52rem; 56 } 57 .model-picker { 58 width: auto; 59 max-width: 24rem; 60 padding: 0.2rem 0.4rem; 61 font-size: 0.8rem; 62 } 63 .model-note { color: var(--fg-dim); font-size: 0.75rem; } 64 .model-note.is-error { color: var(--err); } 65 .model-note.is-warn { color: var(--warn); } 66 .warn-text { color: var(--warn); } 67 .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--fg-dim); flex: none; } 68 .dot.up { background: var(--win); } 69 .dot.down { background: var(--err); } 70 .dot.pending { background: var(--warn); animation: pulse 1.2s infinite; } 71 @keyframes pulse { 50% { opacity: 0.25; } } 72 73 .tabs { display: flex; gap: 0.25rem; padding: 0.75rem 1.5rem 0; } 74 .tab { 75 background: none; 76 border: 1px solid transparent; 77 border-bottom-color: var(--line); 78 color: var(--fg-dim); 79 padding: 0.5rem 0.9rem; 80 border-radius: 6px 6px 0 0; 81 cursor: pointer; 82 font-size: 0.9rem; 83 } 84 .tab.is-active { background: var(--bg-panel); border-color: var(--line); color: var(--fg); } 85 .tab code { color: var(--accent); } 86 87 main { 88 display: grid; 89 grid-template-columns: minmax(24rem, 1fr) minmax(24rem, 1fr); 90 gap: 1.5rem; 91 padding: 1.5rem; 92 align-items: start; 93 } 94 @media (max-width: 1080px) { main { grid-template-columns: 1fr; } } 95 96 .panel { display: flex; flex-direction: column; gap: 1rem; } 97 98 .field { display: flex; flex-direction: column; gap: 0.35rem; } 99 .field > label { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg-dim); } 100 .hint { text-transform: none; letter-spacing: 0; color: var(--fg-dim); font-size: 0.75rem; } 101 .field-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; } 102 103 input, textarea, select { 104 background: var(--bg-raised); 105 border: 1px solid var(--line); 106 border-radius: 6px; 107 color: var(--fg); 108 padding: 0.45rem 0.6rem; 109 font: inherit; 110 width: 100%; 111 } 112 textarea { resize: vertical; line-height: 1.45; } 113 input:focus, textarea:focus, button:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; } 114 115 .state-mode { display: flex; gap: 0.35rem; align-items: center; font-size: 0.75rem; color: var(--fg-dim); } 116 .state-mode input { width: auto; } 117 .state-mode label { text-transform: uppercase; letter-spacing: 0.05em; } 118 119 .note { margin: 0; font-size: 0.78rem; color: var(--fg-dim); min-height: 1rem; } 120 .note.warn { color: var(--warn); } 121 122 .constraint { 123 margin: 0; 124 padding: 0.6rem 0.75rem; 125 border-left: 2px solid var(--accent); 126 background: var(--bg-panel); 127 font-size: 0.83rem; 128 color: var(--fg-dim); 129 } 130 131 .options { display: flex; flex-direction: column; gap: 0.35rem; } 132 .option-row { display: grid; grid-template-columns: 9.5rem 1fr 2rem; gap: 0.35rem; } 133 .option-row .remove-option { padding: 0; } 134 135 .decision { 136 border: 1px solid var(--line); 137 border-radius: 8px; 138 background: var(--bg-panel); 139 padding: 0.75rem; 140 margin-bottom: 0.75rem; 141 display: flex; 142 flex-direction: column; 143 gap: 0.5rem; 144 } 145 .decision-head { display: flex; align-items: center; gap: 0.5rem; } 146 .decision-head .d-id { max-width: 16rem; } 147 .decision-n { font-size: 0.75rem; text-transform: uppercase; color: var(--fg-dim); letter-spacing: 0.06em; } 148 149 button { 150 background: var(--bg-raised); 151 border: 1px solid var(--line); 152 border-radius: 6px; 153 color: var(--fg); 154 padding: 0.45rem 0.85rem; 155 font: inherit; 156 cursor: pointer; 157 } 158 button:hover:not(:disabled) { border-color: var(--accent); } 159 button:disabled { opacity: 0.5; cursor: progress; } 160 button.primary { background: var(--accent); border-color: var(--accent); color: #0b0e14; font-weight: 600; } 161 button.ghost { background: none; border-color: transparent; color: var(--fg-dim); } 162 button.ghost:hover { color: var(--accent); } 163 164 .actions { display: flex; gap: 0.5rem; flex-wrap: wrap; } 165 166 .presets { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--line); } 167 .presets-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg-dim); } 168 #preset-buttons { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.5rem; } 169 .preset { font-size: 0.82rem; padding: 0.3rem 0.7rem; } 170 171 #response { position: sticky; top: 1rem; } 172 .placeholder { color: var(--fg-dim); border: 1px dashed var(--line); border-radius: 8px; padding: 1.25rem; } 173 .placeholder p:first-child { margin-top: 0; color: var(--fg); } 174 .dim { color: var(--fg-dim); font-size: 0.83rem; } 175 .spinner { font-size: 1.5rem; color: var(--accent); animation: spin 1.4s linear infinite; display: inline-block; } 176 @keyframes spin { to { transform: rotate(360deg); } } 177 178 .error { 179 border: 1px solid var(--err); 180 border-left-width: 3px; 181 border-radius: 8px; 182 background: rgba(248, 81, 73, 0.07); 183 padding: 0.9rem 1rem; 184 } 185 .error h3 { margin: 0 0 0.5rem; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--err); } 186 .error pre { margin: 0; white-space: pre-wrap; word-break: break-word; font-size: 0.82rem; } 187 188 .flash { color: var(--win); } 189 190 .result-card { 191 border: 1px solid var(--line); 192 border-radius: 8px; 193 background: var(--bg-panel); 194 padding: 1rem; 195 margin-bottom: 1rem; 196 } 197 .headline { display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.75rem; } 198 .chosen { font-size: 1.3rem; color: var(--win); font-weight: 600; } 199 .score { color: var(--fg-dim); } 200 .rid { color: var(--fg-dim); font-size: 0.8rem; margin-left: auto; } 201 202 .section-title { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--fg-dim); margin: 1rem 0 0.5rem; } 203 204 table.probs { width: 100%; border-collapse: collapse; font-size: 0.86rem; } 205 table.probs th { 206 text-align: left; 207 font-size: 0.72rem; 208 text-transform: uppercase; 209 letter-spacing: 0.06em; 210 color: var(--fg-dim); 211 border-bottom: 1px solid var(--line); 212 padding: 0.2rem 0.4rem; 213 } 214 table.probs td { padding: 0.3rem 0.4rem; border-bottom: 1px solid rgba(42, 49, 64, 0.5); } 215 table.probs td.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; } 216 table.probs tr.is-winner td { color: var(--win); } 217 table.probs td.dim { color: var(--fg-dim); } 218 219 .bar { 220 display: inline-block; 221 width: 5rem; 222 height: 0.55rem; 223 margin-right: 0.5rem; 224 vertical-align: middle; 225 background: linear-gradient(to right, var(--accent) var(--w, 0%), rgba(42, 49, 64, 0.8) 0); 226 border-radius: 3px; 227 } 228 tr.is-winner .bar { background: linear-gradient(to right, var(--win) var(--w, 0%), rgba(42, 49, 64, 0.8) 0); } 229 230 dl.meta { 231 display: grid; 232 grid-template-columns: max-content 1fr; 233 gap: 0.15rem 0.9rem; 234 margin: 0.9rem 0 0; 235 font-size: 0.8rem; 236 } 237 dl.meta dt { color: var(--fg-dim); } 238 dl.meta dd { margin: 0; word-break: break-all; } 239 240 .disclaimer { 241 margin: 0.9rem 0 0; 242 padding-top: 0.7rem; 243 border-top: 1px solid var(--line); 244 font-size: 0.78rem; 245 color: var(--warn); 246 } 247 248 details.raw { margin-top: 0.5rem; font-size: 0.82rem; } 249 details.raw summary { cursor: pointer; color: var(--fg-dim); } 250 details.raw pre { 251 background: var(--bg-raised); 252 border: 1px solid var(--line); 253 border-radius: 6px; 254 padding: 0.7rem; 255 overflow-x: auto; 256 max-height: 24rem; 257 } 258 259 footer { padding: 1rem 1.5rem 2rem; color: var(--fg-dim); font-size: 0.8rem; border-top: 1px solid var(--line); } 260 footer p { margin: 0; } 261 262 .sr-only { position: absolute; left: -9999px; } 263 264 /* ── Demo tabs (platformer + puzzle room) ─────────────────────────────────────────────── 265 Fully scoped under .demo-panel so none of these selectors (pre, .bar, 266 .seg, .entry…) leak into the single/batch readout, or vice versa. */ 267 .demo-panel { 268 grid-column: 1 / -1; 269 display: grid; 270 gap: 1.25rem; 271 grid-template-columns: minmax(0, 3fr) minmax(280px, 2fr); 272 align-items: start; 273 } 274 @media (max-width: 900px) { .demo-panel { grid-template-columns: 1fr; } } 275 276 .demo-panel .game-stage, 277 .demo-panel .game-side { 278 background: var(--bg-panel); 279 border: 1px solid var(--line); 280 border-radius: 8px; 281 padding: 0.9rem 1rem; 282 } 283 .demo-panel h2 { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.06em; 284 color: var(--fg-dim); margin: 0 0 0.6rem; } 285 .demo-panel h2 + h2, .demo-panel pre + h2, .demo-panel textarea + h2 { margin-top: 0.9rem; } 286 .demo-panel canvas { display: block; width: 100%; background: var(--bg-raised); 287 border: 1px solid var(--line); border-radius: 6px; image-rendering: pixelated; } 288 .demo-panel .controls { display: flex; gap: 0.5rem; margin-top: 0.7rem; flex-wrap: wrap; align-items: center; } 289 .demo-panel .status { margin-left: auto; font-size: 0.85rem; color: var(--fg-dim); } 290 .demo-panel .status.win { color: var(--win); } 291 .demo-panel .status.err { color: var(--err); } 292 /* Planning status: rainbow wave, same size. Each letter is a span whose hue 293 cycles and bobs with a staggered negative delay, so the color travels 294 down the text like a wave. Removed the moment setStatus() runs again. */ 295 @keyframes planHue { 296 0% { color: hsl(0, 95%, 65%); } 297 25% { color: hsl(90, 95%, 65%); } 298 50% { color: hsl(180, 95%, 65%); } 299 75% { color: hsl(270, 95%, 65%); } 300 100% { color: hsl(360, 95%, 65%); } 301 } 302 @keyframes planBob { 303 0%, 100% { transform: translateY(0); } 304 50% { transform: translateY(-2px); } 305 } 306 .demo-panel .status.planning span { 307 display: inline-block; /* transforms need a non-inline box; size unchanged */ 308 animation: planHue 1.6s linear infinite, 309 planBob 0.8s ease-in-out infinite; 310 animation-delay: calc(var(--i) * -0.07s), calc(var(--i) * -0.07s); 311 } 312 .demo-panel .seg { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; } 313 .demo-panel .seg button { border: 0; border-radius: 0; padding: 0.4rem 0.7rem; font-size: 0.8rem; color: var(--fg-dim); } 314 .demo-panel .seg button.on { background: var(--bg-raised); color: var(--accent); } 315 .demo-panel .game-hint { margin: 0.6rem 0 0; font-size: 0.78rem; color: var(--fg-dim); } 316 .demo-panel .seed { display: inline-flex; align-items: center; gap: 0.35rem; 317 font-size: 0.78rem; color: var(--fg-dim); } 318 .demo-panel .seed-input { width: 8rem; padding: 0.35rem 0.5rem; font-size: 0.8rem; } 319 .demo-panel pre { font-family: var(--mono); font-size: 0.78rem; background: var(--bg-raised); 320 border: 1px solid var(--line); border-radius: 6px; padding: 0.6rem; margin: 0; 321 white-space: pre-wrap; word-break: break-word; max-height: 260px; overflow: auto; } 322 /* The rules pane is an editor, not a readout: same look as the pre it 323 replaced, but writable, resizable, and it never scrolls the run stats 324 or the decision log away. */ 325 .demo-panel textarea.rules-edit { font-family: var(--mono); font-size: 0.78rem; color: var(--fg); 326 background: var(--bg-raised); border: 1px solid var(--line); border-radius: 6px; padding: 0.6rem; 327 margin: 0; width: 100%; box-sizing: border-box; resize: vertical; min-height: 5.5rem; 328 line-height: 1.45; white-space: pre-wrap; } 329 .demo-panel textarea.rules-edit:focus { outline: none; border-color: var(--accent); } 330 .demo-panel .log { display: flex; flex-direction: column; gap: 0.5rem; max-height: 340px; overflow: auto; } 331 .demo-panel .entry { background: var(--bg-raised); border: 1px solid var(--line); border-radius: 6px; 332 padding: 0.5rem 0.6rem; font-size: 0.8rem; } 333 .demo-panel .entry .head { display: flex; gap: 0.6rem; align-items: baseline; margin-bottom: 0.3rem; } 334 .demo-panel .entry .n { color: var(--fg-dim); font-size: 0.72rem; text-transform: uppercase; } 335 .demo-panel .entry .choice { font-family: var(--mono); color: var(--accent); } 336 .demo-panel .entry .ms { margin-left: auto; color: var(--fg-dim); font-size: 0.75rem; } 337 .demo-panel .entry .probs { font-family: var(--mono); font-size: 0.72rem; color: var(--fg-dim); } 338 .demo-panel .entry .probs.expandable { cursor: pointer; white-space: pre-wrap; } 339 .demo-panel .entry.error .choice { color: var(--err); } 340 .demo-panel .entry.plan { border-color: var(--accent); } 341 .demo-panel .entry.plan .choice { color: var(--win); } 342 /* Override the readout's inline .bar; inside a decision entry it is a block fill. */ 343 .demo-panel .bar { display: block; width: auto; height: 5px; margin: 0.35rem 0 0; border-radius: 3px; 344 background: var(--line); overflow: hidden; } 345 .demo-panel .bar > span { display: block; height: 100%; background: var(--accent); } 346 .demo-panel .empty { color: var(--fg-dim); font-size: 0.8rem; }