case0 / web /src /styles /layout.css
HusseinEid's picture
Case Zero - initial public release (fully local: Qwen2.5-1.5B via llama.cpp + Supertonic, custom pixel-noir SPA via gradio.Server)
414dc55
raw
history blame
18.4 kB
/* ============================================================
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;
}
}