From 97aedede3075b3bd711490d135c3098f747e722f Mon Sep 17 00:00:00 2001 From: v0 Date: Sat, 17 Oct 2026 09:54:44 +0000 Subject: [PATCH 1/6] feat: add retro-console component to dashboard view with themed styling and interactive elements Co-authored-by: HexJasur <315015959+hexjasur@users.noreply.github.com> --- app/globals.css | 49 +++++++++++++++++++++++++ components/dashboard/dashboard-view.tsx | 24 +++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/app/globals.css b/app/globals.css index c585c96..ebe98f0 100644 --- a/app/globals.css +++ b/app/globals.css @@ -134,6 +134,55 @@ .ps-barcode { background: repeating-linear-gradient(90deg, var(--ink) 0 1px, transparent 1px 3px, var(--ink) 3px 5px, transparent 5px 6px, var(--ink) 6px 7px, transparent 7px 11px); } + + /* 1950s-inspired alternate surface for the workspace dashboard */ + .retro-console { + position: relative; + overflow: hidden; + color: #30251b; + border: 1px solid #6f5a42; + border-radius: 4px; + background: #d9c39c; + box-shadow: 6px 6px 0 rgba(48,37,27,.18), inset 0 0 0 5px rgba(255,245,214,.22); + } + [data-theme="dark"] .retro-console { + color: #f4d7a2; + border-color: #b27b43; + background: #2a211b; + box-shadow: 6px 6px 0 rgba(0,0,0,.35), inset 0 0 0 5px rgba(255,177,83,.06); + } + .retro-console::after { + content: ""; + position: absolute; + inset: 0; + pointer-events: none; + opacity: .3; + background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(48,37,27,.12) 3px 4px); + mix-blend-mode: multiply; + } + .retro-console__topline, .retro-console__body { position: relative; z-index: 1; } + .retro-console__topline { + display: flex; justify-content: space-between; align-items: center; gap: 12px; + padding: 10px 18px; border-bottom: 1px solid currentColor; + font: 700 10px/1 var(--font-mono); letter-spacing: .15em; text-transform: uppercase; + } + .retro-console__eyebrow, .retro-console__signal { display: inline-flex; align-items: center; gap: 7px; } + .retro-console__signal { opacity: .72; letter-spacing: .08em; } + .retro-console__signal span { width: 7px; height: 7px; border-radius: 50%; background: #c54a28; box-shadow: 0 0 0 3px rgba(197,74,40,.2); } + .retro-console__body { display: flex; align-items: center; justify-content: space-between; gap: 28px; padding: clamp(22px, 4vw, 36px); } + .retro-console__copy { max-width: 680px; } + .retro-console__kicker { margin: 0 0 10px; font: 700 10px/1 var(--font-mono); letter-spacing: .2em; opacity: .65; } + .retro-console h2 { margin: 0; font: 700 clamp(28px, 4vw, 48px)/.95 Georgia, serif; letter-spacing: -.04em; } + .retro-console h2 em { color: #b54828; font-style: italic; } + [data-theme="dark"] .retro-console h2 em { color: #ffad60; } + .retro-console__copy > p:not(.retro-console__kicker) { max-width: 580px; margin: 16px 0 0; font: 500 14px/1.6 Georgia, serif; opacity: .8; } + .retro-console__actions { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 22px; font: 700 10px/1 var(--font-mono); letter-spacing: .08em; } + .retro-console__actions span { display: inline-flex; align-items: center; gap: 6px; } + .retro-console__dial { display: grid; place-items: center; flex: 0 0 132px; width: 132px; height: 132px; border: 1px solid currentColor; border-radius: 50%; transform: rotate(-8deg); opacity: .8; } + .retro-console__dial-ring { display: grid; place-items: center; width: 92px; height: 92px; border: 5px double currentColor; border-radius: 50%; } + .retro-console__dial b { font: 500 48px/1 Georgia, serif; } + .retro-console__dial > span { position: absolute; bottom: 11px; font: 700 8px/1 var(--font-mono); letter-spacing: .16em; } + @media (max-width: 560px) { .retro-console__dial { display: none; } .retro-console__topline { padding-inline: 13px; } .retro-console__body { padding: 24px 18px; } } } /* View Transitions for Theme Toggle */ diff --git a/components/dashboard/dashboard-view.tsx b/components/dashboard/dashboard-view.tsx index d650a7f..ad414b4 100644 --- a/components/dashboard/dashboard-view.tsx +++ b/components/dashboard/dashboard-view.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ArrowUpRight, BookOpenText } from 'lucide-react'; +import { ArrowUpRight, BookOpenText, Clock3, Radio, Sparkles } from 'lucide-react'; import Link from 'next/link'; import { PsHero, @@ -40,6 +40,28 @@ export function DashboardView() { lead={t('dashboard.hero_lead')} /> +
+
+ + +
+
+
+

SONLI USULLAR PRESENTS

+

Hisoblash — kelajakdan kelgan.

+

1950-yillar ilmiy laboratoriyasi ruhi bilan sonli usullarni qayta kashf eting. Har bir formula — kichik bir ixtiro.

+
+ + +
+
+ +
+
+ Date: Sat, 17 Oct 2026 09:55:34 +0000 Subject: [PATCH 2/6] Revert "feat: add retro-console component to dashboard view with themed styling and interactive elements" This reverts commit 97aedede3075b3bd711490d135c3098f747e722f. --- app/globals.css | 49 ------------------------- components/dashboard/dashboard-view.tsx | 24 +----------- 2 files changed, 1 insertion(+), 72 deletions(-) diff --git a/app/globals.css b/app/globals.css index ebe98f0..c585c96 100644 --- a/app/globals.css +++ b/app/globals.css @@ -134,55 +134,6 @@ .ps-barcode { background: repeating-linear-gradient(90deg, var(--ink) 0 1px, transparent 1px 3px, var(--ink) 3px 5px, transparent 5px 6px, var(--ink) 6px 7px, transparent 7px 11px); } - - /* 1950s-inspired alternate surface for the workspace dashboard */ - .retro-console { - position: relative; - overflow: hidden; - color: #30251b; - border: 1px solid #6f5a42; - border-radius: 4px; - background: #d9c39c; - box-shadow: 6px 6px 0 rgba(48,37,27,.18), inset 0 0 0 5px rgba(255,245,214,.22); - } - [data-theme="dark"] .retro-console { - color: #f4d7a2; - border-color: #b27b43; - background: #2a211b; - box-shadow: 6px 6px 0 rgba(0,0,0,.35), inset 0 0 0 5px rgba(255,177,83,.06); - } - .retro-console::after { - content: ""; - position: absolute; - inset: 0; - pointer-events: none; - opacity: .3; - background: repeating-linear-gradient(0deg, transparent 0 3px, rgba(48,37,27,.12) 3px 4px); - mix-blend-mode: multiply; - } - .retro-console__topline, .retro-console__body { position: relative; z-index: 1; } - .retro-console__topline { - display: flex; justify-content: space-between; align-items: center; gap: 12px; - padding: 10px 18px; border-bottom: 1px solid currentColor; - font: 700 10px/1 var(--font-mono); letter-spacing: .15em; text-transform: uppercase; - } - .retro-console__eyebrow, .retro-console__signal { display: inline-flex; align-items: center; gap: 7px; } - .retro-console__signal { opacity: .72; letter-spacing: .08em; } - .retro-console__signal span { width: 7px; height: 7px; border-radius: 50%; background: #c54a28; box-shadow: 0 0 0 3px rgba(197,74,40,.2); } - .retro-console__body { display: flex; align-items: center; justify-content: space-between; gap: 28px; padding: clamp(22px, 4vw, 36px); } - .retro-console__copy { max-width: 680px; } - .retro-console__kicker { margin: 0 0 10px; font: 700 10px/1 var(--font-mono); letter-spacing: .2em; opacity: .65; } - .retro-console h2 { margin: 0; font: 700 clamp(28px, 4vw, 48px)/.95 Georgia, serif; letter-spacing: -.04em; } - .retro-console h2 em { color: #b54828; font-style: italic; } - [data-theme="dark"] .retro-console h2 em { color: #ffad60; } - .retro-console__copy > p:not(.retro-console__kicker) { max-width: 580px; margin: 16px 0 0; font: 500 14px/1.6 Georgia, serif; opacity: .8; } - .retro-console__actions { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 22px; font: 700 10px/1 var(--font-mono); letter-spacing: .08em; } - .retro-console__actions span { display: inline-flex; align-items: center; gap: 6px; } - .retro-console__dial { display: grid; place-items: center; flex: 0 0 132px; width: 132px; height: 132px; border: 1px solid currentColor; border-radius: 50%; transform: rotate(-8deg); opacity: .8; } - .retro-console__dial-ring { display: grid; place-items: center; width: 92px; height: 92px; border: 5px double currentColor; border-radius: 50%; } - .retro-console__dial b { font: 500 48px/1 Georgia, serif; } - .retro-console__dial > span { position: absolute; bottom: 11px; font: 700 8px/1 var(--font-mono); letter-spacing: .16em; } - @media (max-width: 560px) { .retro-console__dial { display: none; } .retro-console__topline { padding-inline: 13px; } .retro-console__body { padding: 24px 18px; } } } /* View Transitions for Theme Toggle */ diff --git a/components/dashboard/dashboard-view.tsx b/components/dashboard/dashboard-view.tsx index ad414b4..d650a7f 100644 --- a/components/dashboard/dashboard-view.tsx +++ b/components/dashboard/dashboard-view.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ArrowUpRight, BookOpenText, Clock3, Radio, Sparkles } from 'lucide-react'; +import { ArrowUpRight, BookOpenText } from 'lucide-react'; import Link from 'next/link'; import { PsHero, @@ -40,28 +40,6 @@ export function DashboardView() { lead={t('dashboard.hero_lead')} /> -
-
- - -
-
-
-

SONLI USULLAR PRESENTS

-

Hisoblash — kelajakdan kelgan.

-

1950-yillar ilmiy laboratoriyasi ruhi bilan sonli usullarni qayta kashf eting. Har bir formula — kichik bir ixtiro.

-
- - -
-
- -
-
- Date: Sat, 17 Oct 2026 09:57:49 +0000 Subject: [PATCH 3/6] Add retro Print Stream theme styling --- app/globals.css | 80 ++++++++++++++++++++++------------ components/ui/print-stream.tsx | 6 +-- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/app/globals.css b/app/globals.css index c585c96..35d647e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -3,20 +3,21 @@ @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); :root { - --bg: #eceef0; - --bg-2: #f6f7f8; - --panel: #fbfbfc; - --panel-2: #f1f2f4; - --ink: #0d0f12; - --ink-2: #2a2e35; - --muted: #5d646e; - --line: #d5d9de; - --line-2: #b9bfc7; - --cyan: #0891b2; - --cyan-soft: rgba(8,145,178,.09); - --brand: #e8480c; - --brand-ink: #ffffff; - --brand-soft: rgba(232,72,12,.09); + /* Semantic tokens: the Print Stream palette can be swapped by adding a future data-theme. */ + --bg: #e9e1d2; + --bg-2: #f4eee2; + --panel: #f8f2e6; + --panel-2: #e2d6c3; + --ink: #171513; + --ink-2: #39332d; + --muted: #6e655b; + --line: #cfc0aa; + --line-2: #9f8e78; + --cyan: #176d6c; + --cyan-soft: rgba(23,109,108,.11); + --brand: #c6542d; + --brand-ink: #fff8eb; + --brand-soft: rgba(198,84,45,.13); --pos: #0f9d6b; --neg: #d6293e; --ok: #0f9d6b; @@ -31,20 +32,20 @@ } :root[data-theme="dark"] { - --bg: #0a0b0d; - --bg-2: #0f1114; - --panel: #14161a; - --panel-2: #1a1d22; - --ink: #eef0f2; - --ink-2: #c3c8cf; - --muted: #8d949d; - --line: #272b32; - --line-2: #363b44; - --cyan: #22d3ee; - --cyan-soft: rgba(34,211,238,.1); - --brand: #ff6a2b; - --brand-ink: #0a0b0d; - --brand-soft: rgba(255,106,43,.12); + --bg: #171513; + --bg-2: #211d19; + --panel: #28231d; + --panel-2: #342c23; + --ink: #f5ead8; + --ink-2: #d8c8b2; + --muted: #a99780; + --line: #554737; + --line-2: #806b52; + --cyan: #76c1b1; + --cyan-soft: rgba(118,193,177,.13); + --brand: #e47a4d; + --brand-ink: #211813; + --brand-soft: rgba(228,122,77,.15); --pos: #34d399; --neg: #fb7185; --ok: #34d399; @@ -97,12 +98,33 @@ .katex { max-width: 100%; overflow-x: auto; overflow-y: hidden; padding: 2px 8px; } /* Print Stream Base Components */ + .ps-strip { + border-radius: 0; + border-left: 5px solid var(--brand); + background-image: linear-gradient(90deg, var(--brand-soft), transparent 34%), var(--stripe); + box-shadow: 5px 5px 0 var(--line-2), var(--shadow); + } + .ps-hero { + position: relative; + padding: clamp(10px, 2vw, 22px) 0 18px; + border-bottom: 2px solid var(--ink); + } + .ps-hero::after { + content: ""; + position: absolute; + right: 0; + bottom: -6px; + width: 86px; + height: 10px; + background: repeating-linear-gradient(90deg, var(--brand) 0 5px, transparent 5px 9px); + } + .ps-map, .ps-panel { position: relative; padding: 24px; background: var(--panel); border: 1px solid var(--line); - border-radius: 10px; + border-radius: 0; box-shadow: var(--shadow); overflow: hidden; } diff --git a/components/ui/print-stream.tsx b/components/ui/print-stream.tsx index 86ebaf4..ab21c4c 100644 --- a/components/ui/print-stream.tsx +++ b/components/ui/print-stream.tsx @@ -3,7 +3,7 @@ import React from 'react'; // Barcode strip component export function PsStrip({ eyebrow, id, name }: { eyebrow: string; id: string; name: string }) { return ( -
+
{eyebrow} {id} · {name} @@ -28,7 +28,7 @@ export function PsHero({ conditionSub?: React.ReactNode; }) { return ( -
+
{eyebrow} @@ -59,7 +59,7 @@ export function PsHero({ // Step Map export function PsMap({ steps, title = "3 ta oddiy qadam", eyebrow = "Method map" }: { steps: {n: string, t: React.ReactNode, s: React.ReactNode}[], title?: string, eyebrow?: string }) { return ( -
+
{eyebrow} From 15fa8f358881dc3b7280136b3ff9f2a028134000 Mon Sep 17 00:00:00 2001 From: v0 Date: Sat, 17 Oct 2026 10:01:56 +0000 Subject: [PATCH 4/6] =?UTF-8?q?feat(theme):=20add=20selectable=20visual=20?= =?UTF-8?q?design=20settings=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/globals.css | 22 +++++++- components/theme-toggle.tsx | 102 +++++++++++++++++++++--------------- 2 files changed, 80 insertions(+), 44 deletions(-) diff --git a/app/globals.css b/app/globals.css index 35d647e..5687c00 100644 --- a/app/globals.css +++ b/app/globals.css @@ -31,7 +31,13 @@ --sar: env(safe-area-inset-right, 0px); } -:root[data-theme="dark"] { + :root[data-visual-theme="minimal"] { + --stripe: none; + --shadow: 0 8px 24px rgba(18, 24, 32, .08); + } + + :root[data-theme="dark"] { + --bg: #171513; --bg-2: #211d19; --panel: #28231d; @@ -97,6 +103,20 @@ @layer utilities { .katex { max-width: 100%; overflow-x: auto; overflow-y: hidden; padding: 2px 8px; } + :root[data-visual-theme="minimal"] .ps-strip { + border-left-width: 1px; + box-shadow: var(--shadow); + background-image: none; + } + + :root[data-visual-theme="minimal"] .ps-hero::after, + :root[data-visual-theme="minimal"] .ps-panel::before, + :root[data-visual-theme="minimal"] .ps-panel::after, + :root[data-visual-theme="minimal"] .ps-side-panel::before, + :root[data-visual-theme="minimal"] .ps-side-panel::after { + display: none; + } + /* Print Stream Base Components */ .ps-strip { border-radius: 0; diff --git a/components/theme-toggle.tsx b/components/theme-toggle.tsx index fc00d69..b68f2f6 100644 --- a/components/theme-toggle.tsx +++ b/components/theme-toggle.tsx @@ -1,10 +1,19 @@ 'use client'; -import { Moon, Sun } from 'lucide-react'; -import { useSyncExternalStore } from 'react'; +import { Moon, Palette, Sun } from 'lucide-react'; +import { useEffect, useSyncExternalStore } from 'react'; type Theme = 'light' | 'dark'; +export type VisualTheme = 'print' | 'minimal'; const themeEvent = 'numeric-theme-change'; +const visualThemeEvent = 'numeric-visual-theme-change'; + +function getVisualTheme(): VisualTheme { + if (typeof window === 'undefined') return 'print'; + return window.localStorage.getItem('numeric-visual-theme') === 'minimal' + ? 'minimal' + : 'print'; +} function getTheme(): Theme { if (typeof window === 'undefined') return 'light'; @@ -20,63 +29,70 @@ function subscribe(callback: () => void) { export function ThemeToggle() { const theme = useSyncExternalStore(subscribe, getTheme, () => 'light'); + const visualTheme = useSyncExternalStore( + (callback) => { + window.addEventListener(visualThemeEvent, callback); + return () => window.removeEventListener(visualThemeEvent, callback); + }, + getVisualTheme, + () => 'print', + ); const isDark = theme === 'dark'; - function toggleTheme(event: React.MouseEvent) { - const next: Theme = isDark ? 'light' : 'dark'; + useEffect(() => { + document.documentElement.dataset.visualTheme = visualTheme; + }, [visualTheme]); - // Fallback for browsers that don't support View Transitions - if (!document.startViewTransition) { + function setTheme(next: Theme, event?: React.MouseEvent) { + const apply = () => { document.documentElement.dataset.theme = next; window.localStorage.setItem('numeric-theme', next); window.dispatchEvent(new Event(themeEvent)); + }; + if (!event || !document.startViewTransition) { + apply(); return; } - const x = event.clientX; const y = event.clientY; - const endRadius = Math.hypot( - Math.max(x, innerWidth - x), - Math.max(y, innerHeight - y) - ); - - const transition = document.startViewTransition(() => { - document.documentElement.dataset.theme = next; - window.localStorage.setItem('numeric-theme', next); - window.dispatchEvent(new Event(themeEvent)); - }); - + const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)); + const transition = document.startViewTransition(apply); transition.ready.then(() => { - const clipPath = [ - `circle(0px at ${x}px ${y}px)`, - `circle(${endRadius}px at ${x}px ${y}px)`, - ]; - - // To light: new view expands. To dark: old view shrinks (revealing dark underneath) document.documentElement.animate( - { - clipPath: isDark ? [...clipPath].reverse() : clipPath, - }, - { - duration: 400, - easing: 'cubic-bezier(0.4, 0, 0.2, 1)', - pseudoElement: isDark - ? '::view-transition-old(root)' - : '::view-transition-new(root)', - } + { clipPath: isDark ? [`circle(${endRadius}px at ${x}px ${y}px)`, `circle(0px at ${x}px ${y}px)`] : [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`] }, + { duration: 400, easing: 'cubic-bezier(0.4, 0, 0.2, 1)', pseudoElement: isDark ? '::view-transition-old(root)' : '::view-transition-new(root)' }, ); }); } + function setVisualTheme(next: VisualTheme) { + document.documentElement.dataset.visualTheme = next; + window.localStorage.setItem('numeric-visual-theme', next); + window.dispatchEvent(new Event(visualThemeEvent)); + } + return ( - +
+ +
+ + +
+

Theme sozlamalari

+ +

Tanlovingiz shu qurilmada saqlanadi.

+
+
+
); } From d475c8b0151e400ff94d0921c0ba0710d4940fa2 Mon Sep 17 00:00:00 2001 From: v0 Date: Sat, 17 Oct 2026 10:27:05 +0000 Subject: [PATCH 5/6] Add Green Pixel visual theme --- app/globals.css | 108 +++++++++++++++++++++++++++++++++--- components/theme-toggle.tsx | 10 ++-- 2 files changed, 104 insertions(+), 14 deletions(-) diff --git a/app/globals.css b/app/globals.css index 5687c00..1791eba 100644 --- a/app/globals.css +++ b/app/globals.css @@ -31,9 +31,28 @@ --sar: env(safe-area-inset-right, 0px); } - :root[data-visual-theme="minimal"] { - --stripe: none; - --shadow: 0 8px 24px rgba(18, 24, 32, .08); + :root[data-visual-theme="green-pixel"] { + --bg: #020503; + --bg-2: #061009; + --panel: #07150b; + --panel-2: #0b2111; + --ink: #c7ffd0; + --ink-2: #83d892; + --muted: #4d9d5b; + --line: #174f25; + --line-2: #28783a; + --cyan: #65ff8a; + --cyan-soft: rgba(43, 255, 92, .10); + --brand: #39ff68; + --brand-ink: #011b07; + --brand-soft: rgba(57, 255, 104, .14); + --pos: #39ff68; + --neg: #ff6d6d; + --ok: #39ff68; + --head-bg: rgba(2, 10, 4, .9); + --shadow: 0 0 0 1px rgba(57,255,104,.08), 0 0 34px rgba(30,255,77,.10); + --stripe: radial-gradient(circle, rgba(57,255,104,.35) 1px, transparent 1.5px); + --page-glow: radial-gradient(700px 420px at 75% -10%, rgba(27,255,75,.15), transparent 62%); } :root[data-theme="dark"] { @@ -61,6 +80,30 @@ --page-glow: radial-gradient(900px 400px at 85% -10%, rgba(34,211,238,.08), transparent 60%); } +:root[data-theme="dark"][data-visual-theme="green-pixel"] { + --bg: #020503; + --bg-2: #061009; + --panel: #07150b; + --panel-2: #0b2111; + --ink: #c7ffd0; + --ink-2: #83d892; + --muted: #4d9d5b; + --line: #174f25; + --line-2: #28783a; + --cyan: #65ff8a; + --cyan-soft: rgba(43, 255, 92, .10); + --brand: #39ff68; + --brand-ink: #011b07; + --brand-soft: rgba(57, 255, 104, .14); + --pos: #39ff68; + --neg: #ff6d6d; + --ok: #39ff68; + --head-bg: rgba(2, 10, 4, .9); + --shadow: 0 0 0 1px rgba(57,255,104,.08), 0 0 34px rgba(30,255,77,.10); + --stripe: radial-gradient(circle, rgba(57,255,104,.35) 1px, transparent 1.5px); + --page-glow: radial-gradient(700px 420px at 75% -10%, rgba(27,255,75,.15), transparent 62%); +} + @theme inline { --color-bg: var(--bg); --color-bg-2: var(--bg-2); @@ -103,20 +146,67 @@ @layer utilities { .katex { max-width: 100%; overflow-x: auto; overflow-y: hidden; padding: 2px 8px; } - :root[data-visual-theme="minimal"] .ps-strip { + :root[data-visual-theme="green-pixel"] .ps-strip { border-left-width: 1px; box-shadow: var(--shadow); background-image: none; } - :root[data-visual-theme="minimal"] .ps-hero::after, - :root[data-visual-theme="minimal"] .ps-panel::before, - :root[data-visual-theme="minimal"] .ps-panel::after, - :root[data-visual-theme="minimal"] .ps-side-panel::before, - :root[data-visual-theme="minimal"] .ps-side-panel::after { + :root[data-visual-theme="green-pixel"] .ps-hero::after, + :root[data-visual-theme="green-pixel"] .ps-panel::before, + :root[data-visual-theme="green-pixel"] .ps-panel::after, + :root[data-visual-theme="green-pixel"] .ps-side-panel::before, + :root[data-visual-theme="green-pixel"] .ps-side-panel::after { display: none; } + :root[data-visual-theme="green-pixel"] body, + :root[data-visual-theme="green-pixel"] button, + :root[data-visual-theme="green-pixel"] input, + :root[data-visual-theme="green-pixel"] select { + font-family: ui-monospace, "SFMono-Regular", Consolas, monospace; + } + + :root[data-visual-theme="green-pixel"] body { + background-image: var(--page-glow), radial-gradient(rgba(57,255,104,.13) 1px, transparent 1px); + background-size: auto, 5px 5px; + } + + :root[data-visual-theme="green-pixel"] .ps-strip, + :root[data-visual-theme="green-pixel"] .ps-map, + :root[data-visual-theme="green-pixel"] .ps-panel, + :root[data-visual-theme="green-pixel"] .ps-side-panel { + border-color: var(--line); + border-radius: 2px; + box-shadow: var(--shadow); + background-image: radial-gradient(rgba(57,255,104,.12) .8px, transparent .8px); + background-size: 4px 4px; + } + + :root[data-visual-theme="green-pixel"] .ps-panel::before { + display: block; + width: 32px; + height: 32px; + background: var(--brand); + opacity: .8; + } + + :root[data-visual-theme="green-pixel"] .ps-hero { + border-bottom-color: var(--brand); + text-shadow: 0 0 18px rgba(57,255,104,.18); + } + + :root[data-visual-theme="green-pixel"] .ps-hero h1, + :root[data-visual-theme="green-pixel"] .ps-panel h2 { + letter-spacing: .02em; + text-transform: uppercase; + } + + :root[data-visual-theme="green-pixel"] .ps-barcode { + background: repeating-linear-gradient(90deg, var(--brand) 0 2px, transparent 2px 4px, var(--brand) 4px 5px, transparent 5px 8px); + box-shadow: 0 0 8px rgba(57,255,104,.7); + } + /* Print Stream Base Components */ .ps-strip { border-radius: 0; diff --git a/components/theme-toggle.tsx b/components/theme-toggle.tsx index b68f2f6..bab0b33 100644 --- a/components/theme-toggle.tsx +++ b/components/theme-toggle.tsx @@ -4,14 +4,14 @@ import { Moon, Palette, Sun } from 'lucide-react'; import { useEffect, useSyncExternalStore } from 'react'; type Theme = 'light' | 'dark'; -export type VisualTheme = 'print' | 'minimal'; +export type VisualTheme = 'print' | 'green-pixel'; const themeEvent = 'numeric-theme-change'; const visualThemeEvent = 'numeric-visual-theme-change'; function getVisualTheme(): VisualTheme { if (typeof window === 'undefined') return 'print'; - return window.localStorage.getItem('numeric-visual-theme') === 'minimal' - ? 'minimal' + return window.localStorage.getItem('numeric-visual-theme') === 'green-pixel' + ? 'green-pixel' : 'print'; } @@ -87,10 +87,10 @@ export function ThemeToggle() { Design -

Tanlovingiz shu qurilmada saqlanadi.

+

Print Stream yoki Green Pixel tanlovingiz shu qurilmada saqlanadi.

From eaf36e02b598edf5cfc9d113990d029694ab28e5 Mon Sep 17 00:00:00 2001 From: v0 Date: Sat, 17 Oct 2026 10:34:35 +0000 Subject: [PATCH 6/6] Restore classic Print Stream palette --- app/globals.css | 81 ++++++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 51 deletions(-) diff --git a/app/globals.css b/app/globals.css index 1791eba..7266eaf 100644 --- a/app/globals.css +++ b/app/globals.css @@ -3,21 +3,21 @@ @custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); :root { - /* Semantic tokens: the Print Stream palette can be swapped by adding a future data-theme. */ - --bg: #e9e1d2; - --bg-2: #f4eee2; - --panel: #f8f2e6; - --panel-2: #e2d6c3; - --ink: #171513; - --ink-2: #39332d; - --muted: #6e655b; - --line: #cfc0aa; - --line-2: #9f8e78; - --cyan: #176d6c; - --cyan-soft: rgba(23,109,108,.11); - --brand: #c6542d; - --brand-ink: #fff8eb; - --brand-soft: rgba(198,84,45,.13); + /* Semantic tokens: Green Pixel overrides these without changing classic Print Stream. */ + --bg: #eceef0; + --bg-2: #f6f7f8; + --panel: #fbfbfc; + --panel-2: #f1f2f4; + --ink: #0d0f12; + --ink-2: #2a2e35; + --muted: #5d646e; + --line: #d5d9de; + --line-2: #b9bfc7; + --cyan: #0891b2; + --cyan-soft: rgba(8,145,178,.09); + --brand: #e8480c; + --brand-ink: #ffffff; + --brand-soft: rgba(232,72,12,.09); --pos: #0f9d6b; --neg: #d6293e; --ok: #0f9d6b; @@ -57,20 +57,20 @@ :root[data-theme="dark"] { - --bg: #171513; - --bg-2: #211d19; - --panel: #28231d; - --panel-2: #342c23; - --ink: #f5ead8; - --ink-2: #d8c8b2; - --muted: #a99780; - --line: #554737; - --line-2: #806b52; - --cyan: #76c1b1; - --cyan-soft: rgba(118,193,177,.13); - --brand: #e47a4d; - --brand-ink: #211813; - --brand-soft: rgba(228,122,77,.15); + --bg: #0a0b0d; + --bg-2: #0f1114; + --panel: #14161a; + --panel-2: #1a1d22; + --ink: #eef0f2; + --ink-2: #c3c8cf; + --muted: #8d949d; + --line: #272b32; + --line-2: #363b44; + --cyan: #22d3ee; + --cyan-soft: rgba(34,211,238,.1); + --brand: #ff6a2b; + --brand-ink: #0a0b0d; + --brand-soft: rgba(255,106,43,.12); --pos: #34d399; --neg: #fb7185; --ok: #34d399; @@ -208,33 +208,12 @@ } /* Print Stream Base Components */ - .ps-strip { - border-radius: 0; - border-left: 5px solid var(--brand); - background-image: linear-gradient(90deg, var(--brand-soft), transparent 34%), var(--stripe); - box-shadow: 5px 5px 0 var(--line-2), var(--shadow); - } - .ps-hero { - position: relative; - padding: clamp(10px, 2vw, 22px) 0 18px; - border-bottom: 2px solid var(--ink); - } - .ps-hero::after { - content: ""; - position: absolute; - right: 0; - bottom: -6px; - width: 86px; - height: 10px; - background: repeating-linear-gradient(90deg, var(--brand) 0 5px, transparent 5px 9px); - } - .ps-map, .ps-panel { position: relative; padding: 24px; background: var(--panel); border: 1px solid var(--line); - border-radius: 0; + border-radius: 10px; box-shadow: var(--shadow); overflow: hidden; }