ai-playground / static /css /lab.css
Mukhlis
Redesign as an editorial AI exhibition
a9b35e6
Raw
History Blame Contribute Delete
15.1 kB
/* ==========================================================================
AI PLAYGROUND — LAB LAYOUT
One shared skeleton for all seven laboratories: editorial header, a
split workspace (controls left, live result right), an education block,
and related labs. On narrow screens the split stacks controls above result.
========================================================================== */
/* ==========================================================================
01 — LAB HEADER
========================================================================== */
.lab-hero {
padding-block: clamp(2.5rem, 5vw, 4.5rem) clamp(2rem, 4vw, 3.5rem);
}
.lab-hero__top {
display: flex;
align-items: center;
gap: var(--sp-3);
flex-wrap: wrap;
padding-bottom: var(--sp-5);
margin-bottom: var(--sp-6);
border-bottom: var(--rule) solid var(--line-ink);
}
.lab-hero__crumb {
display: inline-flex;
align-items: center;
gap: var(--sp-2);
font-family: var(--font-mono);
font-size: var(--t-10);
letter-spacing: var(--tr-caps);
text-transform: uppercase;
color: var(--ink-muted);
transition: color var(--dur-2) var(--ease);
}
.lab-hero__crumb:hover { color: var(--accent-ink); }
.lab-hero__crumb svg { width: 0.7rem; height: 0.7rem; }
.lab-hero__grid {
display: grid;
grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
gap: var(--sp-6) var(--sp-8);
align-items: end;
}
.lab-hero__title {
font-family: var(--font-display);
font-size: var(--t-display-2);
line-height: var(--lh-display);
letter-spacing: var(--tr-display);
}
.lab-hero__tagline {
font-size: clamp(var(--t-16), 1.4vw, var(--t-21));
line-height: var(--lh-prose);
color: var(--ink-secondary);
max-width: var(--measure);
text-wrap: pretty;
}
/* Metadata strip — model, parameters, IO, latency, where it runs */
.lab-meta {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
gap: var(--sp-4) var(--sp-5);
margin-top: var(--sp-7);
padding-top: var(--sp-5);
border-top: var(--rule) solid var(--line);
}
.lab-meta__item { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.lab-meta__key {
font-family: var(--font-mono);
font-size: var(--t-9);
letter-spacing: var(--tr-caps);
text-transform: uppercase;
color: var(--ink-faint);
}
.lab-meta__val {
font-size: var(--t-14);
font-weight: var(--fw-medium);
color: var(--ink);
line-height: 1.3;
word-break: break-word;
}
.lab-meta__val a {
color: var(--accent-ink);
text-decoration: underline;
text-underline-offset: 0.2em;
}
@media (max-width: 900px) {
.lab-hero__grid { grid-template-columns: 1fr; align-items: start; }
}
/* ==========================================================================
02 — SPLIT WORKSPACE
========================================================================== */
.lab-split {
display: grid;
grid-template-columns: minmax(0, 25rem) minmax(0, 1fr);
gap: var(--sp-6);
align-items: start;
padding-bottom: var(--sp-9);
}
/* Left rail — instructions and controls */
.lab-console {
display: flex;
flex-direction: column;
gap: var(--sp-5);
border: var(--rule) solid var(--line);
border-radius: var(--r-2);
background: var(--paper-raised);
padding: var(--sp-5);
position: sticky;
top: 5.5rem;
max-height: calc(100vh - 7rem);
overflow-y: auto;
overscroll-behavior: contain;
scrollbar-width: thin;
}
.lab-console::-webkit-scrollbar { width: 5px; }
.lab-console::-webkit-scrollbar-thumb {
background: var(--line-strong);
border-radius: var(--r-pill);
}
.console-block { display: flex; flex-direction: column; gap: var(--sp-3); }
.console-block + .console-block {
padding-top: var(--sp-5);
border-top: var(--rule) solid var(--line);
}
.console-block__head {
display: flex;
align-items: baseline;
gap: var(--sp-3);
}
.console-block__num {
font-family: var(--font-mono);
font-size: var(--t-9);
letter-spacing: var(--tr-label);
color: var(--accent-ink);
flex: none;
}
.console-block__title {
font-size: var(--t-13, 0.8125rem);
font-weight: var(--fw-semi);
letter-spacing: var(--tr-mid);
}
.console-actions {
display: flex;
gap: var(--sp-2);
flex-wrap: wrap;
}
.console-actions .btn { flex: 1 1 auto; }
/* Right — the live result */
.lab-output {
display: flex;
flex-direction: column;
gap: var(--sp-4);
min-width: 0;
}
.lab-stage {
position: relative;
border: var(--rule) solid var(--line);
border-radius: var(--r-2);
background: var(--paper-warm);
overflow: hidden;
min-height: 26rem;
display: flex;
flex-direction: column;
justify-content: center;
}
.lab-stage__bar {
display: flex;
align-items: center;
gap: var(--sp-3);
padding: var(--sp-3) var(--sp-4);
border-bottom: var(--rule) solid var(--line);
background: var(--paper);
flex: none;
}
.lab-stage__bar .spacer { flex: 1; }
.lab-stage__inner {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding: var(--sp-5);
min-height: 0;
}
.lab-stage__inner--flush { padding: 0; }
.lab-stage img { border-radius: var(--r-2); }
/* Result panel below the stage: detections, transcript, metrics */
.lab-readout {
border: var(--rule) solid var(--line);
border-radius: var(--r-2);
background: var(--paper-raised);
padding: var(--sp-5);
}
@media (max-width: 1024px) {
.lab-split { grid-template-columns: 1fr; }
.lab-console {
position: static;
max-height: none;
overflow: visible;
}
.lab-stage { min-height: 20rem; }
}
/* ==========================================================================
03 — CHAT-SPECIFIC (conversation column)
========================================================================== */
.chat-log {
display: flex;
flex-direction: column;
gap: var(--sp-4);
padding: var(--sp-5);
overflow-y: auto;
flex: 1;
min-height: 22rem;
max-height: 60vh;
scroll-behavior: smooth;
}
.msg {
display: flex;
flex-direction: column;
gap: var(--sp-2);
max-width: 46rem;
animation: rise var(--dur-3) var(--ease);
}
.msg--user { align-self: flex-end; align-items: flex-end; }
.msg__who {
font-family: var(--font-mono);
font-size: var(--t-9);
letter-spacing: var(--tr-caps);
text-transform: uppercase;
color: var(--ink-faint);
}
.msg__bubble {
padding: var(--sp-4) var(--sp-5);
border-radius: var(--r-3);
font-size: var(--t-15, 0.9375rem);
line-height: var(--lh-prose);
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.msg--ai .msg__bubble {
background: var(--paper-sunk);
border: var(--rule) solid var(--line);
border-top-left-radius: var(--r-1);
}
.msg--user .msg__bubble {
background: var(--ink);
color: var(--ink-inverse);
border-top-right-radius: var(--r-1);
}
.msg__foot {
display: flex;
gap: var(--sp-3);
flex-wrap: wrap;
font-family: var(--font-mono);
font-size: var(--t-9);
letter-spacing: var(--tr-label);
text-transform: uppercase;
color: var(--ink-faint);
}
.chat-compose {
display: flex;
gap: var(--sp-3);
align-items: flex-end;
padding: var(--sp-4);
border-top: var(--rule) solid var(--line);
background: var(--paper);
flex: none;
}
.chat-compose .textarea {
min-height: 2.75rem;
max-height: 9rem;
resize: none;
}
.typing { display: inline-flex; gap: 0.25rem; align-items: center; }
.typing span {
width: 0.3rem; height: 0.3rem;
border-radius: 50%;
background: var(--ink-faint);
animation: typing 1.2s ease-in-out infinite;
}
.typing span:nth-child(2) { animation-delay: 0.15s; }
.typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes typing {
0%, 60%, 100% { opacity: 0.25; transform: translateY(0); }
30% { opacity: 1; transform: translateY(-2px); }
}
/* Suggested prompts */
.suggestions { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.suggestion {
padding: 0.45rem 0.75rem;
min-height: 2.25rem;
font-size: var(--t-12);
border: var(--rule) solid var(--line);
border-radius: var(--r-pill);
color: var(--ink-secondary);
text-align: left;
transition: all var(--dur-2) var(--ease);
}
.suggestion:hover {
border-color: var(--accent);
background: var(--accent-wash);
color: var(--ink);
}
/* ==========================================================================
04 — GALLERY (Dream)
========================================================================== */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(9rem, 100%), 1fr));
gap: var(--sp-3);
}
.gallery__item {
position: relative;
aspect-ratio: 1;
border: var(--rule) solid var(--line);
border-radius: var(--r-2);
overflow: hidden;
cursor: pointer;
padding: 0;
background: var(--paper-sunk);
transition: all var(--dur-2) var(--ease);
}
.gallery__item:hover { border-color: var(--accent); transform: translateY(-2px); }
.gallery__item img { width: 100%; height: 100%; object-fit: cover; }
.gallery__item[aria-current="true"] {
border-color: var(--accent);
box-shadow: 0 0 0 2px var(--accent);
}
.gallery__seed {
position: absolute;
left: 0; right: 0; bottom: 0;
padding: 0.25rem 0.4rem;
font-family: var(--font-mono);
font-size: var(--t-9);
letter-spacing: var(--tr-label);
background: rgba(0, 0, 0, 0.7);
color: #fff;
text-align: left;
}
/* Prompt evolution — a lineage of small wording changes */
.evolution { border-top: var(--rule) solid var(--line); }
.evolution__row {
display: grid;
grid-template-columns: 2.5rem minmax(0, 1fr) auto;
align-items: center;
gap: var(--sp-4);
padding: var(--sp-3) 0;
border-bottom: var(--rule) solid var(--line);
font-size: var(--t-13, 0.8125rem);
}
.evolution__num {
font-family: var(--font-mono);
font-size: var(--t-10);
color: var(--accent-ink);
}
.evolution__text { line-height: var(--lh-prose); overflow-wrap: anywhere; }
.evolution__text ins {
background: var(--green-200);
color: var(--green-900);
text-decoration: none;
padding: 0 2px;
border-radius: 2px;
}
.evolution__text del {
background: var(--red-200);
color: var(--red-900);
padding: 0 2px;
border-radius: 2px;
}
[data-theme="dark"] .evolution__text ins { background: var(--green-900); color: var(--green-400); }
[data-theme="dark"] .evolution__text del { background: var(--red-900); color: var(--red-400); }
.evolution__thumb {
width: 3rem; height: 3rem;
border-radius: var(--r-2);
object-fit: cover;
border: var(--rule) solid var(--line);
}
/* ==========================================================================
05 — AUDIO
========================================================================== */
.player {
display: flex;
align-items: center;
gap: var(--sp-3);
padding: var(--sp-4);
border: var(--rule) solid var(--line);
border-radius: var(--r-2);
background: var(--paper-raised);
flex-wrap: wrap;
}
.player__btn {
display: grid;
place-items: center;
width: 2.75rem; height: 2.75rem;
border-radius: 50%;
background: var(--accent);
color: var(--accent-on);
flex: none;
transition: transform var(--dur-2) var(--ease), filter var(--dur-2) var(--ease);
}
.player__btn:hover { filter: brightness(1.1); transform: scale(1.05); }
.player__btn svg { width: 1.1rem; height: 1.1rem; }
.player__time {
font-family: var(--font-mono);
font-size: var(--t-12);
font-variant-numeric: tabular-nums;
color: var(--ink-muted);
flex: none;
}
.player__scrub { flex: 1 1 8rem; min-width: 6rem; }
/* Karaoke-style word highlight driven by TTS word boundaries */
.speech-text {
font-size: var(--t-18);
line-height: 1.8;
color: var(--ink-muted);
text-wrap: pretty;
}
.speech-text .word {
transition: color var(--dur-1) var(--ease), background-color var(--dur-1) var(--ease);
border-radius: 2px;
padding: 0 1px;
}
.speech-text .word.is-spoken { color: var(--ink); }
.speech-text .word.is-current {
color: var(--ink);
background: var(--accent-wash);
box-shadow: 0 1px 0 var(--accent);
}
/* Recording indicator */
.rec-dot {
width: 0.6rem; height: 0.6rem;
border-radius: 50%;
background: var(--red-700);
animation: pulse-soft 1s ease-in-out infinite;
flex: none;
}
/* ==========================================================================
06 — EDUCATION BLOCK (shared by every lab)
========================================================================== */
.lab-learn {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: var(--sp-8);
padding-block: var(--section-y);
border-top: var(--rule) solid var(--line-ink);
}
@media (max-width: 900px) {
.lab-learn { grid-template-columns: 1fr; gap: var(--sp-7); }
}
.pipeline {
display: flex;
align-items: stretch;
gap: var(--sp-2);
margin-block: var(--sp-5);
flex-wrap: wrap;
}
.pipeline__node {
flex: 1 1 6rem;
padding: var(--sp-4) var(--sp-3);
border: var(--rule) solid var(--line);
border-radius: var(--r-2);
text-align: center;
background: var(--paper-raised);
min-width: 0;
}
.pipeline__node--model {
background: var(--accent-wash);
border-color: var(--accent-line);
}
.pipeline__kind {
font-family: var(--font-mono);
font-size: var(--t-9);
letter-spacing: var(--tr-caps);
text-transform: uppercase;
color: var(--ink-faint);
display: block;
margin-bottom: var(--sp-2);
}
.pipeline__what {
font-size: var(--t-13, 0.8125rem);
font-weight: var(--fw-medium);
line-height: 1.35;
}
.pipeline__arrow {
display: grid;
place-items: center;
color: var(--ink-faint);
flex: none;
width: 1.25rem;
}
.pipeline__arrow svg { width: 0.9rem; height: 0.9rem; }
/* ==========================================================================
07 — RELATED LABS
========================================================================== */
.related {
padding-block: var(--section-y);
border-top: var(--rule) solid var(--line-ink);
}
.related__list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
gap: var(--sp-4);
}
.related__item {
display: flex;
flex-direction: column;
gap: var(--sp-2);
padding: var(--sp-5);
border: var(--rule) solid var(--line);
border-radius: var(--r-2);
transition: all var(--dur-2) var(--ease);
}
.related__item:hover {
border-color: var(--accent);
background: var(--accent-wash);
transform: translateY(-2px);
}
.related__name {
font-family: var(--font-display);
font-size: var(--t-24);
letter-spacing: var(--tr-tight);
}
.related__why { font-size: var(--t-12); color: var(--ink-muted); line-height: var(--lh-prose); }
/* ==========================================================================
08 — SHARE / EXPORT BAR
========================================================================== */
.export-bar {
display: flex;
align-items: center;
gap: var(--sp-2);
flex-wrap: wrap;
padding-top: var(--sp-4);
border-top: var(--rule) solid var(--line);
}
/* Copy-confirmation flash on any button */
.btn.is-copied {
background: var(--green-600);
border-color: var(--green-600);
color: var(--gray-900);
}