SignLens / style.css
venmugilrajan's picture
Fix mobile UI overlap, increase 3D avatar size, and re-enable touch rotation on mobile
7bc4b9d verified
Raw History Blame Contribute Delete
77.9 kB
/* ============================================================
SignLens
Real-time sign language readout.
Design read: instrument UI, not a marketing page. The camera
feed and the skeleton overlay are the moving content, so the
chrome around them stays still and quiet on purpose.
Locks (one each, applied everywhere):
Theme dark only. A bright page reflects off the signer and
washes out the very hand the model has to read.
Accent amber. Semantic red for failure. Nothing else.
Radius panels 18px / controls 10px / pills full.
Numbers always Geist Mono. Text always Geist.
============================================================ */
:root {
/* Ground. Near-black, very slightly warm, never #000. */
--bg: #0a0a0b;
--surface: #121213;
--surface-2: #17171a;
--surface-3: #1e1e22;
--line: #26262b;
--line-bright: #37373e;
--text: #f2f1ee;
--text-dim: #9c9a95;
--text-mute: #6b6963;
/* Single accent. Live state, focus, fill, active control. */
--accent: #f0a53f;
--accent-soft: color-mix(in oklab, var(--accent) 16%, transparent);
--accent-line: color-mix(in oklab, var(--accent) 38%, transparent);
--accent-text: #ffcb84;
/* Semantic failure only. Never decorative. */
--danger: #e2574a;
--danger-soft: color-mix(in oklab, var(--danger) 14%, transparent);
--danger-line: color-mix(in oklab, var(--danger) 36%, transparent);
/* One radius system. */
--r-panel: 18px;
--r-ctrl: 10px;
--r-pill: 999px;
/* Motion. Feedback only, so short and flat. */
--dur: 180ms;
--dur-slow: 420ms;
--ease: cubic-bezier(0.2, 0, 1, 1);
--focus: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);
--font: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
--mono: "Geist Mono", ui-monospace, "SF Mono", "JetBrains Mono", monospace;
}
/* ── Light Mode Palette ──────────────────────────────────────────────── */
:root[data-theme="light"],
[data-theme="light"] {
--bg: #f4f5f8;
--surface: #ffffff;
--surface-2: #eceef3;
--surface-3: #e1e4ec;
--line: #d5d8e2;
--line-bright: #b8bdcb;
--text: #141518;
--text-dim: #4e525d;
--text-mute: #7d8291;
--accent: #d97706;
--accent-soft: color-mix(in oklab, var(--accent) 14%, transparent);
--accent-line: color-mix(in oklab, var(--accent) 40%, transparent);
--accent-text: #92400e;
--danger: #dc2626;
--danger-soft: color-mix(in oklab, var(--danger) 14%, transparent);
--danger-line: color-mix(in oklab, var(--danger) 38%, transparent);
}
/* Streak fill, registered so the dial can interpolate instead of jumping. */
@property --streak {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
color-scheme: dark;
}
html[data-theme="light"] {
color-scheme: light;
}
body {
height: 100dvh;
overflow: hidden;
display: flex;
flex-direction: column;
background: var(--bg);
color: var(--text);
font-family: var(--font);
font-size: 14px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
/* Every numeral in the UI is tabular mono, so live values do not
reflow their neighbours as they tick. */
.detected-letter, .streak-label, .field-value, .step-n,
kbd, .word-chip, .cam-error-code {
font-family: var(--mono);
font-variant-numeric: tabular-nums;
}
::selection { background: var(--accent-soft); color: var(--text); }
:where(button, input, [popovertarget]):focus-visible {
outline: none;
box-shadow: var(--focus);
}
/* ── Top bar ───────────────────────────────────────────────────────────
Fixed 64px. Three zones, single line, never wraps. */
.topbar {
flex: none;
height: 64px;
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
gap: 16px;
padding-inline: 20px;
border-bottom: 1px solid var(--line);
background: var(--surface);
}
.brand { display: flex; align-items: center; gap: 10px; min-width: 0; }
.brand-mark { width: 18px; height: 18px; fill: var(--accent); flex: none; }
.brand-name {
font-size: 0.95rem; font-weight: 600; letter-spacing: -0.01em;
white-space: nowrap;
}
.topbar-right {
display: flex; align-items: center; justify-content: flex-end;
gap: 8px; min-width: 0;
}
/* ── Mode toggle ───────────────────────────────────────────────────── */
.mode-toggle {
position: relative;
display: flex;
padding: 3px;
gap: 2px;
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-pill);
}
.mode-btn {
position: relative; z-index: 2;
flex: 1 1 0;
min-width: 72px;
padding: 6px 14px;
text-align: center;
border: none; background: none;
border-radius: var(--r-pill);
font-family: var(--font);
font-size: 0.78rem; font-weight: 600; letter-spacing: 0.04em;
color: var(--text-mute);
cursor: pointer;
transition: color var(--dur) var(--ease);
}
.mode-btn:hover { color: var(--text-dim); }
.mode-btn.active { color: #23180a; }
.mode-slider {
position: absolute; z-index: 1;
top: 3px; left: 3px;
width: calc((100% - 12px) / 4); height: calc(100% - 6px);
background: var(--accent);
border-radius: var(--r-pill);
transition: transform var(--dur-slow) var(--ease);
}
.mode-toggle.isl-mode .mode-slider { transform: translateX(calc(100% + 2px)); }
.mode-toggle.visually-mode .mode-slider { transform: translateX(calc(200% + 4px)); }
.mode-toggle.upload-mode .mode-slider { transform: translateX(calc(300% + 6px)); }
.hidden,
.hidden * {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
}
/* ── Status pill ───────────────────────────────────────────────────── */
.status-pill {
display: flex; align-items: center; gap: 7px;
padding: 5px 12px 5px 10px;
border: 1px solid var(--line);
border-radius: var(--r-pill);
background: var(--surface-2);
font-size: 0.75rem; font-weight: 500;
color: var(--text-dim);
white-space: nowrap;
}
.status-dot {
width: 6px; height: 6px; border-radius: 50%;
background: var(--text-mute);
flex: none;
}
.status-pill.loading .status-dot { background: var(--accent); }
.status-pill.ready,
.status-pill.ok {
color: var(--accent-text);
border-color: var(--accent-line);
background: var(--accent-soft);
}
.status-pill.ready .status-dot,
.status-pill.ok .status-dot { background: var(--accent); }
.status-pill.err {
color: var(--danger);
border-color: var(--danger-line);
background: var(--danger-soft);
}
.status-pill.err .status-dot { background: var(--danger); }
/* ── Workspace ─────────────────────────────────────────────────────────
Stage carries the weight, rail is a fixed-ish column beside it. */
.workspace {
flex: 1;
display: grid;
grid-template-columns: minmax(0, 1.55fr) minmax(330px, 0.85fr);
gap: 18px;
padding: 18px 20px;
align-items: stretch;
min-height: 0;
overflow: hidden;
}
/* ── Stage ─────────────────────────────────────────────────────────── */
.stage {
display: flex;
flex-direction: column;
gap: 14px;
min-width: 0;
min-height: 0;
}
.viewport {
position: relative;
flex: 1;
min-height: 0;
aspect-ratio: 4 / 3;
width: auto;
max-width: 100%;
margin-inline: auto;
overflow: hidden;
background: #000;
border: 1px solid var(--line);
border-radius: var(--r-panel);
}
@supports (corner-shape: squircle) {
.viewport, .panel, .sheet { corner-shape: squircle; }
}
#webcam-video {
position: absolute;
top: 0;
left: 0;
width: 1px;
height: 1px;
opacity: 0;
pointer-events: none;
z-index: -1;
}
#display-canvas {
display: block;
width: 100%; height: 100%;
object-fit: contain;
transition: transform var(--dur) var(--ease);
}
#display-canvas.mirrored {
transform: scaleX(-1);
}
/* ── Idle / error overlay ──────────────────────────────────────────────
app.js toggles `.visible` for idle and `.error` for camera failure. */
.no-hand-overlay {
position: absolute; inset: 0;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
gap: 6px;
padding: 0 32px;
text-align: center;
background: color-mix(in oklab, var(--bg) 72%, transparent);
opacity: 0;
pointer-events: none;
transition: opacity var(--dur-slow) var(--ease);
}
.no-hand-overlay.visible { opacity: 1; }
.no-hand-overlay.hidden { opacity: 0; }
.idle-title { font-size: 0.95rem; font-weight: 500; color: var(--text); }
.idle-sub { font-size: 0.8rem; color: var(--text-mute); text-wrap: pretty; }
/* Camera failure. Replaces the native alert() camera_utils would raise. */
.no-hand-overlay.error {
opacity: 1;
gap: 10px;
background: color-mix(in oklab, var(--bg) 94%, transparent);
backdrop-filter: blur(6px);
pointer-events: auto;
}
.cam-error-icon {
width: 34px; height: 34px;
display: grid; place-items: center;
border-radius: var(--r-pill);
background: var(--danger-soft);
border: 1px solid var(--danger-line);
color: var(--danger);
font-size: 1rem;
}
.cam-error-title { font-size: 1rem; font-weight: 600; }
.cam-error-msg {
font-size: 0.83rem; line-height: 1.55;
color: var(--text-dim);
max-width: 46ch;
text-wrap: pretty;
}
.cam-error-code {
margin-top: 2px;
padding: 3px 9px;
font-size: 0.68rem; letter-spacing: 0.06em;
color: var(--danger);
background: var(--danger-soft);
border: 1px solid var(--danger-line);
border-radius: var(--r-pill);
}
/* ── Readout ───────────────────────────────────────────────────────────
The dial is the primary affordance: current letter in the middle,
capture progress as the ring around it. */
.readout {
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
align-items: center;
gap: 22px;
flex: none;
padding: 14px 16px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-panel);
transition: border-color var(--dur) var(--ease);
}
/* Only light the panel when tracking is actually live. */
.readout:has(.hand-badge.live) { border-color: var(--accent-line); }
.readout-dial {
position: relative;
display: grid; place-items: center;
width: 74px; height: 74px;
flex: none;
}
.dial-ring {
position: absolute; inset: 0;
border-radius: 50%;
/* --streak is written by app.js alongside the bar width. */
background: conic-gradient(
var(--accent) calc(var(--streak, 0) * 1%),
var(--surface-3) 0
);
mask: radial-gradient(closest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
transition: --streak var(--dur) linear;
}
.detected-letter {
font-size: 2.1rem; font-weight: 600; line-height: 1;
letter-spacing: -0.02em;
color: var(--text);
}
/* Null state: a dimmed placeholder, so the dial never collapses. */
.detected-letter:empty::after {
content: "·";
color: var(--text-mute);
}
.detected-letter.flash { animation: capture 420ms var(--ease); }
@keyframes capture {
0% { transform: scale(1); color: var(--text); }
30% { transform: scale(1.16); color: var(--accent); }
100% { transform: scale(1); color: var(--text); }
}
.readout-body {
display: flex; flex-direction: column; gap: 9px;
min-width: 0; max-width: 340px;
}
.readout-line { display: flex; align-items: center; gap: 10px; }
.detected-sub {
font-size: 0.82rem; color: var(--text-dim);
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hand-badge {
flex: none;
padding: 3px 9px;
border-radius: var(--r-pill);
border: 1px solid var(--line-bright);
background: var(--surface-2);
font-size: 0.63rem; font-weight: 600; letter-spacing: 0.09em;
color: var(--text-mute);
transition: color var(--dur) var(--ease),
background-color var(--dur) var(--ease),
border-color var(--dur) var(--ease);
}
.hand-badge.live,
.hand-badge.detected {
color: var(--accent-text);
background: var(--accent-soft);
border-color: var(--accent-line);
}
.streak-row { display: flex; align-items: center; gap: 10px; }
.streak-track {
flex: 1;
height: 3px;
background: var(--surface-3);
border-radius: var(--r-pill);
overflow: hidden;
}
.streak-fill {
height: 100%; width: 0;
background: var(--accent);
border-radius: inherit;
transition: width var(--dur) linear;
}
.streak-label { font-size: 0.7rem; color: var(--text-mute); flex: none; }
.stage-actions { display: flex; gap: 8px; flex: none; }
/* ── Controls ──────────────────────────────────────────────────────── */
.ctrl-btn, .btn, .ghost-btn {
font-family: var(--font);
font-size: 0.8rem; font-weight: 500;
color: var(--text-dim);
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
padding: 8px 14px;
cursor: pointer;
white-space: nowrap;
transition: color var(--dur) var(--ease),
background-color var(--dur) var(--ease),
border-color var(--dur) var(--ease),
transform var(--dur) var(--ease);
}
.ctrl-btn:hover, .btn:hover, .ghost-btn:hover {
color: var(--text);
background: var(--surface-3);
border-color: var(--line-bright);
}
.ctrl-btn:active, .btn:active, .ghost-btn:active { transform: scale(0.98); }
.ghost-btn { background: none; border-color: transparent; padding: 7px 11px; }
/* Pause / Stop Camera when engaged. Amber = a live control is on. */
.ctrl-btn.active-btn {
color: var(--accent-text);
background: var(--accent-soft);
border-color: var(--accent-line);
}
.btn-sm { padding: 5px 11px; font-size: 0.74rem; }
.btn-quiet { color: var(--text-mute); }
.btn-danger {
width: 100%;
margin-top: 2px;
color: var(--danger);
background: var(--danger-soft);
border-color: var(--danger-line);
}
.btn-danger:hover {
color: #fff;
background: var(--danger);
border-color: var(--danger);
}
/* ── Rail ──────────────────────────────────────────────────────────────
Panels size against the rail's own width, not the viewport, so the
layout holds wherever the rail ends up. */
.rail {
container-type: inline-size;
container-name: rail;
display: flex;
flex-direction: column;
gap: 14px;
min-width: 0;
min-height: 0;
overflow-y: auto;
}
.panel-grow { flex: 1; min-height: 0; }
.panel-grow .sentence-display { flex: 1; overflow-y: auto; }
.panel {
display: flex;
flex-direction: column;
gap: 12px;
padding: 16px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-panel);
}
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.panel-title {
font-size: 0.68rem; font-weight: 600;
letter-spacing: 0.11em; text-transform: uppercase;
color: var(--text-mute);
}
.panel-head-actions { display: flex; gap: 6px; }
.word-display {
min-height: 62px;
display: flex; align-items: center;
padding: 10px 14px;
background: var(--bg);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
font-family: var(--mono);
font-size: 1.6rem; font-weight: 500;
letter-spacing: 0.1em;
word-break: break-all;
}
.sentence-display {
min-height: 74px;
padding: 12px 14px;
background: var(--bg);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
font-size: 1rem; line-height: 1.55;
text-wrap: pretty;
}
.ph { color: var(--text-mute); font-style: normal; letter-spacing: 0; font-size: 0.85rem; }
.panel-actions { display: flex; gap: 7px; }
.panel-actions .btn { flex: 1; padding-inline: 8px; }
/* Chip row only earns its margin once there are chips in it. */
.word-chips { display: none; flex-wrap: wrap; gap: 6px; }
#sentence-panel:has(.word-chip) .word-chips { display: flex; }
.word-chip {
padding: 3px 9px;
background: var(--surface-3);
border: 1px solid var(--line-bright);
border-radius: var(--r-pill);
font-size: 0.72rem;
color: var(--text-dim);
animation: chip-in 220ms var(--ease);
}
@keyframes chip-in {
from { opacity: 0; transform: translateY(3px); }
to { opacity: 1; transform: none; }
}
/* Narrow rail: actions stack rather than crushing their labels. */
@container rail (max-width: 300px) {
.panel-actions { flex-wrap: wrap; }
.panel-actions .btn { flex: 1 1 100%; }
.word-display { font-size: 1.3rem; }
}
/* ── Sheets (Popover API, top layer) ──────────────────────────────────
Popover keeps these out of the z-index stack entirely, and gives
light-dismiss plus Esc for free. */
/* Native popovers: strictly hide them when not open so they never occupy space or bleed into live view */
.sheet:not(:popover-open),
[popover]:not(:popover-open) {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
opacity: 0 !important;
}
.sheet {
width: min(420px, calc(100vw - 32px));
padding: 18px;
border: 1px solid var(--line-bright);
border-radius: var(--r-panel);
background: var(--surface);
color: var(--text);
inset: auto;
position: fixed;
top: 70px; right: 20px;
margin: 0;
display: none;
opacity: 0;
transform: translateY(-6px) scale(0.98);
transition-property: opacity, transform, display, overlay;
transition-duration: var(--dur);
transition-timing-function: var(--ease);
transition-behavior: allow-discrete;
}
.sheet:popover-open,
.sheet.open {
display: flex !important;
flex-direction: column;
visibility: visible !important;
pointer-events: auto !important;
opacity: 1 !important;
transform: none !important;
@starting-style {
opacity: 0 !important;
transform: translateY(-6px) scale(0.98) !important;
}
}
.sheet::backdrop {
background: color-mix(in oklab, var(--bg) 55%, transparent);
opacity: 0;
transition-property: opacity, display, overlay;
transition-duration: var(--dur);
transition-behavior: allow-discrete;
}
.sheet:popover-open::backdrop {
opacity: 1;
@starting-style { opacity: 0; }
}
.sheet-head {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: 16px;
}
.sheet-title { font-size: 0.95rem; font-weight: 600; }
/* ── Fields ────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: 7px; }
.field + .field { margin-top: 18px; }
.field label { font-size: 0.82rem; font-weight: 500; color: var(--text); }
.field-row { display: flex; align-items: center; gap: 12px; }
.field-value {
min-width: 44px; text-align: right;
font-size: 0.82rem; color: var(--accent-text);
}
.field-help { font-size: 0.76rem; color: var(--text-mute); text-wrap: pretty; }
input[type="range"] {
flex: 1;
accent-color: var(--accent);
height: 18px;
cursor: pointer;
}
/* ── Steps and keys ────────────────────────────────────────────────── */
.steps { list-style: none; display: flex; flex-direction: column; gap: 10px; }
.steps li {
display: flex; align-items: baseline; gap: 10px;
font-size: 0.85rem; color: var(--text-dim);
text-wrap: pretty;
}
.step-n {
flex: none;
width: 20px; height: 20px;
display: grid; place-items: center;
border-radius: var(--r-pill);
background: var(--accent-soft);
border: 1px solid var(--accent-line);
color: var(--accent-text);
font-size: 0.68rem;
}
.keys {
margin-top: 18px; padding-top: 16px;
border-top: 1px solid var(--line);
display: flex; flex-direction: column; gap: 8px;
}
.key-row { display: flex; align-items: center; gap: 10px; font-size: 0.8rem; color: var(--text-dim); }
kbd {
min-width: 26px;
padding: 2px 7px;
background: var(--surface-3);
border: 1px solid var(--line-bright);
border-bottom-width: 2px;
border-radius: 6px;
font-size: 0.7rem;
color: var(--text);
text-align: center;
}
/* ── Toast ─────────────────────────────────────────────────────────── */
.toast {
position: fixed;
bottom: 22px; left: 50%;
padding: 9px 18px;
background: var(--surface-3);
border: 1px solid var(--line-bright);
border-radius: var(--r-pill);
font-size: 0.82rem;
color: var(--text);
box-shadow: 0 8px 28px rgb(0 0 0 / 0.45);
opacity: 0;
transform: translateX(-50%) translateY(10px);
pointer-events: none;
transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* ── Responsive ────────────────────────────────────────────────────── */
@media (max-width: 1000px) {
body { height: auto; min-height: 100dvh; overflow-y: auto; overflow-x: hidden; }
.workspace { grid-template-columns: minmax(0, 1fr); overflow: visible; }
.rail { overflow: visible; }
.viewport { flex: none; width: 100%; }
/* Practice Studio (VISUALLY) on tablet/mobile: 3D Avatar at TOP, controls BELOW */
.visually-workspace {
display: flex !important;
flex-direction: column !important;
grid-template-columns: minmax(0, 1fr) !important;
overflow: visible !important;
gap: 14px;
}
.visually-workspace .practice-stage {
order: -1 !important; /* Move 3D Avatar to the top */
width: 100%;
flex: none;
}
.visually-workspace .practice-input-rail {
order: 1 !important; /* Move controls & timeline below */
width: 100%;
overflow: visible;
}
.avatar-viewport {
min-height: 340px;
height: 48vh;
max-height: 460px;
}
}
@media (max-width: 768px) {
/* Prevent horizontal blowout & enable smooth native vertical touch scrolling */
html, body {
height: auto !important;
min-height: 100% !important;
overflow-y: auto !important;
overflow-x: hidden !important;
max-width: 100vw;
-webkit-overflow-scrolling: touch !important;
}
/* ── Top Bar on Mobile ─────────────────────────────────────────── */
.topbar {
height: auto;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 8px 10px;
position: relative;
z-index: 50;
}
.brand {
gap: 6px;
flex: 0 0 auto;
}
.brand-name {
display: inline;
font-size: 0.88rem;
font-weight: 700;
}
.brand-mark {
width: 16px;
height: 16px;
}
/* Right-side quick controls */
.topbar-right {
display: flex;
align-items: center;
gap: 4px;
flex: 1 1 auto;
justify-content: flex-end;
min-width: 0;
}
.ghost-btn {
padding: 5px 8px;
font-size: 0.74rem;
white-space: nowrap;
flex-shrink: 0;
}
.guide-btn svg {
margin-right: 2px;
}
/* Hide verbose guide text on mobile topbar to avoid crowding the row */
.topbar-right .guide-btn span {
display: inline;
}
.status-pill {
font-size: 0.68rem;
padding: 4px 7px;
gap: 4px;
flex-shrink: 0;
}
/* Mode Toggle spans full width on row 2 */
.topbar .mode-toggle {
order: 3;
width: 100%;
margin-top: 2px;
display: flex;
}
.mode-btn {
flex: 1;
min-width: 0;
padding: 7px 10px;
font-size: 0.75rem;
text-align: center;
}
/* ── Workspace General ─────────────────────────────────────────── */
.workspace {
padding: 10px 12px 20px;
gap: 12px;
grid-template-columns: minmax(0, 1fr) !important;
overflow: visible;
}
/* ── Live Camera Stage ─────────────────────────────────────────── */
.stage {
gap: 10px;
}
.viewport {
aspect-ratio: 4 / 3;
max-height: 52vh;
border-radius: 14px;
}
/* Readout panel */
.readout {
display: grid;
grid-template-columns: auto minmax(0, 1fr);
gap: 12px;
padding: 12px;
border-radius: 14px;
}
.readout-dial {
width: 58px;
height: 58px;
}
.detected-letter {
font-size: 1.65rem;
}
.readout-body {
max-width: 100%;
gap: 6px;
}
.readout-line {
gap: 8px;
flex-wrap: wrap;
}
.detected-sub {
font-size: 0.76rem;
}
.hand-badge {
padding: 2px 7px;
font-size: 0.6rem;
}
/* Stage action buttons (Guide / Pause / Stop Camera) full width row */
.stage-actions {
grid-column: 1 / -1;
display: flex;
width: 100%;
gap: 6px;
}
.stage-actions .ctrl-btn {
flex: 1;
min-width: 0;
padding: 8px 6px;
font-size: 0.76rem;
text-align: center;
}
/* ── Output Rail (Word & Sentence Panels) ───────────────────────── */
.rail {
gap: 10px;
overflow: visible;
}
.panel {
padding: 12px;
gap: 10px;
border-radius: 14px;
}
.word-display {
min-height: 52px;
font-size: 1.3rem;
padding: 8px 12px;
}
.panel-actions {
gap: 6px;
}
.panel-actions .btn {
padding: 8px 6px;
font-size: 0.75rem;
}
.sentence-display {
min-height: 64px;
font-size: 0.92rem;
padding: 10px 12px;
}
/* ── VISUALLY (Practice Studio) on Mobile ───────────────────────── */
.visually-workspace {
grid-template-columns: minmax(0, 1fr) !important;
padding: 10px 12px 24px;
gap: 14px;
}
.practice-input-rail {
width: 100%;
overflow: visible;
}
.practice-panel {
gap: 12px;
padding: 12px;
border-radius: 14px;
}
.practice-panel .panel-head {
flex-wrap: wrap;
gap: 8px;
}
.practice-head-title {
flex: 1;
min-width: 120px;
}
.practice-dialect-toggle {
flex: none;
}
.dialect-pill {
padding: 4px 12px;
font-size: 0.75rem;
}
.practice-textarea-box {
padding: 10px;
gap: 8px;
}
.practice-textarea-box textarea {
font-size: 0.88rem;
rows: 3;
}
.practice-input-tools {
flex-wrap: wrap;
gap: 6px;
}
.tool-btn {
padding: 5px 8px;
font-size: 0.72rem;
}
/* Quick samples horizontal scroll */
.quick-samples {
gap: 5px;
overflow-x: auto;
flex-wrap: nowrap;
padding-bottom: 4px;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
}
.quick-samples::-webkit-scrollbar {
display: none;
}
.sample-chip {
flex: none;
padding: 4px 9px;
font-size: 0.7rem;
}
/* Practice Action Row (Demonstrate Sign + Speed) */
.practice-action-row {
flex-direction: column;
align-items: stretch;
gap: 8px;
}
.btn-demo {
width: 100%;
justify-content: center;
padding: 10px 14px;
font-size: 0.85rem;
}
.speed-control {
justify-content: center;
width: 100%;
padding: 4px;
}
.speed-btn {
flex: 1;
padding: 5px 8px;
text-align: center;
}
/* Sequence Timeline */
.sequence-chips {
min-height: 72px;
max-height: 120px;
padding: 8px;
gap: 4px;
}
.sequence-chip {
min-width: 28px;
height: 28px;
font-size: 0.78rem;
padding: 0 6px;
}
/* Practice 3D Avatar Stage on Mobile: Avatar at TOP, Controls BELOW */
.visually-workspace {
display: flex !important;
flex-direction: column !important;
padding: 10px 12px 24px !important;
gap: 12px !important;
overflow: visible !important;
height: auto !important;
min-height: auto !important;
}
.visually-workspace .practice-stage {
order: -1 !important; /* Move 3D Avatar to the very top */
width: 100% !important;
height: auto !important;
margin-bottom: 4px !important;
}
.visually-workspace .practice-input-rail {
order: 1 !important; /* Controls, text input, timeline placed below */
width: 100% !important;
overflow: visible !important;
}
.avatar-viewport {
min-height: 290px !important;
height: 42vh !important;
max-height: 380px !important;
border-radius: 14px;
position: relative;
overflow: hidden;
touch-action: pan-y !important;
}
#avatar-canvas-3d,
#avatar-canvas {
touch-action: pan-y !important;
}
.hud-letter-char {
font-size: 1.65rem !important;
}
.hud-letter-sub {
font-size: 0.66rem !important;
}
.hud-letter-cue {
display: none !important;
}
.avatar-hud-letter {
top: 10px;
left: 12px;
z-index: 5;
max-width: 55%;
pointer-events: none;
}
.avatar-hud-status {
top: 10px !important;
right: 10px !important;
padding: 3px 8px !important;
font-size: 0.65rem !important;
z-index: 10 !important;
}
/* Sign Reference Card placed cleanly in top-right of Avatar on Mobile (sitting below status badge, NO overlap!) */
.avatar-sign-preview {
top: 42px !important;
bottom: auto !important;
right: 10px !important;
left: auto !important;
width: 82px !important;
max-height: 115px !important;
height: auto !important;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45) !important;
z-index: 8 !important;
border-radius: 10px !important;
overflow: hidden !important;
}
.avatar-sign-img-wrap {
width: 100% !important;
height: 60px !important;
aspect-ratio: auto !important;
background: #000;
}
.avatar-sign-info {
padding: 2px 5px 3px !important;
}
.avatar-sign-char {
font-size: 0.74rem !important;
}
.avatar-sign-hands {
font-size: 0.55rem !important;
padding: 1px 3px !important;
}
.avatar-sign-desc {
display: none !important;
}
/* Floating controls bar in avatar viewport on mobile */
.avatar-controls-bar {
min-width: 0 !important;
width: calc(100% - 16px) !important;
max-width: calc(100% - 16px) !important;
bottom: 8px !important;
padding: 4px 8px !important;
gap: 6px !important;
z-index: 10 !important;
}
.avatar-ctrl-btn {
width: 28px !important;
height: 28px !important;
font-size: 0.72rem !important;
}
.avatar-scrubber {
height: 4px !important;
}
/* ── Sheets & Modals on Mobile ─────────────────────────────────── */
.sheet {
top: auto !important;
bottom: 10px !important;
right: 10px !important;
left: 10px !important;
width: calc(100vw - 20px) !important;
max-height: 85vh;
border-radius: 16px;
padding: 14px;
transform: none !important;
}
/* Crucial: Sign Guide wide modal centered & full size on mobile */
.sheet.sheet-wide,
#panel-guide.sheet.sheet-wide {
position: fixed !important;
inset: 12px !important;
top: 12px !important;
left: 12px !important;
right: 12px !important;
bottom: 12px !important;
width: auto !important;
max-width: none !important;
height: auto !important;
max-height: none !important;
transform: none !important;
border-radius: 18px !important;
box-shadow: 0 16px 60px rgba(0, 0, 0, 0.6) !important;
z-index: 9999 !important;
}
.sheet.sheet-wide:popover-open,
.sheet.sheet-wide.open,
#panel-guide.sheet.sheet-wide:popover-open,
#panel-guide.sheet.sheet-wide.open {
display: flex !important;
flex-direction: column !important;
transform: none !important;
}
.sheet-wide .sheet-head {
padding: 14px 16px;
flex-wrap: wrap;
gap: 8px;
border-bottom: 1px solid var(--line);
}
.sheet-title-group {
flex: 1;
min-width: 140px;
}
.sheet-title-group .sheet-title {
font-size: 1.05rem;
}
.sheet-sub {
font-size: 0.72rem;
}
.guide-tabs {
width: 100%;
order: 3;
display: flex;
}
.guide-tab-btn {
flex: 1;
justify-content: center;
padding: 7px 10px;
font-size: 0.74rem;
}
.guide-tab-content {
padding: 12px 14px 20px;
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.guide-cards-grid {
grid-template-columns: repeat(auto-fill, minmax(95px, 1fr));
gap: 8px;
}
.guide-card-char {
font-size: 0.95rem;
}
.guide-card-desc {
font-size: 0.68rem;
padding: 4px 6px 6px;
}
/* Sign Reference Lightbox Dialog on Mobile */
.sign-lightbox {
padding: 20px 16px 16px;
width: calc(100vw - 24px);
max-width: calc(100vw - 24px);
}
}
@media (max-width: 400px) {
/* Extra-compact phones (iPhone SE, narrow Android) */
.topbar {
padding: 6px 8px;
gap: 6px;
}
.brand-name {
font-size: 0.82rem;
}
.ghost-btn {
padding: 4px 6px;
font-size: 0.68rem;
}
.status-pill {
padding: 3px 6px;
font-size: 0.64rem;
}
.mode-btn {
font-size: 0.7rem;
padding: 6px 4px;
}
.readout-dial {
width: 50px;
height: 50px;
}
.detected-letter {
font-size: 1.45rem;
}
.guide-cards-grid {
grid-template-columns: repeat(2, 1fr);
}
.avatar-sign-preview {
width: 76px !important;
top: 40px !important;
bottom: auto !important;
}
}
/* ── Reduced motion ────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
}
}
/* ── Reduced transparency ──────────────────────────────────────────── */
@media (prefers-reduced-transparency: reduce) {
.no-hand-overlay, .no-hand-overlay.error { backdrop-filter: none; background: var(--bg); }
}
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-thumb { background: var(--line-bright); border-radius: var(--r-pill); }
/* ══════════════════════════════════════════════════════════════════════
VISUALLY — Practice Studio
Interactive 3D avatar & gesture synthesizer matching RyloTranslate.
══════════════════════════════════════════════════════════════════════ */
.visually-workspace {
grid-template-columns: minmax(380px, 0.95fr) minmax(0, 1.45fr);
}
.practice-input-rail {
display: flex;
flex-direction: column;
gap: 14px;
min-width: 0;
min-height: 0;
overflow: visible;
}
.practice-panel {
display: flex;
flex-direction: column;
gap: 16px;
overflow: visible;
}
.practice-head-title {
display: flex;
flex-direction: column;
gap: 4px;
}
.practice-badge {
display: inline-block;
align-self: flex-start;
padding: 2px 8px;
font-family: var(--mono);
font-size: 0.68rem;
font-weight: 600;
letter-spacing: 0.08em;
color: var(--accent-text);
background: var(--accent-soft);
border: 1px solid var(--accent-line);
border-radius: var(--r-pill);
}
.practice-dialect-toggle {
display: flex;
gap: 4px;
background: var(--surface-3);
padding: 3px;
border-radius: var(--r-pill);
border: 1px solid var(--line);
position: relative;
z-index: 20;
}
.dialect-pill {
position: relative;
z-index: 21;
padding: 5px 16px;
min-height: 28px;
border-radius: var(--r-pill);
border: none;
background: transparent;
font-family: var(--mono);
font-size: 0.8rem;
font-weight: 600;
color: var(--text-dim);
cursor: pointer;
user-select: none;
touch-action: manipulation;
transition: all var(--dur) var(--ease);
}
.dialect-pill:hover {
color: var(--text);
}
.dialect-pill.active {
background: var(--accent);
color: #23180a;
}
/* Textarea & Tools */
.practice-textarea-box {
display: flex;
flex-direction: column;
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
padding: 12px;
gap: 10px;
transition: border-color var(--dur) var(--ease);
}
.practice-textarea-box:focus-within {
border-color: var(--accent-line);
box-shadow: 0 0 0 1px var(--accent-line);
}
.practice-textarea-box textarea {
width: 100%;
background: transparent;
border: none;
color: var(--text);
font-family: var(--font);
font-size: 0.95rem;
line-height: 1.5;
resize: none;
outline: none;
}
.practice-textarea-box textarea::placeholder {
color: var(--text-mute);
}
.practice-input-tools {
display: flex;
align-items: center;
gap: 8px;
padding-top: 8px;
border-top: 1px solid var(--line);
}
.tool-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 5px 10px;
background: var(--surface-3);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
font-family: var(--font);
font-size: 0.78rem;
font-weight: 500;
color: var(--text-dim);
cursor: pointer;
transition: all var(--dur) var(--ease);
}
.tool-btn:hover {
color: var(--text);
border-color: var(--line-bright);
}
.tool-btn .icon {
width: 15px;
height: 15px;
flex: none;
}
.mic-btn.listening {
background: var(--danger-soft);
color: var(--danger);
border-color: var(--danger-line);
animation: pulse-mic 1.2s infinite ease-in-out;
}
@keyframes pulse-mic {
0%, 100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--danger) 40%, transparent); }
50% { box-shadow: 0 0 0 6px transparent; }
}
.char-count {
margin-left: auto;
font-family: var(--mono);
font-size: 0.72rem;
color: var(--text-mute);
}
/* Quick Samples */
.quick-samples {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 6px;
}
.quick-label {
font-size: 0.75rem;
color: var(--text-mute);
margin-right: 2px;
}
.sample-chip {
padding: 3px 9px;
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-pill);
font-family: var(--mono);
font-size: 0.72rem;
color: var(--text-dim);
cursor: pointer;
transition: all var(--dur) var(--ease);
}
.sample-chip:hover {
color: var(--accent-text);
border-color: var(--accent-line);
background: var(--accent-soft);
}
/* Main Action Row */
.practice-action-row {
display: flex;
align-items: center;
gap: 12px;
}
.btn-demo {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 18px;
font-weight: 600;
}
.icon-play {
width: 16px;
height: 16px;
}
.speed-control {
display: flex;
align-items: center;
gap: 4px;
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
padding: 3px;
}
.speed-label {
font-size: 0.72rem;
color: var(--text-mute);
padding-inline: 6px 2px;
}
.speed-btn {
padding: 3px 8px;
background: transparent;
border: none;
border-radius: 6px;
font-family: var(--mono);
font-size: 0.72rem;
color: var(--text-dim);
cursor: pointer;
transition: all var(--dur) var(--ease);
}
.speed-btn:hover {
color: var(--text);
}
.speed-btn.active {
background: var(--surface-3);
color: var(--accent);
font-weight: 600;
}
/* Sequence Timeline */
.sequence-section {
display: flex;
flex-direction: column;
gap: 8px;
flex: 1;
min-height: 0;
overflow: hidden;
}
.sequence-head {
display: flex;
justify-content: space-between;
align-items: center;
}
.seq-title {
font-size: 0.78rem;
font-weight: 600;
color: var(--text-dim);
letter-spacing: 0.02em;
}
.seq-counter {
font-family: var(--mono);
font-size: 0.72rem;
color: var(--text-mute);
}
.sequence-chips {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
gap: 6px;
padding: 10px;
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
min-height: 100px;
max-height: 180px;
overflow-y: auto;
}
.sequence-chips .ph {
color: var(--text-mute);
font-size: 0.8rem;
align-self: center;
margin: auto;
}
.sequence-chip {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 32px;
height: 32px;
padding: 0 8px;
background: var(--surface-3);
border: 1px solid var(--line-bright);
border-radius: 8px;
font-family: var(--mono);
font-size: 0.88rem;
font-weight: 600;
color: var(--text);
cursor: pointer;
transition: all var(--dur) var(--ease);
}
.sequence-chip:hover {
border-color: var(--accent-line);
color: var(--accent-text);
}
.sequence-chip.is-space {
min-width: 22px;
background: transparent;
border-style: dashed;
color: var(--text-mute);
font-size: 0.65rem;
}
.sequence-chip.active {
background: var(--accent-soft);
border-color: var(--accent);
color: var(--accent-text);
box-shadow: 0 0 12px color-mix(in oklab, var(--accent) 35%, transparent);
transform: scale(1.08);
}
/* ── Practice Avatar Stage ─────────────────────────────────────────────── */
.practice-stage {
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
height: 100%;
}
.avatar-viewport {
position: relative;
flex: 1;
width: 100%;
height: 100%;
min-height: 480px;
background: #161619;
border: 1px solid var(--line);
border-radius: var(--r-panel);
overflow: hidden;
}
#avatar-canvas-3d,
#avatar-canvas {
position: absolute;
inset: 0;
display: block;
width: 100%;
height: 100%;
}
#avatar-canvas-3d {
z-index: 1;
}
#avatar-canvas {
z-index: 2;
pointer-events: none;
}
/* 3D Avatar Loading Indicator Overlay */
.avatar-3d-loading-overlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: color-mix(in oklab, var(--bg-card, #161619) 92%, transparent);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
z-index: 6;
opacity: 1;
visibility: visible;
transition: opacity 0.4s ease, visibility 0.4s ease;
pointer-events: auto;
}
.avatar-3d-loading-overlay.loaded {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.avatar-loading-box {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
max-width: 380px;
width: 100%;
padding: 28px 24px;
border-radius: var(--r-panel, 14px);
background: var(--bg-card, #1a1a1f);
border: 1px solid var(--line, rgba(255, 255, 255, 0.1));
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}
.avatar-loading-spinner-ring {
position: relative;
width: 48px;
height: 48px;
margin-bottom: 18px;
border-radius: 50%;
border: 3px solid color-mix(in oklab, var(--accent, #6366f1) 20%, transparent);
border-top-color: var(--accent, #6366f1);
border-right-color: color-mix(in oklab, var(--accent, #6366f1) 60%, transparent);
animation: avatarSpin 1.1s cubic-bezier(0.55, 0.15, 0.45, 0.85) infinite;
}
.avatar-loading-core-dot {
position: absolute;
top: 50%;
left: 50%;
width: 8px;
height: 8px;
margin-top: -4px;
margin-left: -4px;
border-radius: 50%;
background: var(--accent, #6366f1);
box-shadow: 0 0 12px var(--accent, #6366f1);
animation: avatarPulse 1.8s ease-in-out infinite;
}
@keyframes avatarSpin {
to { transform: rotate(360deg); }
}
@keyframes avatarPulse {
0%, 100% { transform: scale(0.85); opacity: 0.6; }
50% { transform: scale(1.35); opacity: 1; }
}
.avatar-loading-title {
font-family: var(--sans, 'Geist', sans-serif);
font-size: 1.05rem;
font-weight: 600;
color: var(--text, #f1f5f9);
letter-spacing: -0.01em;
margin-bottom: 6px;
}
.avatar-loading-subtitle {
font-size: 0.8rem;
color: var(--text-dim, #94a3b8);
margin-bottom: 16px;
line-height: 1.4;
min-height: 1.2rem;
}
.avatar-loading-progress-track {
width: 100%;
height: 5px;
background: color-mix(in oklab, var(--line, rgba(255, 255, 255, 0.1)) 80%, transparent);
border-radius: 999px;
overflow: hidden;
}
.avatar-loading-progress-bar {
width: 25%;
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, var(--accent, #6366f1), #a855f7);
transition: width 0.25s ease-out;
box-shadow: 0 0 8px color-mix(in oklab, var(--accent, #6366f1) 50%, transparent);
}
/* 3D Avatar Model Missing Placeholder Overlay */
.avatar-3d-placeholder {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: color-mix(in oklab, var(--bg-card, #161619) 88%, transparent);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
z-index: 10;
}
.avatar-3d-placeholder .ph-card {
max-width: 440px;
width: 100%;
padding: 24px 28px;
border-radius: var(--r-panel, 14px);
background: var(--bg-card, #1a1a1f);
border: 1px solid var(--line, rgba(255, 255, 255, 0.1));
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.35);
text-align: center;
}
.avatar-3d-placeholder .ph-icon {
font-size: 2.5rem;
margin-bottom: 10px;
}
.avatar-3d-placeholder .ph-title {
font-size: 1.15rem;
font-weight: 600;
color: var(--text, #f1f5f9);
margin-bottom: 8px;
}
.avatar-3d-placeholder .ph-desc {
font-size: 0.85rem;
color: var(--text-dim, #94a3b8);
margin-bottom: 10px;
line-height: 1.45;
}
.avatar-3d-placeholder .ph-path {
display: inline-block;
padding: 6px 12px;
margin-bottom: 12px;
border-radius: 6px;
background: color-mix(in oklab, var(--accent, #6366f1) 15%, transparent);
border: 1px solid color-mix(in oklab, var(--accent, #6366f1) 35%, transparent);
color: var(--accent, #818cf8);
font-family: var(--mono, monospace);
font-size: 0.82rem;
user-select: all;
}
.avatar-3d-placeholder .ph-hint {
font-size: 0.76rem;
color: var(--text-dim, #64748b);
line-height: 1.4;
margin-bottom: 16px;
}
.avatar-3d-placeholder .ph-btn {
padding: 8px 18px;
border-radius: var(--r-ctrl, 8px);
background: color-mix(in oklab, var(--text, #fff) 10%, transparent);
border: 1px solid var(--line, rgba(255, 255, 255, 0.15));
color: var(--text, #f1f5f9);
font-size: 0.82rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.avatar-3d-placeholder .ph-btn:hover {
background: var(--accent, #6366f1);
color: #fff;
border-color: transparent;
}
/* Avatar HUD Badges */
.avatar-hud-letter {
position: absolute;
top: 18px;
left: 20px;
display: flex;
flex-direction: column;
pointer-events: none;
}
.hud-letter-char {
font-family: var(--mono);
font-size: 3.2rem;
font-weight: 700;
line-height: 1;
color: var(--text);
text-shadow: 0 0 20px color-mix(in oklab, var(--accent) 40%, transparent);
}
.hud-letter-sub {
font-size: 0.78rem;
color: var(--text-dim);
margin-top: 4px;
}
.hud-letter-cue {
display: inline-flex;
align-items: center;
gap: 6px;
margin-top: 6px;
padding: 4px 10px;
border-radius: var(--r-ctrl);
background: color-mix(in oklab, var(--accent) 14%, transparent);
border: 1px solid color-mix(in oklab, var(--accent) 30%, transparent);
font-size: 0.76rem;
font-weight: 500;
color: var(--accent);
max-width: 340px;
line-height: 1.35;
backdrop-filter: blur(8px);
}
.avatar-hud-status {
position: absolute;
top: 18px;
right: 20px;
display: flex;
align-items: center;
gap: 7px;
padding: 5px 12px;
border-radius: var(--r-pill);
background: rgb(18 18 19 / 0.85);
backdrop-filter: blur(8px);
border: 1px solid var(--line);
font-family: var(--mono);
font-size: 0.75rem;
color: var(--text-dim);
}
.status-badge-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--text-mute);
}
.avatar-hud-status.playing .status-badge-dot {
background: var(--accent);
box-shadow: 0 0 8px var(--accent);
}
/* ── Top-Right Real Human Sign Preview Reference Card ─────────────────── */
.avatar-sign-preview {
position: absolute;
top: 54px;
right: 20px;
width: 140px;
background: var(--surface);
border: 1px solid var(--line-bright);
border-radius: var(--r-ctrl);
overflow: hidden;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
z-index: 10;
cursor: pointer;
transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.avatar-sign-preview:hover {
transform: translateY(-2px);
border-color: var(--accent);
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
}
.avatar-sign-img-wrap {
width: 100%;
aspect-ratio: 1;
background: #000;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.avatar-sign-img-wrap img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.avatar-sign-badge {
position: absolute;
bottom: 6px;
right: 6px;
padding: 2px 6px;
font-size: 0.65rem;
font-weight: 700;
font-family: var(--mono);
background: rgba(0, 0, 0, 0.75);
backdrop-filter: blur(4px);
color: var(--accent);
border-radius: 4px;
border: 1px solid var(--line-bright);
}
.avatar-sign-info {
padding: 6px 8px 8px;
background: var(--surface-2);
border-top: 1px solid var(--line);
display: flex;
flex-direction: column;
gap: 3px;
}
.avatar-sign-char-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.avatar-sign-char {
font-family: var(--mono);
font-size: 0.95rem;
font-weight: 700;
color: var(--text);
}
.avatar-sign-hands {
font-size: 0.62rem;
font-weight: 600;
padding: 1px 5px;
border-radius: 4px;
background: var(--surface-3);
color: var(--text-dim);
}
.avatar-sign-desc {
font-size: 0.65rem;
color: var(--text-dim);
line-height: 1.25;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
[data-theme="light"] .avatar-sign-preview {
background: #ffffff;
border-color: #cbd5e1;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
[data-theme="light"] .avatar-sign-info {
background: #f8fafc;
border-top-color: #e2e8f0;
}
[data-theme="light"] .avatar-sign-desc {
color: #64748b;
}
/* Floating Avatar Controls Bar */
.avatar-controls-bar {
position: absolute;
bottom: 18px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
gap: 10px;
padding: 8px 16px;
background: rgb(18 18 20 / 0.88);
backdrop-filter: blur(12px);
border: 1px solid var(--line-bright);
border-radius: var(--r-pill);
box-shadow: 0 8px 32px rgb(0 0 0 / 0.6);
z-index: 10;
min-width: 380px;
max-width: 90%;
}
.avatar-ctrl-btn {
width: 34px;
height: 34px;
display: grid;
place-items: center;
background: var(--surface-3);
border: 1px solid var(--line);
border-radius: 50%;
color: var(--text);
font-size: 0.88rem;
cursor: pointer;
transition: all var(--dur) var(--ease);
flex: none;
}
.avatar-ctrl-btn:hover {
background: var(--accent-soft);
color: var(--accent-text);
border-color: var(--accent-line);
}
.play-pause-btn {
background: var(--accent);
color: #23180a;
border: none;
}
.play-pause-btn:hover {
background: #ffb854;
color: #1a1005;
}
.avatar-progress-wrap {
flex: 1;
display: flex;
align-items: center;
padding-inline: 6px;
}
.avatar-scrubber {
width: 100%;
accent-color: var(--accent);
cursor: pointer;
height: 4px;
}
/* ════ SIGN REFERENCE GUIDE MODAL & PHOTO PREVIEW ═══════════════════════ */
.guide-btn {
background: var(--surface-2);
border: 1px solid var(--accent-line);
color: var(--accent-text);
font-weight: 500;
}
.guide-btn:hover {
background: var(--accent-soft);
color: #fff;
border-color: var(--accent);
}
.sheet.sheet-wide {
width: min(1040px, calc(100vw - 48px));
max-height: min(88vh, 880px);
top: 50%;
left: 50%;
right: auto;
bottom: auto;
transform: translate(-50%, -50%) scale(0.96);
padding: 0;
overflow: hidden;
box-shadow: 0 28px 80px rgba(0, 0, 0, 0.55), 0 0 0 1px var(--line-bright);
}
.sheet.sheet-wide:not(:popover-open):not(.open) {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
opacity: 0 !important;
}
.sheet.sheet-wide:popover-open,
.sheet.sheet-wide.open {
display: flex !important;
flex-direction: column !important;
visibility: visible !important;
pointer-events: auto !important;
opacity: 1 !important;
transform: translate(-50%, -50%) scale(1) !important;
}
.sheet-wide .sheet-head {
padding: 20px 28px;
border-bottom: 1px solid var(--line);
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
background: var(--surface);
position: sticky;
top: 0;
z-index: 10;
}
.sheet-title-group {
display: flex;
flex-direction: column;
gap: 3px;
}
.sheet-title-group .sheet-title {
font-size: 1.15rem;
font-weight: 700;
color: var(--text);
margin: 0;
}
.sheet-sub {
font-size: 0.8rem;
color: var(--text-dim);
}
.guide-tabs {
display: inline-flex;
gap: 4px;
background: var(--surface-3);
padding: 4px;
border-radius: var(--r-pill);
border: 1px solid var(--line);
}
.guide-tab-btn {
padding: 6px 16px;
border: none;
background: transparent;
color: var(--text-dim);
font-family: var(--font);
font-size: 0.82rem;
font-weight: 600;
border-radius: var(--r-pill);
cursor: pointer;
transition: all var(--dur) var(--ease);
display: inline-flex;
align-items: center;
gap: 6px;
}
.guide-tab-btn:hover {
color: var(--text);
}
.guide-tab-btn.active {
background: var(--accent);
color: #ffffff;
box-shadow: 0 2px 8px color-mix(in oklab, var(--accent) 30%, transparent);
}
.guide-tab-content {
flex: 1;
overflow-y: auto;
padding: 20px 24px 28px;
}
.guide-alert-banner {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 12px 16px;
background: color-mix(in oklab, var(--accent) 10%, var(--surface-2));
border: 1px solid var(--accent-line);
border-radius: var(--r-ctrl);
color: var(--text);
font-size: 0.82rem;
line-height: 1.45;
margin-bottom: 20px;
}
.guide-alert-banner kbd {
background: var(--surface-3);
padding: 1px 5px;
border-radius: 4px;
border: 1px solid var(--line-bright);
font-family: var(--mono);
font-size: 0.75rem;
}
.banner-icon {
font-size: 1.1rem;
line-height: 1;
}
.guide-section-head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.guide-section-title {
font-size: 0.88rem;
font-weight: 600;
color: var(--text);
}
.pill-badge {
font-size: 0.72rem;
font-weight: 600;
padding: 3px 9px;
border-radius: var(--r-pill);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.pill-amber {
background: var(--accent-soft);
color: var(--accent-text);
border: 1px solid var(--accent-line);
}
.pill-blue {
background: color-mix(in oklab, #3b82f6 18%, transparent);
color: #93c5fd;
border: 1px solid color-mix(in oklab, #3b82f6 36%, transparent);
}
.guide-cards-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
gap: 12px;
}
.guide-card {
background: var(--surface-2);
border: 1px solid var(--line);
border-radius: var(--r-ctrl);
padding: 0;
display: flex;
flex-direction: column;
overflow: hidden;
cursor: pointer;
user-select: none;
transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.guide-card:hover {
transform: translateY(-2px);
border-color: var(--accent-line);
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
}
.guide-card:active {
transform: scale(0.98);
}
.guide-card-img-wrap {
width: 100%;
aspect-ratio: 1;
background: #000;
position: relative;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.guide-card-img-wrap img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.guide-card-body {
padding: 8px 10px;
display: flex;
align-items: center;
justify-content: space-between;
background: var(--surface-3);
border-top: 1px solid var(--line);
}
.guide-card-char {
font-family: var(--mono);
font-size: 1.05rem;
font-weight: 700;
color: var(--text);
}
.guide-card-hands {
font-size: 0.65rem;
font-weight: 600;
}
.guide-card-desc {
padding: 6px 10px 10px;
font-size: 0.72rem;
color: var(--text-dim);
line-height: 1.35;
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ASL Full Chart view */
.asl-chart-wrap {
width: 100%;
border-radius: var(--r-ctrl);
overflow: hidden;
border: 1px solid var(--line);
background: #000;
}
.asl-full-chart {
width: 100%;
height: auto;
display: block;
}
/* Practice Studio Real Human Photo Preview Card - permanently disabled on live screen */
.avatar-photo-ref,
#avatar-photo-ref,
.visually-workspace .avatar-photo-ref,
#live-workspace .avatar-photo-ref,
.hidden .avatar-photo-ref {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
overflow: hidden !important;
}
/* ══════════════════════════════════════════════════════════════════════
SIGN REFERENCE GUIDE MODAL
══════════════════════════════════════════════════════════════════════ */
#panel-guide:not(:popover-open):not(.open) {
display: none !important;
visibility: hidden !important;
pointer-events: none !important;
opacity: 0 !important;
}
#panel-guide:popover-open,
#panel-guide.open {
display: flex !important;
flex-direction: column !important;
visibility: visible !important;
pointer-events: auto !important;
opacity: 1 !important;
transform: translate(-50%, -50%) scale(1) !important;
}
.asl-chart-wrap {
width: 100%;
border-radius: 10px;
overflow: hidden;
border: 1px solid var(--line);
background: #000;
}
.asl-full-chart {
width: 100%;
display: block;
object-fit: contain;
}
/* ── Light Mode Specific Polish & Theme Toggle ───────────────────────── */
.theme-toggle-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 6px 10px;
min-width: 36px;
height: 32px;
cursor: pointer;
border-radius: var(--r-ctrl);
border: 1px solid var(--line);
background: var(--surface-2);
color: var(--text);
font-size: 0.95rem;
line-height: 1;
transition: all var(--dur) var(--ease);
}
.theme-toggle-btn:hover {
background: var(--surface-3);
border-color: var(--line-bright);
transform: translateY(-1px);
}
.theme-toggle-btn:active {
transform: scale(0.95);
}
[data-theme="light"] .mode-btn.active {
color: #ffffff;
}
[data-theme="light"] .avatar-viewport {
background: #eaedf4;
}
[data-theme="light"] .guide-card-img-wrap,
[data-theme="light"] .asl-chart-wrap {
background: #f1f3f8;
}
[data-theme="light"] .topbar {
background: #ffffff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
[data-theme="light"] .sheet {
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);
}
[data-theme="light"] .sheet.sheet-wide {
background: #ffffff;
border-color: #e2e8f0;
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.15), 0 4px 16px rgba(0, 0, 0, 0.08);
}
[data-theme="light"] .sheet-wide .sheet-head {
background: #ffffff;
border-bottom-color: #e2e8f0;
}
[data-theme="light"] .guide-card {
background: #ffffff;
border-color: #e2e8f0;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
}
[data-theme="light"] .guide-card:hover {
border-color: var(--accent);
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
}
[data-theme="light"] .guide-card-body {
background: #f8fafc;
border-top-color: #e2e8f0;
}
[data-theme="light"] .guide-card-desc {
color: #64748b;
}
[data-theme="light"] .guide-tabs {
background: #f1f5f9;
border-color: #e2e8f0;
}
[data-theme="light"] .guide-tab-btn {
color: #475569;
}
[data-theme="light"] .guide-tab-btn:hover {
color: #0f172a;
}
[data-theme="light"] .guide-tab-btn.active {
background: var(--accent);
color: #ffffff;
}
/* ═══════════════════════════════════════════════════════════════════════════
SIGN GUIDE LIGHTBOX — fullscreen popup for viewing sign images in detail
Uses native <dialog> to render above popovers in the Top Layer!
═══════════════════════════════════════════════════════════════════════════ */
dialog.sign-lightbox-dialog {
border: none;
background: transparent;
padding: 0;
margin: 0;
max-width: 100vw;
max-height: 100vh;
width: 100vw;
height: 100vh;
position: fixed;
inset: 0;
display: none;
align-items: center;
justify-content: center;
z-index: 2147483647;
opacity: 0;
pointer-events: none;
transition: opacity 0.25s ease, transform 0.25s ease;
}
dialog.sign-lightbox-dialog:not([open]) {
display: none !important;
pointer-events: none !important;
visibility: hidden !important;
}
dialog.sign-lightbox-dialog[open] {
display: flex !important;
opacity: 1;
pointer-events: auto;
visibility: visible !important;
}
dialog.sign-lightbox-dialog::backdrop {
background: rgba(0, 0, 0, 0.78);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
opacity: 0;
transition: opacity 0.25s ease;
}
dialog.sign-lightbox-dialog[open]::backdrop {
opacity: 1;
}
.sign-lightbox {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
background: var(--surface-1, #1a1a1e);
border: 1px solid var(--line, #2a2a2e);
border-radius: 18px;
padding: 28px 32px 24px;
max-width: 420px;
width: 90vw;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.3);
transform: scale(0.9) translateY(20px);
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
dialog.sign-lightbox-dialog[open] .sign-lightbox {
transform: scale(1) translateY(0);
}
.sign-lightbox-close {
position: absolute;
top: 12px;
right: 14px;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid var(--line, #2a2a2e);
border-radius: 8px;
background: var(--surface-2, #222226);
color: var(--text-dim, #888);
font-size: 1.1rem;
cursor: pointer;
transition: all 0.15s ease;
z-index: 2;
}
.sign-lightbox-close:hover {
background: var(--surface-3, #333);
color: var(--text, #fff);
border-color: var(--accent-line, #e67e22);
}
.sign-lightbox-img-wrap {
width: 100%;
max-width: 340px;
aspect-ratio: 1;
border-radius: 14px;
overflow: hidden;
background: #000;
border: 1px solid var(--line, #2a2a2e);
margin-bottom: 18px;
}
.sign-lightbox-img-wrap img {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
}
.sign-lightbox-letter {
font-family: var(--mono, 'Geist Mono', monospace);
font-size: 2.2rem;
font-weight: 800;
color: var(--text, #fff);
margin-bottom: 4px;
}
.sign-lightbox-type {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 14px;
border-radius: 20px;
font-size: 0.78rem;
font-weight: 600;
margin-bottom: 14px;
}
.sign-lightbox-type.one-hand {
background: rgba(245, 158, 11, 0.15);
color: #f59e0b;
border: 1px solid rgba(245, 158, 11, 0.25);
}
.sign-lightbox-type.two-hand {
background: rgba(59, 130, 246, 0.15);
color: #60a5fa;
border: 1px solid rgba(59, 130, 246, 0.25);
}
.sign-lightbox-desc {
font-size: 0.88rem;
color: var(--text-dim, #999);
line-height: 1.5;
text-align: center;
margin: 0;
padding: 0 8px;
}
.sign-lightbox-lang {
font-size: 0.72rem;
color: var(--text-dim, #666);
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid var(--line, #2a2a2e);
width: 100%;
text-align: center;
text-transform: uppercase;
letter-spacing: 0.08em;
font-weight: 600;
}
/* Light mode adjustments */
[data-theme="light"] dialog.sign-lightbox-dialog::backdrop {
background: rgba(255, 255, 255, 0.75);
}
[data-theme="light"] .sign-lightbox {
background: #fff;
border-color: #e5e5e5;
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.15), 0 8px 24px rgba(0, 0, 0, 0.08);
}
[data-theme="light"] .sign-lightbox-img-wrap {
background: #f5f5f5;
border-color: #e5e5e5;
}
[data-theme="light"] .sign-lightbox-close {
background: #f0f0f0;
border-color: #ddd;
color: #666;
}
[data-theme="light"] .sign-lightbox-close:hover {
background: #e5e5e5;
color: #333;
}
/* ══════════════════════════════════════════════════════════════════════
UPLOAD SIGN RECOGNITION STUDIO STYLES
══════════════════════════════════════════════════════════════════════ */
.upload-workspace {
grid-template-columns: minmax(320px, 380px) 1fr;
align-items: stretch;
}
.upload-sidebar {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
.upload-panel {
display: flex;
flex-direction: column;
gap: 16px;
height: 100%;
}
.upload-badge {
font-family: var(--mono);
font-size: 0.62rem;
font-weight: 700;
letter-spacing: 0.1em;
padding: 3px 7px;
border-radius: var(--r-pill);
background: var(--accent-soft);
color: var(--accent-text);
border: 1px solid var(--accent-line);
display: inline-block;
margin-bottom: 4px;
}
.upload-dialect-toggle {
display: flex;
background: var(--surface-3);
padding: 2px;
border-radius: var(--r-pill);
border: 1px solid var(--line);
gap: 2px;
}
.upload-dialect-btn {
padding: 4px 12px;
font-family: var(--font);
font-size: 0.74rem;
font-weight: 600;
border: none;
background: transparent;
color: var(--text-mute);
border-radius: var(--r-pill);
cursor: pointer;
transition: all var(--dur) var(--ease);
}
.upload-dialect-btn:hover {
color: var(--text);
}
.upload-dialect-btn.active {
background: var(--accent);
color: #23180a;
}
[data-theme="light"] .upload-dialect-btn.active {
color: #fff;
}
/* Drag & Drop Area */
.upload-dropzone {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 28px 18px;
border: 2px dashed var(--line-bright);
border-radius: var(--r-panel);
background: var(--surface-2);
text-align: center;
cursor: pointer;
transition: all var(--dur) var(--ease);
}
.upload-dropzone:hover,
.upload-dropzone.dragover {
border-color: var(--accent);
background: var(--accent-soft);
transform: scale(1.01);
}
.upload-file-hidden {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
width: 100%;
height: 100%;
}
.dropzone-icon {
color: var(--accent);
margin-bottom: 12px;
transition: transform var(--dur) var(--ease);
}
.upload-dropzone:hover .dropzone-icon {
transform: translateY(-3px);
}
.dropzone-title {
font-size: 0.92rem;
font-weight: 600;
color: var(--text);
margin-bottom: 4px;
}
.dropzone-sub {
font-size: 0.8rem;
color: var(--text-dim);
margin-bottom: 8px;
}
.dropzone-browse {
color: var(--accent-text);
text-decoration: underline;
text-underline-offset: 3px;
font-weight: 600;
}
.dropzone-formats {
font-size: 0.68rem;
font-family: var(--mono);
color: var(--text-mute);
}
/* Samples Section */
.upload-samples-wrap {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 4px;
}
.upload-samples-label {
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-mute);
}
.upload-samples-chips {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.sample-img-chip {
padding: 5px 11px;
font-family: var(--mono);
font-size: 0.74rem;
font-weight: 600;
border-radius: var(--r-pill);
border: 1px solid var(--line);
background: var(--surface-3);
color: var(--text-dim);
cursor: pointer;
transition: all var(--dur) var(--ease);
}
.sample-img-chip:hover {
background: var(--accent-soft);
border-color: var(--accent-line);
color: var(--accent-text);
transform: translateY(-1px);
}
/* Upload Stage & Visual Viewport */
.upload-stage {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
.upload-viewport {
position: relative;
flex: 1;
width: 100%;
height: 100%;
background: #0e0e11;
border: 1px solid var(--line);
border-radius: var(--r-panel);
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
[data-theme="light"] .upload-viewport {
background: #f0f2f7;
}
.upload-empty-state {
max-width: 420px;
padding: 32px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.upload-empty-icon {
font-size: 3.5rem;
margin-bottom: 4px;
animation: floatHand 3s ease-in-out infinite;
}
@keyframes floatHand {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
.upload-empty-state h3 {
font-size: 1.25rem;
font-weight: 600;
color: var(--text);
}
.upload-empty-state p {
font-size: 0.84rem;
color: var(--text-dim);
line-height: 1.55;
margin-bottom: 6px;
}
.upload-canvas-wrap {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
padding: 16px;
box-sizing: border-box;
}
#upload-canvas {
width: auto;
height: auto;
min-width: min(340px, 85%);
min-height: min(340px, 75%);
max-width: 92%;
max-height: 88%;
object-fit: contain;
display: block;
border-radius: 12px;
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5);
background: #141418;
}
/* Floating Results Card inside Viewport */
.upload-result-hud {
position: absolute;
top: 18px;
left: 18px;
width: 310px;
max-width: calc(100% - 36px);
background: rgb(18 18 20 / 0.88);
backdrop-filter: blur(14px);
border: 1px solid var(--line-bright);
border-radius: var(--r-panel);
padding: 16px;
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.45);
display: flex;
flex-direction: column;
gap: 14px;
z-index: 10;
animation: hudSlideIn 0.28s cubic-bezier(0.2, 0, 0.2, 1);
}
[data-theme="light"] .upload-result-hud {
background: rgb(255 255 255 / 0.92);
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.12);
}
@keyframes hudSlideIn {
from { opacity: 0; transform: translateY(-8px) scale(0.96); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
.result-hud-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.result-badge-dialect {
font-family: var(--mono);
font-size: 0.72rem;
font-weight: 700;
padding: 2px 8px;
border-radius: var(--r-pill);
background: var(--accent);
color: #23180a;
}
[data-theme="light"] .result-badge-dialect {
color: #fff;
}
.result-badge-hands {
font-size: 0.72rem;
font-weight: 500;
color: var(--text-dim);
}
.result-main-row {
display: flex;
align-items: center;
gap: 16px;
}
.result-letter-huge {
font-family: var(--mono);
font-size: 3.4rem;
font-weight: 700;
line-height: 1;
color: var(--text);
min-width: 64px;
text-align: center;
text-shadow: 0 0 24px color-mix(in oklab, var(--accent) 45%, transparent);
}
.result-details {
display: flex;
flex-direction: column;
gap: 4px;
flex: 1;
}
.result-conf-row {
display: flex;
align-items: baseline;
justify-content: space-between;
}
.result-conf-label {
font-size: 0.72rem;
color: var(--text-mute);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.result-conf-val {
font-family: var(--mono);
font-size: 1rem;
font-weight: 700;
color: var(--accent-text);
}
.result-desc {
font-size: 0.76rem;
color: var(--text-dim);
line-height: 1.35;
}
/* Top 3 Breakdown */
.result-top3-section {
display: flex;
flex-direction: column;
gap: 8px;
border-top: 1px solid var(--line);
padding-top: 10px;
}
.result-top3-title {
font-size: 0.68rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-mute);
}
.result-top3-bars {
display: flex;
flex-direction: column;
gap: 6px;
}
.top3-row {
display: flex;
align-items: center;
gap: 8px;
font-size: 0.75rem;
}
.top3-label {
font-family: var(--mono);
font-weight: 700;
min-width: 22px;
color: var(--text);
}
.top3-bar-track {
flex: 1;
height: 6px;
background: var(--surface-3);
border-radius: var(--r-pill);
overflow: hidden;
}
.top3-bar-fill {
height: 100%;
border-radius: inherit;
background: var(--accent);
transition: width 0.35s ease;
}
.top3-val {
font-family: var(--mono);
font-size: 0.7rem;
color: var(--text-dim);
min-width: 38px;
text-align: right;
}