Add read-only Noya admin panel with assignments and UX polish.
Ship admin auth, user overview, assessments, chats, assignment filters/export, security hardening, and a separate desktop admin shell with clearer assessment answers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+161
-88
@@ -35,8 +35,8 @@
|
||||
--neon-emerald: #10b981;
|
||||
--navy-deep: #0f172a;
|
||||
--navy: #1e293b;
|
||||
--glass-bg: rgba(255, 255, 255, 0.88);
|
||||
--glass-bg-strong: rgba(255, 255, 255, 0.94);
|
||||
--glass-bg: rgba(255, 255, 255, 0.55);
|
||||
--glass-bg-strong: rgba(255, 255, 255, 0.72);
|
||||
--body-text: #334155;
|
||||
--glow-blue: 0 0 16px rgba(0, 168, 232, 0.35);
|
||||
--glow-teal: 0 0 16px rgba(38, 212, 202, 0.4);
|
||||
@@ -75,8 +75,8 @@
|
||||
--neon-blue: #00a8e8;
|
||||
--neon-cyan: #0d9488;
|
||||
--neon-teal: #0f766e;
|
||||
--glass-bg: rgba(255, 255, 255, 0.88);
|
||||
--glass-bg-strong: rgba(255, 255, 255, 0.94);
|
||||
--glass-bg: rgba(255, 255, 255, 0.55);
|
||||
--glass-bg-strong: rgba(255, 255, 255, 0.72);
|
||||
--body-text: #334155;
|
||||
--glow-blue: 0 2px 8px rgba(0, 168, 232, 0.18);
|
||||
--glow-teal: 0 2px 8px rgba(38, 212, 202, 0.16);
|
||||
@@ -114,8 +114,8 @@
|
||||
--neon-blue: #00a8e8;
|
||||
--neon-cyan: #26d4ca;
|
||||
--neon-teal: #26d4ca;
|
||||
--glass-bg: rgba(30, 41, 59, 0.82);
|
||||
--glass-bg-strong: rgba(30, 41, 59, 0.92);
|
||||
--glass-bg: rgba(30, 41, 59, 0.52);
|
||||
--glass-bg-strong: rgba(30, 41, 59, 0.72);
|
||||
--body-text: #e2e8f0;
|
||||
--glow-blue: 0 0 18px rgba(0, 168, 232, 0.45), 0 0 36px rgba(0, 168, 232, 0.2);
|
||||
--glow-teal: 0 0 18px rgba(38, 212, 202, 0.5), 0 0 36px rgba(38, 212, 202, 0.22);
|
||||
@@ -160,7 +160,10 @@
|
||||
html {
|
||||
color-scheme: light;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
@@ -182,7 +185,9 @@
|
||||
#root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
@@ -278,6 +283,7 @@
|
||||
.app-mobile-shell {
|
||||
@apply relative z-10 flex w-full max-w-[430px] flex-1 flex-col overflow-hidden;
|
||||
min-height: 0;
|
||||
max-width: min(100%, 430px);
|
||||
padding-bottom: env(safe-area-inset-bottom, 0px);
|
||||
background: #0f172a;
|
||||
border: 1px solid rgb(51 65 85 / 0.55);
|
||||
@@ -334,58 +340,54 @@
|
||||
}
|
||||
|
||||
.glass-panel {
|
||||
@apply relative rounded-2xl backdrop-blur-xl;
|
||||
@apply relative overflow-hidden rounded-2xl;
|
||||
background: var(--glass-bg);
|
||||
border: 1px solid rgb(226 232 240 / 0.9);
|
||||
box-shadow: 0 1px 2px rgb(15 23 42 / 0.04);
|
||||
}
|
||||
|
||||
/* Chat messages surface — high-intensity glass, no extra border */
|
||||
.glass-panel-chat {
|
||||
@apply relative h-full min-h-0 overflow-hidden rounded-none;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
backdrop-filter: blur(42px) saturate(1.7);
|
||||
-webkit-backdrop-filter: blur(42px) saturate(1.7);
|
||||
border: none;
|
||||
border: 1px solid rgb(255 255 255 / 0.45);
|
||||
backdrop-filter: blur(24px) saturate(1.45);
|
||||
-webkit-backdrop-filter: blur(24px) saturate(1.45);
|
||||
box-shadow:
|
||||
0 16px 40px rgba(47, 127, 212, 0.14),
|
||||
0 10px 28px rgba(52, 184, 150, 0.1),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.45);
|
||||
0 8px 32px rgb(15 23 42 / 0.08),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.55);
|
||||
}
|
||||
|
||||
.glass-panel-chat::before {
|
||||
.glass-panel::before {
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background:
|
||||
radial-gradient(ellipse 80% 50% at 100% 0%, rgba(56, 160, 230, 0.18), transparent 55%),
|
||||
radial-gradient(ellipse 70% 45% at 0% 100%, rgba(52, 184, 150, 0.16), transparent 50%);
|
||||
inset-inline: 0;
|
||||
top: 0;
|
||||
height: 7rem;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgb(0 168 232 / 0.14),
|
||||
rgb(38 212 202 / 0.05),
|
||||
transparent
|
||||
);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
html.dark .glass-panel-chat {
|
||||
background: rgba(12, 20, 36, 0.22);
|
||||
/* Legacy alias — prefer .glass-panel (same visual language as login / assessment) */
|
||||
.glass-panel-chat {
|
||||
@apply relative h-full min-h-0 overflow-hidden rounded-2xl;
|
||||
background: var(--glass-bg);
|
||||
border: 1px solid rgb(255 255 255 / 0.45);
|
||||
backdrop-filter: blur(24px) saturate(1.45);
|
||||
-webkit-backdrop-filter: blur(24px) saturate(1.45);
|
||||
box-shadow:
|
||||
0 16px 40px rgba(0, 140, 210, 0.16),
|
||||
0 10px 28px rgba(52, 184, 150, 0.1),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
||||
0 8px 32px rgb(15 23 42 / 0.08),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.55);
|
||||
}
|
||||
|
||||
html.light .glass-panel-chat {
|
||||
background: rgba(255, 255, 255, 0.22);
|
||||
box-shadow:
|
||||
0 16px 40px rgba(47, 127, 212, 0.12),
|
||||
0 10px 28px rgba(52, 184, 150, 0.1),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
/* Chat composer */
|
||||
/* Chat composer — single flat background (no nested input fill) */
|
||||
/* Chat composer — glass, aligned with login inputs */
|
||||
.composer-glass {
|
||||
@apply relative flex min-h-12 w-full items-end gap-2 rounded-2xl p-1.5;
|
||||
background: #ffffff;
|
||||
border: 1px solid rgb(226 232 240);
|
||||
box-shadow: 0 1px 2px rgb(15 23 42 / 0.05);
|
||||
background: var(--glass-bg);
|
||||
border: 1px solid rgb(255 255 255 / 0.4);
|
||||
backdrop-filter: blur(18px) saturate(1.35);
|
||||
-webkit-backdrop-filter: blur(18px) saturate(1.35);
|
||||
box-shadow:
|
||||
0 4px 16px rgb(15 23 42 / 0.06),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.45);
|
||||
}
|
||||
|
||||
.composer-glass textarea.input-neon {
|
||||
@@ -400,37 +402,41 @@
|
||||
border-color: rgb(38 212 202 / 0.55);
|
||||
box-shadow:
|
||||
0 0 0 1px rgb(38 212 202 / 0.3),
|
||||
0 3px 8px rgb(15 23 42 / 0.08);
|
||||
0 4px 16px rgb(15 23 42 / 0.08),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.5);
|
||||
}
|
||||
|
||||
html.dark .composer-glass,
|
||||
html.dark .composer-glass:focus-within {
|
||||
background: #1e293b;
|
||||
border-color: rgb(51 65 85 / 0.9);
|
||||
box-shadow: 0 2px 6px rgb(0 0 0 / 0.25);
|
||||
background: var(--glass-bg);
|
||||
border-color: rgb(255 255 255 / 0.12);
|
||||
box-shadow:
|
||||
0 4px 18px rgb(0 0 0 / 0.28),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.08);
|
||||
}
|
||||
|
||||
html.dark .composer-glass:focus-within {
|
||||
border-color: #26d4ca;
|
||||
box-shadow:
|
||||
0 0 0 1px rgb(38 212 202 / 0.45),
|
||||
0 3px 10px rgb(0 0 0 / 0.35),
|
||||
0 0 14px rgb(38 212 202 / 0.35),
|
||||
0 0 22px rgb(0 168 232 / 0.2);
|
||||
0 4px 18px rgb(0 0 0 / 0.35),
|
||||
0 0 14px rgb(38 212 202 / 0.3),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.1);
|
||||
}
|
||||
|
||||
html.light .composer-glass,
|
||||
html.light .composer-glass:focus-within {
|
||||
background: #ffffff;
|
||||
border-color: rgb(203 213 225 / 0.95);
|
||||
background: var(--glass-bg);
|
||||
border-color: rgb(255 255 255 / 0.55);
|
||||
}
|
||||
|
||||
html.light .composer-glass:focus-within {
|
||||
border-color: #26d4ca;
|
||||
box-shadow:
|
||||
0 0 0 1px rgb(38 212 202 / 0.28),
|
||||
0 3px 8px rgb(15 23 42 / 0.08),
|
||||
0 0 8px rgb(38 212 202 / 0.16);
|
||||
0 4px 16px rgb(15 23 42 / 0.08),
|
||||
0 0 8px rgb(38 212 202 / 0.14),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.6);
|
||||
}
|
||||
|
||||
.composer-glass .input-neon,
|
||||
@@ -454,12 +460,14 @@
|
||||
}
|
||||
|
||||
.glass-panel-strong {
|
||||
@apply relative rounded-2xl backdrop-blur-md;
|
||||
@apply relative overflow-hidden rounded-2xl;
|
||||
background: var(--glass-bg-strong);
|
||||
border: 1px solid rgb(226 232 240 / 0.95);
|
||||
border: 1px solid rgb(255 255 255 / 0.4);
|
||||
backdrop-filter: blur(20px) saturate(1.35);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(1.35);
|
||||
box-shadow:
|
||||
0 8px 24px rgb(15 23 42 / 0.08),
|
||||
0 1px 2px rgb(15 23 42 / 0.04);
|
||||
0 8px 28px rgb(15 23 42 / 0.1),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.5);
|
||||
}
|
||||
|
||||
.neon-border {
|
||||
@@ -470,16 +478,27 @@
|
||||
|
||||
html.light .glass-panel,
|
||||
html.light .glass-panel-strong {
|
||||
border-color: rgb(226 232 240 / 0.95);
|
||||
border-color: rgb(255 255 255 / 0.65);
|
||||
box-shadow:
|
||||
0 1px 2px rgb(15 23 42 / 0.04),
|
||||
0 4px 12px rgb(15 23 42 / 0.03);
|
||||
0 8px 28px rgb(15 23 42 / 0.07),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.7);
|
||||
}
|
||||
|
||||
html.dark .glass-panel,
|
||||
html.dark .glass-panel-strong {
|
||||
border-color: rgb(51 65 85 / 0.55);
|
||||
box-shadow: 0 1px 2px rgb(0 0 0 / 0.2);
|
||||
border-color: rgb(255 255 255 / 0.12);
|
||||
box-shadow:
|
||||
0 10px 32px rgb(0 0 0 / 0.35),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.1);
|
||||
}
|
||||
|
||||
html.dark .glass-panel::before {
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgb(0 168 232 / 0.18),
|
||||
rgb(38 212 202 / 0.06),
|
||||
transparent
|
||||
);
|
||||
}
|
||||
|
||||
html.dark .neon-border {
|
||||
@@ -559,28 +578,34 @@
|
||||
|
||||
.btn-glass {
|
||||
@apply inline-flex items-center justify-center rounded-xl px-4 py-2.5 text-sm font-medium transition-all duration-300;
|
||||
background: rgb(241 245 249 / 0.9);
|
||||
border: 1px solid rgb(203 213 225 / 0.95);
|
||||
background: rgb(255 255 255 / 0.35);
|
||||
border: 1px solid rgb(255 255 255 / 0.5);
|
||||
color: var(--body-text);
|
||||
box-shadow: 0 2px 4px rgb(15 23 42 / 0.05);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
box-shadow:
|
||||
0 2px 8px rgb(15 23 42 / 0.05),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.5);
|
||||
}
|
||||
|
||||
.btn-glass:hover:not(:disabled) {
|
||||
border-color: rgb(38 212 202 / 0.5);
|
||||
background: rgb(248 250 252);
|
||||
background: rgb(255 255 255 / 0.55);
|
||||
color: hsl(var(--foreground));
|
||||
box-shadow: 0 3px 8px rgb(15 23 42 / 0.07);
|
||||
box-shadow: 0 3px 10px rgb(15 23 42 / 0.07);
|
||||
}
|
||||
|
||||
html.dark .btn-glass {
|
||||
background: rgb(30 41 59 / 0.85);
|
||||
border-color: rgb(38 212 202 / 0.28);
|
||||
box-shadow: 0 2px 6px rgb(0 0 0 / 0.25);
|
||||
background: rgb(30 41 59 / 0.45);
|
||||
border-color: rgb(255 255 255 / 0.14);
|
||||
box-shadow:
|
||||
0 2px 10px rgb(0 0 0 / 0.25),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.08);
|
||||
}
|
||||
|
||||
html.dark .btn-glass:hover:not(:disabled) {
|
||||
border-color: #26d4ca;
|
||||
background: rgb(51 65 85 / 0.75);
|
||||
background: rgb(51 65 85 / 0.55);
|
||||
box-shadow:
|
||||
0 3px 10px rgb(0 0 0 / 0.35),
|
||||
0 0 12px rgb(38 212 202 / 0.28),
|
||||
@@ -588,8 +613,8 @@
|
||||
}
|
||||
|
||||
html.light .btn-glass {
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
border-color: rgb(203 213 225 / 0.95);
|
||||
background: rgb(255 255 255 / 0.4);
|
||||
border-color: rgb(255 255 255 / 0.6);
|
||||
}
|
||||
|
||||
.btn-glass:focus,
|
||||
@@ -652,10 +677,14 @@
|
||||
|
||||
.input-neon {
|
||||
@apply flex h-11 w-full items-center rounded-xl px-3 py-0 text-sm leading-relaxed transition-all duration-300;
|
||||
background: rgb(248 250 252);
|
||||
border: 1px solid rgb(203 213 225 / 0.9);
|
||||
background: rgb(255 255 255 / 0.45);
|
||||
border: 1px solid rgb(255 255 255 / 0.5);
|
||||
color: hsl(var(--foreground));
|
||||
box-shadow: 0 2px 4px rgb(15 23 42 / 0.05);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
box-shadow:
|
||||
0 2px 8px rgb(15 23 42 / 0.05),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.55);
|
||||
}
|
||||
|
||||
.input-neon::placeholder {
|
||||
@@ -663,16 +692,20 @@
|
||||
}
|
||||
|
||||
html.dark .input-neon {
|
||||
background: rgb(30 41 59 / 0.9);
|
||||
border-color: rgb(71 85 105 / 0.75);
|
||||
box-shadow: 0 2px 6px rgb(0 0 0 / 0.25);
|
||||
background: rgb(15 23 42 / 0.35);
|
||||
border-color: rgb(255 255 255 / 0.12);
|
||||
box-shadow:
|
||||
0 2px 10px rgb(0 0 0 / 0.25),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.08);
|
||||
}
|
||||
|
||||
html.light .input-neon {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-color: rgb(203 213 225 / 0.95);
|
||||
background: rgb(255 255 255 / 0.5);
|
||||
border-color: rgb(255 255 255 / 0.65);
|
||||
color: hsl(var(--foreground));
|
||||
box-shadow: 0 2px 4px rgb(15 23 42 / 0.05);
|
||||
box-shadow:
|
||||
0 2px 8px rgb(15 23 42 / 0.05),
|
||||
inset 0 1px 0 rgb(255 255 255 / 0.7);
|
||||
}
|
||||
|
||||
html.light .input-neon::placeholder {
|
||||
@@ -743,15 +776,35 @@
|
||||
|
||||
.ambient-glow {
|
||||
position: relative;
|
||||
/* Pseudo glows extend past the box; clip X so mobile cannot pan sideways */
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
@supports not (overflow: clip) {
|
||||
.ambient-glow {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.ambient-glow::before {
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
inset: -20% -10% auto;
|
||||
height: 55%;
|
||||
background: radial-gradient(ellipse at center, rgba(0, 102, 255, 0.25), transparent 70%);
|
||||
inset: -18% 0 auto;
|
||||
height: 58%;
|
||||
background:
|
||||
radial-gradient(ellipse 70% 60% at 30% 40%, rgba(0, 168, 232, 0.22), transparent 70%),
|
||||
radial-gradient(ellipse 60% 50% at 78% 30%, rgba(38, 212, 202, 0.18), transparent 68%);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.ambient-glow::after {
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
inset: auto 0 -25%;
|
||||
height: 45%;
|
||||
background: radial-gradient(ellipse 65% 55% at 60% 70%, rgba(38, 212, 202, 0.12), transparent 72%);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@@ -786,7 +839,8 @@
|
||||
|
||||
.bubble-user {
|
||||
@apply inline-flex w-fit flex-col rounded-2xl py-2.5 text-base leading-7;
|
||||
max-width: calc(85% * 1.2);
|
||||
/* Cap at 100% — calc(85% * 1.2) was 102% and caused mobile sideways scroll */
|
||||
max-width: min(100%, calc(85% * 1.2));
|
||||
padding-inline: calc(0.875rem * 1.2);
|
||||
background: rgba(255, 255, 255, 0.28);
|
||||
backdrop-filter: blur(18px) saturate(1.35);
|
||||
@@ -854,6 +908,19 @@
|
||||
text-justify: inter-word;
|
||||
}
|
||||
|
||||
/* ChatGPT-like breathing room between blocks */
|
||||
.bubble-ai > div {
|
||||
@apply space-y-4;
|
||||
}
|
||||
|
||||
.bubble-ai p + p {
|
||||
margin-top: 0.35rem;
|
||||
}
|
||||
|
||||
.bubble-ai h3 {
|
||||
@apply mt-1 mb-0.5;
|
||||
}
|
||||
|
||||
.bubble-user .chat-prose {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
@@ -882,6 +949,12 @@
|
||||
margin-inline-end: 0.15rem;
|
||||
}
|
||||
|
||||
/* Ordered lists keep source numbers (۱. ۲. ۳.) — no CSS auto-renumber padding */
|
||||
.bubble-ai ol.list-none {
|
||||
padding-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
.bubble-ai li::marker {
|
||||
color: hsl(var(--foreground));
|
||||
font-weight: 600;
|
||||
|
||||
Reference in New Issue
Block a user