Spaces:
Running
Running
Case Zero - initial public release (fully local: Qwen2.5-1.5B via llama.cpp + Supertonic, custom pixel-noir SPA via gradio.Server)
414dc55 | /* ============================================================ | |
| LAYOUT & SCREEN CHROME (ported from prototype/css/layout.css) | |
| ============================================================ */ | |
| .app{ position:fixed; inset:0; display:flex; flex-direction:column; background:var(--ink-0); } | |
| .app__view{ position:absolute; inset:0; display:flex; flex-direction:column; flex:1; min-height:0; } | |
| /* device simulation: mobile = centered phone column */ | |
| .app[data-mode="mobile"] .app__frame{ | |
| width:min(430px,100vw); height:min(932px,100vh); margin:auto; | |
| position:relative; box-shadow:0 0 0 6px var(--ink-2), 0 0 0 9px var(--ink-0), 0 0 60px -10px #000; | |
| overflow:hidden; display:flex; flex-direction:column; | |
| } | |
| .app[data-mode="mobile"] .app__stage{ background:var(--ink-1); } | |
| .app[data-mode="desktop"] .app__frame{ position:absolute; inset:0; display:flex; flex-direction:column; } | |
| .app__stage{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center; } | |
| /* ---------- view toggle (top, outside content) ---------- */ | |
| .viewbar{ | |
| position:fixed; top:10px; right:14px; z-index:80; | |
| display:flex; gap:6px; align-items:center; | |
| } | |
| .viewbar .seg{ display:flex; box-shadow:0 0 0 3px var(--ink-0); } | |
| .viewbar .seg button{ | |
| font-family:var(--f-display); font-size:8px; letter-spacing:.08em; | |
| padding:6px 9px; background:var(--ink-2); color:var(--bone-1); border:0; | |
| } | |
| .viewbar .seg button.on{ background:var(--amber-2); color:var(--ink-0); } | |
| /* ============================================================ | |
| HUD (top chrome of in-game screens) | |
| ============================================================ */ | |
| .hud{ | |
| display:flex; align-items:center; justify-content:space-between; gap:12px; | |
| padding:10px 14px; background:var(--ink-2); | |
| box-shadow:inset 0 -3px 0 var(--ink-0), 0 3px 0 var(--ink-0); | |
| z-index:20; flex-shrink:0; | |
| } | |
| .hud-badge{ | |
| display:flex; flex-direction:column; align-items:flex-start; gap:1px; | |
| background:var(--amber-2); border:0; padding:5px 9px; line-height:1.1; flex-shrink:0; | |
| box-shadow:2px 2px 0 var(--ink-0), inset -2px -2px 0 rgba(0,0,0,.25); | |
| } | |
| .hud-badge span{ white-space:nowrap; } | |
| .hud-badge:hover{ background:var(--amber-3); } | |
| /* Title clamps to one line with an ellipsis on desktop (plenty of width there). */ | |
| .hud__title{ | |
| font-size:12px; color:var(--bone-3); line-height:1.15; | |
| white-space:nowrap; overflow:hidden; text-overflow:ellipsis; | |
| } | |
| /* On narrow screens, wrap to two lines at a smaller size instead of cropping mid-word. */ | |
| [data-mode="mobile"] .hud__title{ | |
| font-size:10px; white-space:normal; overflow:hidden; | |
| display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; | |
| } | |
| /* ============================================================ | |
| BOTTOM NAV (mobile) | |
| ============================================================ */ | |
| .bottom-nav{ display:none; } | |
| [data-mode="mobile"] .bottom-nav{ | |
| display:flex; justify-content:space-around; align-items:center; | |
| background:var(--ink-2); box-shadow:inset 0 3px 0 var(--ink-0); | |
| padding:7px 4px 9px; flex-shrink:0; z-index:20; | |
| } | |
| .nav-btn{ | |
| display:flex; flex-direction:column; align-items:center; gap:4px; | |
| background:transparent; border:0; color:var(--bone-1); padding:4px 8px; min-width:56px; min-height:44px; | |
| position:relative; | |
| } | |
| .nav-btn--on{ color:var(--ink-0); } | |
| .nav-btn--on::before{ | |
| content:''; position:absolute; margin-top:-9px; width:34px; height:34px; | |
| background:var(--amber-2); z-index:-1; box-shadow:0 0 0 2px var(--ink-0); | |
| } | |
| /* ============================================================ | |
| "DEVELOPS IN" reveal — scanline/dither wipe | |
| ============================================================ */ | |
| .develop-veil{ position:absolute; inset:0; background:var(--ink-1); z-index:3; | |
| background-image:repeating-linear-gradient(0deg, rgba(0,0,0,.5) 0 2px, transparent 2px 4px); } | |
| .develop-veil--anim{ animation:develop .7s steps(10) forwards; } | |
| @keyframes develop{ | |
| 0%{ clip-path:inset(0 0 0 0); opacity:1; } | |
| 99%{ clip-path:inset(0 0 100% 0); opacity:1; } | |
| 100%{ clip-path:inset(0 0 100% 0); opacity:0; } | |
| } | |
| /* ============================================================ | |
| DOSSIER — physical case file you flip through | |
| ============================================================ */ | |
| .dossier-stage{ flex:1; display:flex; align-items:center; justify-content:center; padding:20px; perspective:2200px; overflow:hidden; } | |
| .dossier{ width:min(820px,96vw); max-height:100%; display:flex; flex-direction:column; gap:14px; } | |
| .dossier__folder{ | |
| position:relative; background:linear-gradient(160deg,#2a2417,#1c1810); | |
| box-shadow:0 0 0 3px var(--ink-0), 0 18px 40px -12px #000, inset 0 2px 0 rgba(224,164,76,.12); | |
| padding:14px; | |
| } | |
| .dossier__folder::before{ | |
| content:''; position:absolute; top:-14px; left:30px; width:120px; height:16px; | |
| background:linear-gradient(160deg,#2a2417,#1c1810); box-shadow:0 0 0 3px var(--ink-0); | |
| clip-path:polygon(8% 0,92% 0,100% 100%,0 100%); | |
| } | |
| .page-wrap{ position:relative; height:min(560px,68vh); transform-style:preserve-3d; } | |
| .page{ | |
| position:absolute; inset:0; background:#e7e0cc; color:#211d15; | |
| padding:26px 30px; overflow:auto; | |
| box-shadow:inset 0 0 0 1px #b9b09433, 0 4px 0 rgba(0,0,0,.35), 6px 8px 18px -6px rgba(0,0,0,.5); | |
| background-image:repeating-linear-gradient(0deg, transparent 0 27px, rgba(33,29,21,.06) 27px 28px); | |
| font-family:var(--f-mono); | |
| } | |
| .page--paper2{ background:#ece6d4; } | |
| .page--flip-fwd{ animation:flipFwd .46s cubic-bezier(.2,.6,.2,1) both; transform-origin:left center; } | |
| .page--flip-back{ animation:flipBack .46s cubic-bezier(.2,.6,.2,1) both; transform-origin:right center; } | |
| @keyframes flipFwd{ from{ transform:rotateY(82deg); opacity:.2; } to{ transform:rotateY(0); opacity:1; } } | |
| @keyframes flipBack{ from{ transform:rotateY(-82deg); opacity:.2; } to{ transform:rotateY(0); opacity:1; } } | |
| .page__edge{ position:absolute; top:0; bottom:0; width:34px; cursor:pointer; z-index:5; } | |
| .page__edge--r{ right:0; background:linear-gradient(270deg, rgba(0,0,0,.14), transparent); } | |
| .page__edge--l{ left:0; background:linear-gradient(90deg, rgba(0,0,0,.14), transparent); } | |
| .page__edge:hover{ filter:brightness(1.1); } | |
| .page__curl{ position:absolute; bottom:0; right:0; width:0; height:0; | |
| border-style:solid; border-width:0 0 26px 26px; border-color:transparent transparent #cfc6ad transparent; | |
| box-shadow:-2px -2px 4px rgba(0,0,0,.2); pointer-events:none; } | |
| .dh{ font-family:var(--f-display); text-transform:uppercase; color:#1a1610; letter-spacing:.02em; } | |
| .dlabel{ font-family:var(--f-display); font-size:8px; letter-spacing:.18em; color:#8a3a2c; text-transform:uppercase; } | |
| .dtype{ font-family:var(--f-mono); font-size:calc(17px*var(--mono-scale)); line-height:1.55; color:#2a251b; } | |
| .dstamp{ font-family:var(--f-display); text-transform:uppercase; color:#8a2a2a; | |
| border:3px solid #8a2a2a; padding:5px 10px; letter-spacing:.05em; transform:rotate(-7deg); | |
| opacity:.82; box-shadow:0 0 0 1px #8a2a2a33; display:inline-block; } | |
| .paperclip{ position:absolute; top:-8px; left:18px; width:14px; height:34px; | |
| border:3px solid #9aa0a6; border-radius:8px; border-bottom-color:transparent; transform:rotate(8deg); } | |
| .photo-paper{ background:#fff; padding:6px 6px 22px; box-shadow:3px 5px 0 rgba(0,0,0,.3); transform:rotate(-2deg); position:relative; } | |
| .dossier__nav{ display:flex; align-items:center; justify-content:space-between; gap:12px; } | |
| .page-dots{ display:flex; gap:6px; } | |
| .page-dot{ width:24px; height:6px; background:#3a3324; box-shadow:inset 0 0 0 1px var(--ink-0); cursor:pointer; } | |
| .page-dot--on{ background:var(--amber-2); } | |
| [data-mode="mobile"] .page{ padding:20px 18px; } | |
| [data-mode="mobile"] .page-wrap{ height:62vh; } | |
| /* let the dossier nav wrap so long labels ("Open the Wall") never crop on narrow phones */ | |
| [data-mode="mobile"] .dossier__nav{ flex-wrap:wrap; row-gap:8px; justify-content:center; } | |
| [data-mode="mobile"] .dossier__nav .pbtn{ flex-shrink:0; } | |
| /* ============================================================ | |
| ASSISTANT — partner-on-the-wire hint dock | |
| ============================================================ */ | |
| .assistant{ position:fixed; left:14px; bottom:14px; z-index:70; display:flex; flex-direction:column; align-items:flex-start; gap:10px; } | |
| [data-mode="mobile"] .assistant{ bottom:78px; left:10px; right:10px; } | |
| .assistant__panel{ | |
| width:min(330px,92vw); background:var(--ink-2); padding:12px; | |
| box-shadow:0 0 0 3px var(--ink-0), inset 0 0 0 2px var(--amber-1), 0 0 26px -8px var(--glow); | |
| animation:slideup .2s steps(5); | |
| } | |
| .assistant__x{ background:transparent; border:0; color:var(--bone-1); font-family:var(--f-mono); font-size:16px; line-height:1; padding:2px 4px; } | |
| .assistant__x:hover{ color:var(--ox-3); } | |
| .hint-btn{ | |
| display:inline-flex; align-items:center; gap:6px; | |
| font-family:var(--f-display); font-size:9px; letter-spacing:.1em; | |
| color:var(--ink-0); background:var(--amber-2); border:0; padding:8px 11px; | |
| box-shadow:2px 2px 0 var(--ink-0), inset -2px -2px 0 rgba(0,0,0,.25); | |
| } | |
| .hint-btn:hover{ background:var(--amber-3); } | |
| .hint-btn__dot{ width:6px; height:6px; background:var(--ink-0); animation:blink 1.3s steps(1) infinite; } | |
| /* ============================================================ | |
| INVESTIGATION BOARD — corkboard | |
| ============================================================ */ | |
| .board{ position:relative; flex:1; overflow:hidden; | |
| background: | |
| radial-gradient(rgba(0,0,0,.22) 1px, transparent 1px), | |
| radial-gradient(rgba(255,255,255,.035) 1px, transparent 1px), | |
| repeating-linear-gradient(26deg, rgba(0,0,0,.05) 0 2px, transparent 2px 5px), | |
| linear-gradient(160deg, #5a4326, #3a2c18 55%, #2a2012); | |
| background-size:5px 5px, 7px 7px, 9px 9px, 100% 100%; | |
| background-position:0 0, 3px 4px, 0 0, 0 0; | |
| } | |
| .board__felt{ position:absolute; inset:0; pointer-events:none; | |
| background: | |
| radial-gradient(70% 50% at 50% 0%, rgba(245,208,138,.16), transparent 60%), | |
| radial-gradient(120% 90% at 50% 45%, transparent 45%, rgba(0,0,0,.5) 100%); | |
| } | |
| .board__frame{ position:absolute; inset:6px; pointer-events:none; z-index:9; | |
| box-shadow:inset 0 0 0 5px #241a0e, inset 0 0 0 8px #120d07, inset 0 0 40px 6px rgba(0,0,0,.5); } | |
| .wall-item{ position:absolute; z-index:2; } | |
| .pushpin{ position:absolute; top:-7px; left:50%; transform:translateX(-50%); width:11px; height:11px; z-index:3; | |
| background:var(--amber-2); box-shadow:0 0 0 2px var(--ink-0), inset -2px -2px 0 var(--amber-1); } | |
| .pushpin--ox{ background:var(--ox-3); box-shadow:0 0 0 2px var(--ink-0), inset -2px -2px 0 var(--ox-1); } | |
| .pushpin--bone{ background:var(--bone-2); box-shadow:0 0 0 2px var(--ink-0), inset -2px -2px 0 var(--bone-1); } | |
| .wall-photo{ background:#efe9d6; padding:6px 6px 16px; box-shadow:4px 6px 0 rgba(0,0,0,.45); } | |
| .wall-clip{ background:#e3ddc8; color:#231f16; padding:9px 11px; box-shadow:4px 6px 0 rgba(0,0,0,.45); | |
| background-image:repeating-linear-gradient(0deg, transparent 0 9px, rgba(0,0,0,.05) 9px 10px); } | |
| .wall-note{ background:var(--amber-2); color:#2a1f0c; padding:11px 12px; box-shadow:4px 6px 0 rgba(0,0,0,.4); | |
| font-family:var(--f-body); } | |
| .wall-note--bone{ background:#e7e0cc; color:#231f16; } | |
| .wall-redact{ background:#1a1610; padding:10px; box-shadow:4px 6px 0 rgba(0,0,0,.45); } | |
| .wall-redact .bar-blk{ height:7px; background:#0a0805; margin:4px 0; } | |
| .scrawl{ font-family:var(--f-body); line-height:1.2; } | |
| .pin-card{ position:absolute; cursor:default; user-select:none; z-index:4; transition:transform .05s; } | |
| .pin-card .pin{ | |
| position:absolute; top:-9px; left:50%; transform:translateX(-50%); | |
| width:12px; height:12px; background:var(--ox-3); z-index:6; cursor:grab; | |
| box-shadow:0 0 0 2px var(--ink-0), inset -2px -2px 0 var(--ox-1); | |
| } | |
| .pin-card .pin:active{ cursor:grabbing; } | |
| .card-grip{ display:flex; align-items:center; justify-content:space-between; gap:6px; | |
| background:var(--ink-3); color:var(--bone-1); padding:2px 6px; cursor:grab; | |
| box-shadow:inset 0 0 0 2px var(--ink-0); } | |
| .card-grip:active{ cursor:grabbing; background:var(--slate-1); } | |
| .card-grip__dots{ font-size:11px; line-height:1; letter-spacing:-1px; color:var(--amber-2); } | |
| .card-grip__lbl{ font-family:var(--f-display); font-size:7px; letter-spacing:.12em; } | |
| .card-actions{ margin-top:6px; display:flex; justify-content:center; } | |
| .pin-card--sel{ filter:drop-shadow(0 0 14px rgba(224,164,76,.35)); } | |
| .pin-note{ background:var(--bone-2); color:var(--ink-1); padding:8px 10px; | |
| box-shadow:3px 4px 0 rgba(0,0,0,.4); font-family:var(--f-body); } | |
| .board__filters{ position:absolute; top:12px; left:12px; z-index:8; display:flex; gap:6px; flex-wrap:wrap; } | |
| .board-layout{ flex:1; display:flex; min-height:0; } | |
| .board-layout .board{ flex:1; } | |
| .suspect-rail{ width:316px; flex-shrink:0; background:var(--ink-2); box-shadow:inset 4px 0 0 var(--ink-0); | |
| display:flex; flex-direction:column; min-height:0; } | |
| .suspect-rail__head{ padding:14px 14px 10px; box-shadow:inset 0 -3px 0 var(--ink-0); } | |
| .suspect-rail__list{ flex:1; overflow-y:auto; padding:12px; display:flex; flex-direction:column; gap:10px; } | |
| .rail-card{ cursor:pointer; } | |
| .rail-card__reveal{ overflow:hidden; max-height:0; transition:max-height .25s steps(6); } | |
| .rail-card__reveal--open{ max-height:200px; } | |
| /* ============================================================ | |
| INTERROGATION | |
| ============================================================ */ | |
| .interro{ flex:1; display:grid; grid-template-columns:minmax(300px,440px) 1fr; gap:0; overflow:hidden; } | |
| .interro__stage{ position:relative; overflow:hidden; background:var(--ink-0); display:flex; flex-direction:column; } | |
| .interro__sprite{ position:absolute; left:50%; bottom:0; transform:translateX(-50%); z-index:2; } | |
| .interro__right{ display:flex; flex-direction:column; min-width:0; background:var(--ink-1); | |
| box-shadow:inset 4px 0 0 var(--ink-0); } | |
| .transcript{ flex:1; overflow-y:auto; padding:16px; display:flex; flex-direction:column; gap:12px; } | |
| .tline{ max-width:88%; } | |
| .tline--det{ align-self:flex-end; } | |
| .tline--det .tline__b{ background:var(--slate-1); color:var(--bone-3); box-shadow:inset -2px -2px 0 rgba(0,0,0,.4); } | |
| .tline--sus .tline__b{ background:var(--ink-3); color:var(--bone-2); box-shadow:inset 0 0 0 2px var(--ink-0); } | |
| .tline__b{ padding:10px 12px; font-family:var(--f-body); font-size:15px; line-height:1.45; } | |
| .tline__who{ font-family:var(--f-display); font-size:8px; letter-spacing:.1em; color:var(--bone-1); margin-bottom:4px; } | |
| .tline--det .tline__who{ text-align:right; color:var(--amber-2); } | |
| .composer{ flex-shrink:0; padding:12px; background:var(--ink-2); box-shadow:inset 0 3px 0 var(--ink-0); } | |
| .qsuggest{ display:flex; gap:6px; flex-wrap:wrap; margin-bottom:10px; } | |
| .qchip{ font-family:var(--f-body); font-size:13px; line-height:1.25; padding:7px 10px; background:var(--ink-1); | |
| color:var(--bone-2); border:0; box-shadow:inset 0 0 0 2px var(--slate-1); text-align:left; flex:1 1 auto; min-width:0; } | |
| .qchip:hover{ box-shadow:inset 0 0 0 2px var(--amber-2); color:var(--bone-3); } | |
| .qchip:disabled{ opacity:.35; } | |
| .composer__input{ display:flex; gap:8px; } | |
| .pinput{ flex:1; background:var(--ink-1); border:0; color:var(--bone-3); padding:11px 12px; | |
| font-size:15px; box-shadow:inset 0 0 0 2px var(--ink-0), inset 2px 2px 0 rgba(0,0,0,.4); outline:none; } | |
| .pinput::placeholder{ color:var(--bone-1); } | |
| .pinput:focus{ box-shadow:inset 0 0 0 2px var(--amber-1); } | |
| .tray{ position:absolute; inset:0; z-index:30; background:rgba(8,11,16,.82); | |
| display:flex; flex-direction:column; justify-content:flex-end; } | |
| .tray__sheet{ background:var(--ink-2); box-shadow:0 -4px 0 var(--ink-0), inset 0 4px 0 var(--amber-1); | |
| padding:16px; max-height:70%; overflow-y:auto; animation:slideup .25s steps(6); } | |
| @keyframes slideup{ from{ transform:translateY(100%);} to{ transform:translateY(0);} } | |
| .tray__grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(210px,1fr)); gap:10px; } | |
| /* ============================================================ | |
| GENERIC SCREEN SCAFFOLD | |
| ============================================================ */ | |
| .screen-pad{ flex:1; overflow-y:auto; padding:22px; } | |
| .screen-center{ flex:1; display:flex; align-items:center; justify-content:center; padding:22px; overflow-y:auto; } | |
| .maxw{ width:100%; max-width:1180px; margin:0 auto; } | |
| .grid-2{ display:grid; grid-template-columns:1fr 1fr; gap:18px; } | |
| .grid-3{ display:grid; grid-template-columns:repeat(3,1fr); gap:14px; } | |
| .grid-4{ display:grid; grid-template-columns:repeat(4,1fr); gap:14px; } | |
| /* ============================================================ | |
| TIMELINE | |
| ============================================================ */ | |
| .tl-track{ position:relative; padding:30px 10px; } | |
| .tl-line{ position:absolute; left:0; right:0; top:50%; height:4px; | |
| background:repeating-linear-gradient(90deg,var(--slate-1) 0 6px, transparent 6px 12px); } | |
| .tl-stop{ position:relative; z-index:2; display:flex; flex-direction:column; align-items:center; gap:6px; } | |
| .tl-node{ width:14px; height:14px; background:var(--slate-2); box-shadow:0 0 0 3px var(--ink-0); } | |
| .tl-node--lock{ background:var(--amber-2); } | |
| .tl-node--conflict{ background:var(--ox-3); } | |
| .tl-slot{ min-height:62px; } | |
| /* ============================================================ | |
| FLASHBACK compare | |
| ============================================================ */ | |
| .flash-grid{ display:grid; grid-template-columns:1fr 1fr; gap:16px; } | |
| .flash-flag{ box-shadow:inset 0 0 0 2px var(--ox-2); } | |
| /* ============================================================ | |
| RESPONSIVE | |
| ============================================================ */ | |
| [data-mode="mobile"] .interro{ grid-template-columns:1fr; grid-template-rows:auto 1fr; } | |
| [data-mode="mobile"] .interro__stage{ height:32vh; min-height:200px; } | |
| [data-mode="mobile"] .grid-2,[data-mode="mobile"] .grid-3,[data-mode="mobile"] .grid-4,[data-mode="mobile"] .flash-grid{ grid-template-columns:1fr; } | |
| [data-mode="mobile"] .screen-pad{ padding:14px; } | |
| [data-mode="mobile"] .hud{ padding:9px 11px; } | |
| @media (max-width:760px){ | |
| .app[data-mode="auto"] .interro{ grid-template-columns:1fr; grid-template-rows:auto 1fr; } | |
| .app[data-mode="auto"] .grid-2,.app[data-mode="auto"] .grid-3,.app[data-mode="auto"] .grid-4{ grid-template-columns:1fr; } | |
| .app[data-mode="auto"] .hud__title{ | |
| font-size:10px; white-space:normal; overflow:hidden; | |
| display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; | |
| } | |
| } | |