diff --git a/.gitignore b/.gitignore index 3c3629e..85c2d1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,10 @@ node_modules + +# Reference source (legacy Next.js design in refs/): branding icons are not needed +refs/public/icon.svg +refs/public/icon-dark-32x32.png +refs/public/icon-light-32x32.png +refs/public/apple-icon.png +refs/public/placeholder-logo.svg +refs/public/placeholder-logo.png +refs/public/placeholder.svg diff --git a/package.json b/package.json index 2111171..3d58cef 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "test": "echo \"Error: no test specified\" && exit 1", "dev": "pnpm --dir web dev", "build": "pnpm --dir web build", - "format": "pnpm --dir web format" + "format": "pnpm --dir web format", + "html": "pnpm --dir refs build && node scripts/extract-static.mjs refs/.next/server/app refs-html" }, "keywords": [], "author": "Ku6epXBOCTuK", diff --git a/refs-html/background-remover.html b/refs-html/background-remover.html index aa8b73d..3c578aa 100644 --- a/refs-html/background-remover.html +++ b/refs-html/background-remover.html @@ -7,11 +7,6 @@ @layer properties { @supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) { *,:before,:after,::backdrop { - --tw-rotate-x:initial; - --tw-rotate-y:initial; - --tw-rotate-z:initial; - --tw-skew-x:initial; - --tw-skew-y:initial; --tw-border-style:solid; --tw-font-weight:initial; --tw-shadow:0 0 #0000; @@ -290,13 +285,7 @@ button,input:where([type=button],[type=reset],[type=submit]) { } @layer components; @layer utilities { - .static { - position:static -} -.inline { - display:inline -} -.inline-flex { + .inline-flex { display:inline-flex } .size-6 { @@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) { .shrink-0 { flex-shrink:0 } -.transform { - transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,) -} .items-center { align-items:center } @@ -630,7 +616,7 @@ button { --line:#33414c; --muted:#91a0ac; --blue:#54a2ff; - background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px) + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer { align-items:center; @@ -643,6 +629,26 @@ button { height:64px; padding:0 clamp(20px,4vw,64px) } +.topbar>.brand { + color:var(--foreground); + text-decoration:none +} +.top-nav { + align-items:center; + gap:22px; + margin-left:auto; + margin-right:28px; + display:flex +} +.top-nav a { + color:var(--muted); + font:10px var(--font-mono); + white-space:nowrap; + text-decoration:none +} +.top-nav a:hover,.top-nav a.active { + color:var(--blue) +} .brand { font:600 14px var(--font-mono); gap:10px @@ -1103,6 +1109,9 @@ h1 { gap:32px } +} +.dark-mode .app-shell { + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .dark-mode .tile-canvas { background-color:#202a31; @@ -1113,7 +1122,22 @@ h1 { } @media (max-width:800px) { .topbar { - padding:0 16px + flex-wrap:wrap; + gap:12px; + height:auto; + min-height:64px; + padding:12px 16px +} +.top-nav { + order:3; + gap:12px; + width:100%; + margin:0; + padding-bottom:2px; + overflow:auto +} +.top-nav a { + font-size:9px } .status { display:none @@ -1532,9 +1556,9 @@ h1 { } .catalog-page { width:100%; - max-width:1680px; - margin:0 auto; - padding:64px clamp(24px,4vw,72px) 72px + max-width:none; + margin:0; + padding:60px clamp(24px,4vw,72px) 72px } .catalog-head { border-bottom:1px solid var(--line); @@ -1803,26 +1827,6 @@ h1 { gap:12px 18px } -} -@property --tw-rotate-x { - syntax:"*"; - inherits:false -} -@property --tw-rotate-y { - syntax:"*"; - inherits:false -} -@property --tw-rotate-z { - syntax:"*"; - inherits:false -} -@property --tw-skew-x { - syntax:"*"; - inherits:false -} -@property --tw-skew-y { - syntax:"*"; - inherits:false } @property --tw-border-style { syntax:"*"; @@ -1984,43 +1988,57 @@ h1 { -
+
- + +
- AUTO PROCESSING + + AUTO PROCESSING - + / + + +
diff --git a/refs-html/demo.html b/refs-html/demo.html index 195baa5..64c5d3e 100644 --- a/refs-html/demo.html +++ b/refs-html/demo.html @@ -7,11 +7,6 @@ @layer properties { @supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) { *,:before,:after,::backdrop { - --tw-rotate-x:initial; - --tw-rotate-y:initial; - --tw-rotate-z:initial; - --tw-skew-x:initial; - --tw-skew-y:initial; --tw-border-style:solid; --tw-font-weight:initial; --tw-shadow:0 0 #0000; @@ -290,13 +285,7 @@ button,input:where([type=button],[type=reset],[type=submit]) { } @layer components; @layer utilities { - .static { - position:static -} -.inline { - display:inline -} -.inline-flex { + .inline-flex { display:inline-flex } .size-6 { @@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) { .shrink-0 { flex-shrink:0 } -.transform { - transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,) -} .items-center { align-items:center } @@ -630,7 +616,7 @@ button { --line:#33414c; --muted:#91a0ac; --blue:#54a2ff; - background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px) + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer { align-items:center; @@ -643,6 +629,26 @@ button { height:64px; padding:0 clamp(20px,4vw,64px) } +.topbar>.brand { + color:var(--foreground); + text-decoration:none +} +.top-nav { + align-items:center; + gap:22px; + margin-left:auto; + margin-right:28px; + display:flex +} +.top-nav a { + color:var(--muted); + font:10px var(--font-mono); + white-space:nowrap; + text-decoration:none +} +.top-nav a:hover,.top-nav a.active { + color:var(--blue) +} .brand { font:600 14px var(--font-mono); gap:10px @@ -1103,6 +1109,9 @@ h1 { gap:32px } +} +.dark-mode .app-shell { + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .dark-mode .tile-canvas { background-color:#202a31; @@ -1113,7 +1122,22 @@ h1 { } @media (max-width:800px) { .topbar { - padding:0 16px + flex-wrap:wrap; + gap:12px; + height:auto; + min-height:64px; + padding:12px 16px +} +.top-nav { + order:3; + gap:12px; + width:100%; + margin:0; + padding-bottom:2px; + overflow:auto +} +.top-nav a { + font-size:9px } .status { display:none @@ -1532,9 +1556,9 @@ h1 { } .catalog-page { width:100%; - max-width:1680px; - margin:0 auto; - padding:64px clamp(24px,4vw,72px) 72px + max-width:none; + margin:0; + padding:60px clamp(24px,4vw,72px) 72px } .catalog-head { border-bottom:1px solid var(--line); @@ -1803,26 +1827,6 @@ h1 { gap:12px 18px } -} -@property --tw-rotate-x { - syntax:"*"; - inherits:false -} -@property --tw-rotate-y { - syntax:"*"; - inherits:false -} -@property --tw-rotate-z { - syntax:"*"; - inherits:false -} -@property --tw-skew-x { - syntax:"*"; - inherits:false -} -@property --tw-skew-y { - syntax:"*"; - inherits:false } @property --tw-border-style { syntax:"*"; @@ -1986,18 +1990,30 @@ h1 {
- + +
- AUTO PIPELINE + + AUTO PIPELINE -
diff --git a/refs-html/gradient.html b/refs-html/gradient.html index e5bf73d..1ff30c0 100644 --- a/refs-html/gradient.html +++ b/refs-html/gradient.html @@ -7,11 +7,6 @@ @layer properties { @supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) { *,:before,:after,::backdrop { - --tw-rotate-x:initial; - --tw-rotate-y:initial; - --tw-rotate-z:initial; - --tw-skew-x:initial; - --tw-skew-y:initial; --tw-border-style:solid; --tw-font-weight:initial; --tw-shadow:0 0 #0000; @@ -290,13 +285,7 @@ button,input:where([type=button],[type=reset],[type=submit]) { } @layer components; @layer utilities { - .static { - position:static -} -.inline { - display:inline -} -.inline-flex { + .inline-flex { display:inline-flex } .size-6 { @@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) { .shrink-0 { flex-shrink:0 } -.transform { - transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,) -} .items-center { align-items:center } @@ -630,7 +616,7 @@ button { --line:#33414c; --muted:#91a0ac; --blue:#54a2ff; - background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px) + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer { align-items:center; @@ -643,6 +629,26 @@ button { height:64px; padding:0 clamp(20px,4vw,64px) } +.topbar>.brand { + color:var(--foreground); + text-decoration:none +} +.top-nav { + align-items:center; + gap:22px; + margin-left:auto; + margin-right:28px; + display:flex +} +.top-nav a { + color:var(--muted); + font:10px var(--font-mono); + white-space:nowrap; + text-decoration:none +} +.top-nav a:hover,.top-nav a.active { + color:var(--blue) +} .brand { font:600 14px var(--font-mono); gap:10px @@ -1103,6 +1109,9 @@ h1 { gap:32px } +} +.dark-mode .app-shell { + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .dark-mode .tile-canvas { background-color:#202a31; @@ -1113,7 +1122,22 @@ h1 { } @media (max-width:800px) { .topbar { - padding:0 16px + flex-wrap:wrap; + gap:12px; + height:auto; + min-height:64px; + padding:12px 16px +} +.top-nav { + order:3; + gap:12px; + width:100%; + margin:0; + padding-bottom:2px; + overflow:auto +} +.top-nav a { + font-size:9px } .status { display:none @@ -1532,9 +1556,9 @@ h1 { } .catalog-page { width:100%; - max-width:1680px; - margin:0 auto; - padding:64px clamp(24px,4vw,72px) 72px + max-width:none; + margin:0; + padding:60px clamp(24px,4vw,72px) 72px } .catalog-head { border-bottom:1px solid var(--line); @@ -1803,26 +1827,6 @@ h1 { gap:12px 18px } -} -@property --tw-rotate-x { - syntax:"*"; - inherits:false -} -@property --tw-rotate-y { - syntax:"*"; - inherits:false -} -@property --tw-rotate-z { - syntax:"*"; - inherits:false -} -@property --tw-skew-x { - syntax:"*"; - inherits:false -} -@property --tw-skew-y { - syntax:"*"; - inherits:false } @property --tw-border-style { syntax:"*"; @@ -1984,39 +1988,57 @@ h1 { -
+
- + +
- + +
+ + / + + +
diff --git a/refs-html/index.html b/refs-html/index.html index 195baa5..28aa2d4 100644 --- a/refs-html/index.html +++ b/refs-html/index.html @@ -7,11 +7,6 @@ @layer properties { @supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) { *,:before,:after,::backdrop { - --tw-rotate-x:initial; - --tw-rotate-y:initial; - --tw-rotate-z:initial; - --tw-skew-x:initial; - --tw-skew-y:initial; --tw-border-style:solid; --tw-font-weight:initial; --tw-shadow:0 0 #0000; @@ -290,13 +285,7 @@ button,input:where([type=button],[type=reset],[type=submit]) { } @layer components; @layer utilities { - .static { - position:static -} -.inline { - display:inline -} -.inline-flex { + .inline-flex { display:inline-flex } .size-6 { @@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) { .shrink-0 { flex-shrink:0 } -.transform { - transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,) -} .items-center { align-items:center } @@ -630,7 +616,7 @@ button { --line:#33414c; --muted:#91a0ac; --blue:#54a2ff; - background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px) + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer { align-items:center; @@ -643,6 +629,26 @@ button { height:64px; padding:0 clamp(20px,4vw,64px) } +.topbar>.brand { + color:var(--foreground); + text-decoration:none +} +.top-nav { + align-items:center; + gap:22px; + margin-left:auto; + margin-right:28px; + display:flex +} +.top-nav a { + color:var(--muted); + font:10px var(--font-mono); + white-space:nowrap; + text-decoration:none +} +.top-nav a:hover,.top-nav a.active { + color:var(--blue) +} .brand { font:600 14px var(--font-mono); gap:10px @@ -1103,6 +1109,9 @@ h1 { gap:32px } +} +.dark-mode .app-shell { + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .dark-mode .tile-canvas { background-color:#202a31; @@ -1113,7 +1122,22 @@ h1 { } @media (max-width:800px) { .topbar { - padding:0 16px + flex-wrap:wrap; + gap:12px; + height:auto; + min-height:64px; + padding:12px 16px +} +.top-nav { + order:3; + gap:12px; + width:100%; + margin:0; + padding-bottom:2px; + overflow:auto +} +.top-nav a { + font-size:9px } .status { display:none @@ -1532,9 +1556,9 @@ h1 { } .catalog-page { width:100%; - max-width:1680px; - margin:0 auto; - padding:64px clamp(24px,4vw,72px) 72px + max-width:none; + margin:0; + padding:60px clamp(24px,4vw,72px) 72px } .catalog-head { border-bottom:1px solid var(--line); @@ -1803,26 +1827,6 @@ h1 { gap:12px 18px } -} -@property --tw-rotate-x { - syntax:"*"; - inherits:false -} -@property --tw-rotate-y { - syntax:"*"; - inherits:false -} -@property --tw-rotate-z { - syntax:"*"; - inherits:false -} -@property --tw-skew-x { - syntax:"*"; - inherits:false -} -@property --tw-skew-y { - syntax:"*"; - inherits:false } @property --tw-border-style { syntax:"*"; @@ -1986,18 +1990,30 @@ h1 {
- + +
- AUTO PIPELINE + + AUTO PIPELINE -
diff --git a/refs-html/list-tools.html b/refs-html/list-tools.html index cf0ea3a..d8ba64a 100644 --- a/refs-html/list-tools.html +++ b/refs-html/list-tools.html @@ -7,11 +7,6 @@ @layer properties { @supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) { *,:before,:after,::backdrop { - --tw-rotate-x:initial; - --tw-rotate-y:initial; - --tw-rotate-z:initial; - --tw-skew-x:initial; - --tw-skew-y:initial; --tw-border-style:solid; --tw-font-weight:initial; --tw-shadow:0 0 #0000; @@ -290,13 +285,7 @@ button,input:where([type=button],[type=reset],[type=submit]) { } @layer components; @layer utilities { - .static { - position:static -} -.inline { - display:inline -} -.inline-flex { + .inline-flex { display:inline-flex } .size-6 { @@ -330,9 +319,6 @@ button,input:where([type=button],[type=reset],[type=submit]) { .shrink-0 { flex-shrink:0 } -.transform { - transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,) -} .items-center { align-items:center } @@ -630,7 +616,7 @@ button { --line:#33414c; --muted:#91a0ac; --blue:#54a2ff; - background-image:linear-gradient(#1b252d 1px,#0000 1px),linear-gradient(90deg,#1b252d 1px,#0000 1px) + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer { align-items:center; @@ -643,6 +629,26 @@ button { height:64px; padding:0 clamp(20px,4vw,64px) } +.topbar>.brand { + color:var(--foreground); + text-decoration:none +} +.top-nav { + align-items:center; + gap:22px; + margin-left:auto; + margin-right:28px; + display:flex +} +.top-nav a { + color:var(--muted); + font:10px var(--font-mono); + white-space:nowrap; + text-decoration:none +} +.top-nav a:hover,.top-nav a.active { + color:var(--blue) +} .brand { font:600 14px var(--font-mono); gap:10px @@ -1103,6 +1109,9 @@ h1 { gap:32px } +} +.dark-mode .app-shell { + background-image:linear-gradient(#1e2a3447 1px,#0000 1px),linear-gradient(90deg,#1e2a3447 1px,#0000 1px) } .dark-mode .tile-canvas { background-color:#202a31; @@ -1113,7 +1122,22 @@ h1 { } @media (max-width:800px) { .topbar { - padding:0 16px + flex-wrap:wrap; + gap:12px; + height:auto; + min-height:64px; + padding:12px 16px +} +.top-nav { + order:3; + gap:12px; + width:100%; + margin:0; + padding-bottom:2px; + overflow:auto +} +.top-nav a { + font-size:9px } .status { display:none @@ -1532,9 +1556,9 @@ h1 { } .catalog-page { width:100%; - max-width:1680px; - margin:0 auto; - padding:64px clamp(24px,4vw,72px) 72px + max-width:none; + margin:0; + padding:60px clamp(24px,4vw,72px) 72px } .catalog-head { border-bottom:1px solid var(--line); @@ -1803,26 +1827,6 @@ h1 { gap:12px 18px } -} -@property --tw-rotate-x { - syntax:"*"; - inherits:false -} -@property --tw-rotate-y { - syntax:"*"; - inherits:false -} -@property --tw-rotate-z { - syntax:"*"; - inherits:false -} -@property --tw-skew-x { - syntax:"*"; - inherits:false -} -@property --tw-skew-y { - syntax:"*"; - inherits:false } @property --tw-border-style { syntax:"*"; @@ -1984,923 +1988,965 @@ h1 { -
-
- easy-png-tools +
+
+ + EP + + easy-png-tools + + / + CATALOG + -
-
-
-
EASY-PNG-TOOLS / CATALOG -
-

Tool catalog -

-

Focused utilities for working with PNG. Inspect, transform, and export — locally in your browser. -

-
-
- 32 - - TOOLS -
AVAILABLE +
+ + + + LOCAL MODE / READY + + +
+ + / + + +
-
-
- -
- - - - - - - - +
+
+
+
+
EASY-PNG-TOOLS / CATALOG +
+

Tool catalog +

+

Focused utilities for working with PNG. Inspect, transform, and export — locally in your browser. +

+
+
+ 32 + + TOOLS +
AVAILABLE +
+
+
+ +
+ + + + + + + + +
+
+
+
+
+ CONVERT + + 05 + TOOLS + +
+ +
+
+
+ TRANSPARENCY + + 05 + TOOLS + +
+ +
+
+
+ COLOR + + 05 + TOOLS + +
+ +
+
+
+ GEOMETRY + + 05 + TOOLS + +
+ +
+
+
+ FILTERS + + 04 + TOOLS + +
+ +
+
+
+ ANALYZE + + 04 + TOOLS + +
+ +
+
+
ALL OPERATIONS RUN LOCALLY + • + YOUR FILES NEVER LEAVE THIS DEVICE +
-
-
-
- CONVERT - - 05 - TOOLS - -
- -
-
-
- TRANSPARENCY - - 05 - TOOLS - -
- -
-
-
- COLOR - - 05 - TOOLS - -
- -
-
-
- GEOMETRY - - 05 - TOOLS - -
- -
-
-
- FILTERS - - 04 - TOOLS - -
- -
-
-
- ANALYZE - - 04 - TOOLS - -
- -
-
-
ALL OPERATIONS RUN LOCALLY - • - YOUR FILES NEVER LEAVE THIS DEVICE -
diff --git a/refs/app/easy-png-tools/background-remover/page.tsx b/refs/app/easy-png-tools/background-remover/page.tsx index 68c8550..3de1776 100644 --- a/refs/app/easy-png-tools/background-remover/page.tsx +++ b/refs/app/easy-png-tools/background-remover/page.tsx @@ -1,20 +1,20 @@ 'use client' +import TopBar from '@/components/top-bar' import { useMemo, useState } from 'react' -import { Download, Moon, RotateCcw, Sun, Upload, Check } from 'lucide-react' +import { Download, RotateCcw, Upload, Check } from 'lucide-react' export default function BackgroundRemoverPage() { const [color, setColor] = useState('#E8EEF2') const [similarity, setSimilarity] = useState(72) const [outerOnly, setOuterOnly] = useState(true) const [showMask, setShowMask] = useState(false) - const [dark, setDark] = useState(true) const [downloaded, setDownloaded] = useState(false) const previewBackground = showMask ? 'repeating-conic-gradient(#7b8791 0 25%, #cbd3da 0 50%) 50% / 28px 28px' : 'repeating-conic-gradient(#d7dce0 0 25%, #f3f5f6 0 50%) 50% / 28px 28px' const subjectStyle = useMemo(() => ({ background: showMask ? '#596773' : 'linear-gradient(145deg,#1769d2 0 38%,#00a8c7 38% 66%,#bd7411 66%)', opacity: showMask ? .88 : 1, clipPath: `polygon(23% 11%, 73% 8%, 89% 30%, 79% 81%, 52% 93%, 17% 78%, 8% 39%)` }), [showMask]) const reset = () => { setColor('#E8EEF2'); setSimilarity(72); setOuterOnly(true); setShowMask(false) } - return
-
EPeasy-png-tools/ BACKGROUND REMOVER
AUTO PROCESSING
+ return
+
PNG PROCESSING / SINGLE TOOL

Remove background.

Select a background color and tune the edge detection. Changes are processed automatically in your browser.

LIVE PREVIEW
REMOVER SETTINGSConfigure detection
TOOL 02
setColor(e.target.value)} /> setColor(e.target.value)} aria-label="Choose background color" />
sampled from image background
diff --git a/refs/app/easy-png-tools/gradient/page.tsx b/refs/app/easy-png-tools/gradient/page.tsx index 401a55d..a0fbe1f 100644 --- a/refs/app/easy-png-tools/gradient/page.tsx +++ b/refs/app/easy-png-tools/gradient/page.tsx @@ -1,7 +1,8 @@ 'use client' +import TopBar from '@/components/top-bar' import { useMemo, useState } from 'react' -import { Check, ChevronDown, Copy, Download, Moon, RotateCcw, Sun } from 'lucide-react' +import { Check, ChevronDown, Copy, Download, RotateCcw } from 'lucide-react' const directions = ['0° →', '45° ↗', '90° ↑', '135° ↖', '180° ←', '225° ↙', '270° ↓', '315° ↘'] @@ -11,14 +12,13 @@ export default function GradientPage() { const [direction, setDirection] = useState(135) const [opacity, setOpacity] = useState(100) const [type, setType] = useState<'linear' | 'radial'>('linear') - const [dark, setDark] = useState(true) const [copied, setCopied] = useState(false) const gradient = useMemo(() => type === 'linear' ? `linear-gradient(${direction}deg, ${start} 0%, ${end} 100%)` : `radial-gradient(circle, ${start} 0%, ${end} 100%)`, [direction, end, start, type]) const css = `background: ${gradient};\nopacity: ${opacity / 100};` const reset = () => { setStart('#1769D2'); setEnd('#00A8C7'); setDirection(135); setOpacity(100); setType('linear') } const copyCss = async () => { await navigator.clipboard?.writeText(css); setCopied(true); setTimeout(() => setCopied(false), 1400) } - return
-
EPeasy-png-tools/ GRADIENT
+ return
+
PNG PROCESSING / SINGLE TOOL

Gradient background.

Create a clean, export-ready gradient with precise control over color, direction and transparency.

LIVE PREVIEW
GRADIENT SETTINGSConfigure output
TOOL 01
diff --git a/refs/app/easy-png-tools/list-tools/page.tsx b/refs/app/easy-png-tools/list-tools/page.tsx index d7d2351..17d31d7 100644 --- a/refs/app/easy-png-tools/list-tools/page.tsx +++ b/refs/app/easy-png-tools/list-tools/page.tsx @@ -1,5 +1,6 @@ "use client" +import TopBar from '@/components/top-bar' import Link from "next/link" import { useMemo, useState } from "react" import { ArrowUpRight, FileImage, Filter, Search, Sparkles } from "lucide-react" @@ -17,11 +18,11 @@ export default function ListToolsPage() { const [query, setQuery] = useState("") const [active, setActive] = useState("ALL") const filtered = useMemo(() => groups.map(group => ({ ...group, tools: group.tools.filter(([name, description]) => (active === "ALL" || active === group.name) && `${name} ${description}`.toLowerCase().includes(query.toLowerCase())) })).filter(group => group.tools.length), [query, active]) - return
easy-png-toolsLOCAL MODE / READY
+ return
EASY-PNG-TOOLS / CATALOG

Tool catalog

Focused utilities for working with PNG. Inspect, transform, and export — locally in your browser.

32TOOLS
AVAILABLE
{["ALL", ...groups.map(g => g.name)].map(name => )}
{filtered.map(group =>
{group.name}{String(group.tools.length).padStart(2, "0")} TOOLS
{group.tools.map(([name, description, href], index) => { if (!href) e.preventDefault() }}>{name}{description}{String(index + 1).padStart(2, "0")})}
)}
{!filtered.length &&
No tools match your search.
}
ALL OPERATIONS RUN LOCALLY YOUR FILES NEVER LEAVE THIS DEVICE
-
+
} diff --git a/refs/app/globals.css b/refs/app/globals.css index 3e1e0d5..2b1aac9 100644 --- a/refs/app/globals.css +++ b/refs/app/globals.css @@ -4,12 +4,12 @@ @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --color-border: var(--line); --font-sans: 'IBM Plex Sans', sans-serif; --font-mono: 'IBM Plex Mono', monospace; } :root { color-scheme: light; --background:#eef1f4; --foreground:#17212b; --panel:#f8fafb; --line:#cbd3da; --muted:#6d7883; --blue:#1769d2; --cyan:#00a8c7; --amber:#bd7411; --radius:4px; } * { box-sizing:border-box; border-color:var(--line); } html { background:var(--background); } body { margin:0; background:var(--background); color:var(--foreground); font-family:var(--font-sans); } button,input { font:inherit; } button { cursor:pointer; } -.app-shell { min-height:100vh; background-color:var(--background); background-image:linear-gradient(#dce2e7 1px,transparent 1px),linear-gradient(90deg,#dce2e7 1px,transparent 1px); background-size:32px 32px; }.dark-mode { --background:#11171d; --foreground:#e8eef2; --panel:#182129; --line:#33414c; --muted:#91a0ac; --blue:#54a2ff; background-image:linear-gradient(#1b252d 1px,transparent 1px),linear-gradient(90deg,#1b252d 1px,transparent 1px); } -.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer { display:flex; align-items:center; }.topbar { height:64px; border-bottom:1px solid var(--line); background:var(--panel); justify-content:space-between; padding:0 clamp(20px,4vw,64px); }.brand { gap:10px; font:600 14px var(--font-mono); }.brand-mark { display:grid; place-items:center; width:30px; height:30px; background:var(--blue); color:white; font-size:11px; }.version,.label,.step-type,.eyebrow { font:10px var(--font-mono); letter-spacing:.12em; color:var(--muted); }.version,.eyebrow { color:var(--blue); }.top-actions { gap:16px; }.status { gap:7px; color:var(--muted); font:10px var(--font-mono); letter-spacing:.08em; }.status i,.auto-note i { width:6px; height:6px; background:#25a96a; border-radius:50%; }.icon-btn { display:grid; place-items:center; border:0; background:transparent; color:var(--muted); padding:6px; }.language { border:1px solid var(--line); }.language button { border:0; background:transparent; padding:6px 9px; color:var(--muted); font:10px var(--font-mono); }.language .active { background:var(--foreground); color:var(--background); } +.app-shell { min-height:100vh; background-color:var(--background); background-image:linear-gradient(#dce2e7 1px,transparent 1px),linear-gradient(90deg,#dce2e7 1px,transparent 1px); background-size:32px 32px; }.dark-mode { --background:#11171d; --foreground:#e8eef2; --panel:#182129; --line:#33414c; --muted:#91a0ac; --blue:#54a2ff; background-image:linear-gradient(rgba(30,42,52,.28) 1px,transparent 1px),linear-gradient(90deg,rgba(30,42,52,.28) 1px,transparent 1px); } +.topbar,.brand,.top-actions,.language,.status,.title-row,.pipeline-head,.step-heading,.step-tools,.pipeline-footer,.preview-top,.footer { display:flex; align-items:center; }.topbar { height:64px; border-bottom:1px solid var(--line); background:var(--panel); justify-content:space-between; padding:0 clamp(20px,4vw,64px); }.topbar > .brand { color:var(--foreground); text-decoration:none; }.top-nav { display:flex; align-items:center; gap:22px; margin-left:auto; margin-right:28px; }.top-nav a { color:var(--muted); font:10px var(--font-mono); text-decoration:none; white-space:nowrap; }.top-nav a:hover,.top-nav a.active { color:var(--blue); }.brand { gap:10px; font:600 14px var(--font-mono); }.brand-mark { display:grid; place-items:center; width:30px; height:30px; background:var(--blue); color:white; font-size:11px; }.version,.label,.step-type,.eyebrow { font:10px var(--font-mono); letter-spacing:.12em; color:var(--muted); }.version,.eyebrow { color:var(--blue); }.top-actions { gap:16px; }.status { gap:7px; color:var(--muted); font:10px var(--font-mono); letter-spacing:.08em; }.status i,.auto-note i { width:6px; height:6px; background:#25a96a; border-radius:50%; }.icon-btn { display:grid; place-items:center; border:0; background:transparent; color:var(--muted); padding:6px; }.language { border:1px solid var(--line); }.language button { border:0; background:transparent; padding:6px 9px; color:var(--muted); font:10px var(--font-mono); }.language .active { background:var(--foreground); color:var(--background); } .page-grid { width:100%; max-width:none; margin:auto; padding:60px clamp(24px,4vw,72px) 72px; display:grid; grid-template-columns:minmax(0,1.05fr) minmax(520px,.95fr); gap:56px; align-items:start; }.preview-panel { position:sticky; top:24px; margin-top:0; min-width:0; }.preview-top { justify-content:space-between; border-bottom:1px solid var(--line); padding-bottom:14px; }.preview-actions { display:flex; align-items:center; gap:18px; }.preview-meta { display:flex; gap:24px; }.preview-meta div { display:grid; gap:5px; }.preview-meta span { font:10px var(--font-mono); color:var(--muted); }.preview-meta b { font:600 11px var(--font-mono); }.workspace,.preview-panel { min-width:0; }.preview-stack { display:grid; width:100%; min-width:0; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }.preview-tile { width:100%; min-width:0; overflow:hidden; }.history-toggle { display:flex; align-items:center; justify-content:center; gap:8px; width:100%; margin-top:18px; padding:11px 14px; border:1px solid var(--line); background:transparent; color:var(--muted); font:10px var(--font-mono); letter-spacing:.04em; }.history-toggle:hover { color:var(--foreground); background:var(--panel); }.top-toggle { width:auto; margin:0; padding:8px 10px; }.history-toggle .rotated { transform:rotate(180deg); }.tile-canvas { width:100%; min-width:0; min-height:clamp(300px,22vw,430px); overflow:hidden; }.image-preview { max-width:100%; min-width:0; overflow:hidden; }.eyebrow { margin-bottom:18px; }.eyebrow span { color:var(--muted); margin:0 7px; }.title-row { justify-content:space-between; align-items:flex-end; gap:30px; margin-bottom:56px; }h1 { font-size:clamp(36px,4vw,64px); line-height:1; letter-spacing:-.06em; margin:0 0 16px; max-width:700px; font-weight:650; }.lede { color:var(--muted); margin:0; max-width:550px; line-height:1.6; }.file-chip { white-space:nowrap; display:flex; align-items:center; gap:8px; border:1px solid var(--line); background:var(--panel); padding:10px 12px; font:11px var(--font-mono); color:var(--muted); }.file-chip b { color:var(--blue); font-weight:500; }.pipeline-head { justify-content:space-between; border-bottom:1px solid var(--line); padding-bottom:12px; }.pipeline-head strong,.preview-top strong { display:block; font:600 14px var(--font-mono); margin-top:5px; }.pipeline-head em { color:#25a96a; font-style:normal; font-size:10px; }.add-btn,.reset-btn { border:0; background:transparent; color:var(--blue); display:flex; align-items:center; gap:7px; font-size:12px; }.steps-list { padding-top:14px; display:grid; gap:10px; }.step-card { display:grid; grid-template-columns:46px 20px 1fr; min-height:138px; border:1px solid var(--line); background:var(--panel); }.step-index { font:11px var(--font-mono); color:var(--blue); padding:17px 0 0 15px; }.drag { color:var(--line); margin-top:17px; }.step-body { padding:15px 18px 18px; }.step-heading { justify-content:space-between; gap:15px; }.step-heading h2 { font:600 15px var(--font-mono); margin:5px 0 18px; }.step-tools { gap:13px; }.step-tools button { border:0; background:none; color:var(--muted); }.check { color:#238354; font:10px var(--font-mono); display:flex; align-items:center; gap:4px; }.controls { display:grid; grid-template-columns:1.1fr 1fr 1.2fr; gap:16px; }.controls.compact { grid-template-columns:1fr 1fr; }.control-block label { display:flex; justify-content:space-between; margin-bottom:8px; color:var(--muted); font:10px var(--font-mono); letter-spacing:.08em; }.control-block output { color:var(--foreground); }.color-field { display:flex; align-items:center; gap:8px; border:1px solid var(--line); height:32px; padding:0 8px; }.swatch { width:14px; height:14px; border:1px solid var(--line); }.swatch.dark { background:#16202b; }.color-field input { min-width:0; flex:1; border:0; outline:0; color:var(--foreground); background:transparent; font:11px var(--font-mono); }.control-block input[type=range] { width:100%; accent-color:var(--blue); }.segmented { display:flex; border:1px solid var(--line); height:32px; }.segmented button { flex:1; border:0; border-right:1px solid var(--line); background:transparent; color:var(--muted); font:10px var(--font-mono); }.segmented .selected { background:var(--blue); color:white; }.transform-note,.auto-note { display:flex; align-items:center; gap:8px; color:var(--muted); font:11px var(--font-mono); }.pipeline-footer { justify-content:space-between; padding-top:18px; }.auto-note { color:var(--muted); }.auto-note i { display:inline-block; }.preview-panel { position:sticky; top:24px; align-self:start; border:1px solid var(--line); background:var(--panel); padding:18px; }.preview-top { justify-content:space-between; border-bottom:1px solid var(--line); padding-bottom:15px; }.preview-stack { display:grid; grid-template-columns:1fr 1fr; gap:12px; padding:16px 0; }.preview-tile { border:1px solid var(--line); background:var(--background); }.preview-tile.active { border-color:var(--blue); }.tile-canvas { aspect-ratio:1.35; display:grid; place-items:center; padding:16px; background-color:#e4e8eb; background-image:linear-gradient(45deg,#d2d8dc 25%,transparent 25%),linear-gradient(-45deg,#d2d8dc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#d2d8dc 75%),linear-gradient(-45deg,transparent 75%,#d2d8dc 75%); background-size:14px 14px; background-position:0 0,0 7px,7px -7px,-7px 0; }.image-preview { width:80%; aspect-ratio:1.5; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px; color:#16202b; font:600 10px var(--font-mono); }.sample-icon { border:1px solid currentColor; padding:3px 5px; font-size:9px; }.tile-label { display:flex; justify-content:space-between; gap:8px; padding:8px; border-top:1px solid var(--line); font:9px var(--font-mono); color:var(--blue); }.tile-label b { color:var(--muted); font-weight:400; text-align:right; }.preview-meta { display:grid; grid-template-columns:repeat(3,1fr); gap:8px; border-top:1px solid var(--line); padding-top:14px; }.preview-meta span { display:block; color:var(--muted); font:9px var(--font-mono); }.preview-meta b { display:block; margin-top:5px; font:11px var(--font-mono); }.download-btn { width:100%; margin-top:18px; height:42px; display:flex; justify-content:center; align-items:center; gap:9px; border:0; background:var(--blue); color:white; font:11px var(--font-mono); }.preview-note { color:var(--muted); font-size:11px; line-height:1.5; margin:12px 0 0; }.footer { justify-content:space-between; border-top:1px solid var(--line); padding:16px clamp(20px,4vw,72px); color:var(--muted); font:10px var(--font-mono); }.footer span { display:flex; gap:7px; align-items:center; }.footer b { color:var(--blue); font-weight:400; } -@media (max-width:1200px) { .page-grid { grid-template-columns:minmax(0,1fr) minmax(420px,.9fr); gap:32px; } }.dark-mode .tile-canvas { background-color:#202a31; background-image:linear-gradient(45deg,#29343c 25%,transparent 25%),linear-gradient(-45deg,#29343c 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#29343c 75%),linear-gradient(-45deg,transparent 75%,#29343c 75%); }.dark-mode .image-preview { color:#16202b; } -@media (max-width:800px) { .topbar { padding:0 16px; }.status { display:none; }.page-grid { display:block; padding:36px 16px 48px; }.title-row { display:block; margin-bottom:40px; }.file-chip { margin-top:22px; width:max-content; }.controls,.controls.compact { grid-template-columns:1fr; }.preview-panel { position:static; margin-top:36px; }.footer { padding:0 16px 20px; gap:12px; flex-wrap:wrap; }.footer span:last-child { display:none; } } +@media (max-width:1200px) { .page-grid { grid-template-columns:minmax(0,1fr) minmax(420px,.9fr); gap:32px; } }.dark-mode .app-shell { background-image:linear-gradient(rgba(30,42,52,.28) 1px,transparent 1px),linear-gradient(90deg,rgba(30,42,52,.28) 1px,transparent 1px); }.dark-mode .tile-canvas { background-color:#202a31; background-image:linear-gradient(45deg,#29343c 25%,transparent 25%),linear-gradient(-45deg,#29343c 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#29343c 75%),linear-gradient(-45deg,transparent 75%,#29343c 75%); }.dark-mode .image-preview { color:#16202b; } +@media (max-width:800px) { .topbar { height:auto; min-height:64px; padding:12px 16px; flex-wrap:wrap; gap:12px; }.top-nav { order:3; width:100%; margin:0; gap:12px; overflow:auto; padding-bottom:2px; }.top-nav a { font-size:9px; }.status { display:none; }.page-grid { display:block; padding:36px 16px 48px; }.title-row { display:block; margin-bottom:40px; }.file-chip { margin-top:22px; width:max-content; }.controls,.controls.compact { grid-template-columns:1fr; }.preview-panel { position:static; margin-top:36px; }.footer { padding:0 16px 20px; gap:12px; flex-wrap:wrap; }.footer span:last-child { display:none; } } @media (max-width:1100px) { .preview-stack { grid-template-columns:repeat(3,minmax(220px,1fr)); } }.preview-actions { flex-wrap:wrap; justify-content:flex-end; }.download-btn { white-space:nowrap; } @media (max-width:800px) { .preview-top { align-items:flex-start; flex-direction:column; gap:18px; }.preview-actions { width:100%; justify-content:space-between; }.preview-meta { gap:14px; }.preview-stack { grid-template-columns:repeat(2,minmax(0,1fr)); }.tile-canvas { min-height:260px; } } @media (max-width:480px) { .preview-stack { grid-template-columns:1fr; }.preview-meta { width:100%; justify-content:space-between; }.title-row h1 { font-size:40px; }.pipeline-footer { align-items:flex-start; flex-direction:column; gap:12px; } } .tool-page { width:100%; padding:60px clamp(24px,4vw,72px) 72px; }.tool-title { display:flex; justify-content:space-between; align-items:end; gap:32px; margin-bottom:48px; }.tool-title h1 { margin-bottom:14px; }.tool-status { display:flex; align-items:center; gap:8px; color:#25a96a; font:10px var(--font-mono); white-space:nowrap; }.tool-status i,.auto-note i { width:6px; height:6px; background:#25a96a; border-radius:50%; }.gradient-layout { display:grid; grid-template-columns:minmax(360px,.7fr) minmax(0,1.3fr); gap:56px; align-items:start; }.settings-panel,.gradient-preview { background:var(--panel); border:1px solid var(--line); }.panel-heading,.preview-toolbar { display:flex; justify-content:space-between; align-items:center; padding:18px 20px; border-bottom:1px solid var(--line); }.panel-heading strong,.preview-toolbar strong { display:block; margin-top:5px; font:600 14px var(--font-mono); }.setting-group { padding:22px 20px; border-bottom:1px solid var(--line); }.setting-group label { display:flex; justify-content:space-between; margin-bottom:12px; font:10px var(--font-mono); letter-spacing:.1em; color:var(--muted); }.setting-group output { color:var(--blue); }.color-row { display:flex; align-items:center; gap:10px; }.color-row .color-field { flex:1; }.stop-arrow { color:var(--muted); }.gradient-bar { height:14px; margin-top:14px; border:1px solid var(--line); }.direction-grid { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; margin-top:14px; }.direction-grid button,.secondary-btn { border:1px solid var(--line); background:transparent; color:var(--muted); padding:8px 6px; font:10px var(--font-mono); }.direction-grid button.selected,.secondary-btn:hover { background:var(--foreground); color:var(--background); }.wide { width:100%; }.settings-footer { display:flex; align-items:center; justify-content:space-between; padding:16px 20px; }.large-canvas { padding:24px; background-color:#202a31; background-image:linear-gradient(45deg,#29343c 25%,transparent 25%),linear-gradient(-45deg,#29343c 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#29343c 75%),linear-gradient(-45deg,transparent 75%,#29343c 75%); background-size:28px 28px; background-position:0 0,0 14px,14px -14px,-14px 0; }.gradient-art { min-height:clamp(420px,42vw,680px); display:grid; place-content:center; justify-items:center; color:#fff; font:12px var(--font-mono); }.art-mark { display:grid; place-items:center; width:70px; height:70px; margin-bottom:12px; border:1px solid rgba(255,255,255,.65); font-size:16px; }.code-block { padding:16px 20px; }.code-block > div { display:flex; justify-content:space-between; align-items:center; }.code-block pre { margin:12px 0 0; padding:14px; background:var(--background); color:var(--blue); font:12px/1.6 var(--font-mono); white-space:pre-wrap; }.preview-actions { display:flex; align-items:center; gap:10px; }.secondary-btn { display:flex; align-items:center; gap:8px; }.dark-mode .large-canvas { background-color:#202a31; } -.remover-layout { display:grid; grid-template-columns:minmax(360px,.62fr) minmax(0,1.38fr); gap:56px; align-items:start; }.remover-preview { min-width:0; background:var(--panel); border:1px solid var(--line); }.comparison-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; padding:20px; }.image-card { min-width:0; }.image-label { display:flex; justify-content:space-between; margin-bottom:10px; font:10px var(--font-mono); color:var(--muted); }.image-label span { color:var(--blue); }.image-label b { font-weight:400; }.remover-canvas { position:relative; min-height:clamp(360px,30vw,560px); overflow:hidden; display:grid; place-items:center; border:1px solid var(--line); }.source-canvas { background:#e8eef2; }.subject { width:74%; height:68%; display:grid; place-items:center; color:rgba(255,255,255,.85); font:600 14px var(--font-mono); text-shadow:0 1px 2px #17212b; transition:all .2s ease; }.subject-source { transform:rotate(-3deg); }.canvas-size { position:absolute; right:10px; bottom:9px; font:9px var(--font-mono); color:var(--muted); }.result-meta { display:flex; gap:24px; padding:16px 20px; border-top:1px solid var(--line); font:10px var(--font-mono); color:var(--muted); }.result-meta b { color:var(--foreground); font-weight:600; margin-left:6px; }.processed { display:flex; align-items:center; gap:5px; color:#25a96a; font:10px var(--font-mono); }.color-reference,.range-hints { display:flex; justify-content:space-between; margin-top:10px; color:var(--muted); font:10px var(--font-mono); }.color-reference { justify-content:flex-start; gap:8px; }.color-reference span { width:9px; height:9px; border:1px solid var(--line); }.native-color { width:30px; padding:0!important; border:0!important; }.toggle-group label { align-items:center; cursor:pointer; }.toggle-group input { display:none; }.toggle { width:32px; height:18px; border:1px solid var(--line); position:relative; }.toggle:after { content:''; position:absolute; width:10px; height:10px; background:var(--muted); top:3px; left:3px; transition:transform .2s; }.toggle-group input:checked + .toggle { background:var(--blue); border-color:var(--blue); }.toggle-group input:checked + .toggle:after { background:white; transform:translateX(14px); }.toggle-group p { margin:8px 0 0; color:var(--muted); font-size:12px; line-height:1.5; }.catalog-nav { display:flex; align-items:center; justify-content:space-between; gap:24px; margin:-64px 0 64px; padding:18px 0; border-bottom:1px solid var(--line); }.catalog-brand { color:var(--foreground); font:600 14px var(--font-mono); text-decoration:none; }.catalog-nav nav { display:flex; gap:24px; }.catalog-nav nav a,.catalog-nav-status { color:var(--muted); font:10px var(--font-mono); text-decoration:none; }.catalog-nav nav a:hover,.catalog-nav nav a.current { color:var(--blue); }.catalog-nav-status { color:#25a96a; }.catalog-page { width:100%; max-width:1680px; margin:0 auto; padding:64px clamp(24px,4vw,72px) 72px; }.catalog-head { display:flex; align-items:flex-end; justify-content:space-between; gap:40px; padding-bottom:42px; border-bottom:1px solid var(--line); }.catalog-head h1 { margin:12px 0 14px; }.catalog-head p { max-width:660px; margin:0; color:var(--muted); font:14px/1.6 var(--font-mono); }.catalog-total { display:flex; align-items:center; gap:14px; color:var(--muted); font:10px/1.4 var(--font-mono); text-align:right; }.catalog-total b { color:var(--blue); font:400 clamp(48px,5vw,76px)/.9 var(--font-mono); letter-spacing:-.08em; }.catalog-toolbar { display:flex; align-items:center; justify-content:space-between; gap:24px; padding:24px 0 42px; }.catalog-search { display:flex; align-items:center; gap:12px; width:min(420px,100%); padding:12px 14px; border:1px solid var(--line); color:var(--muted); }.catalog-search input { width:100%; border:0; outline:0; background:transparent; color:var(--foreground); font:12px var(--font-mono); }.catalog-filters { display:flex; align-items:center; gap:6px; flex-wrap:wrap; color:var(--muted); }.catalog-filters button { padding:8px 10px; border:1px solid transparent; background:transparent; color:var(--muted); font:10px var(--font-mono); }.catalog-filters button:hover,.catalog-filters button.active { border-color:var(--blue); color:var(--blue); }.catalog-groups { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:56px 28px; }.catalog-group { min-width:0; }.group-title { display:flex; justify-content:space-between; align-items:center; padding-bottom:12px; border-bottom:1px solid var(--line); color:var(--foreground); font:600 11px var(--font-mono); letter-spacing:.12em; }.group-title i { color:var(--muted); font:10px var(--font-mono); font-style:normal; }.tool-cards { display:grid; gap:10px; padding-top:14px; }.tool-card { display:grid; grid-template-columns:42px minmax(0,1fr) 24px 18px; align-items:center; gap:14px; min-height:106px; padding:16px; border:1px solid var(--line); background:var(--panel); color:var(--foreground); text-decoration:none; transition:border-color .18s,transform .18s,background .18s; }.tool-card:hover { border-color:var(--blue); background:var(--panel-strong); transform:translateY(-2px); }.tool-icon { display:grid; place-items:center; width:42px; height:42px; background:color-mix(in srgb,var(--blue) 12%,transparent); color:var(--blue); }.tool-copy { min-width:0; display:grid; gap:8px; }.tool-copy strong { font:600 13px var(--font-mono); }.tool-copy span { color:var(--muted); font:12px/1.5 var(--font-mono); }.tool-index { color:var(--muted); font:10px var(--font-mono); align-self:start; }.tool-arrow { color:var(--blue); opacity:0; transition:opacity .18s,transform .18s; }.tool-card:hover .tool-arrow { opacity:1; transform:translate(2px,-2px); }.catalog-empty { display:flex; gap:10px; align-items:center; padding:40px; border:1px dashed var(--line); color:var(--muted); font:12px var(--font-mono); }.catalog-footer { margin-top:64px; padding-top:20px; border-top:1px solid var(--line); color:var(--muted); font:10px var(--font-mono); }.catalog-footer span { margin:0 8px; color:var(--blue); } @media (max-width:800px) { .catalog-nav { margin:-36px 0 36px; }.catalog-nav-status { display:none; }.catalog-nav nav { gap:14px; }.catalog-page { padding:36px 16px 48px; }.catalog-head { align-items:flex-start; flex-direction:column; gap:24px; }.catalog-total { text-align:left; }.catalog-toolbar { align-items:stretch; flex-direction:column; padding-bottom:30px; }.catalog-search { width:100%; }.catalog-groups { grid-template-columns:1fr; gap:36px; }.tool-card { min-height:96px; grid-template-columns:38px minmax(0,1fr) 18px; gap:12px; }.tool-icon { width:38px; height:38px; }.tool-index { display:none; }.tool-arrow { opacity:1; } } +.remover-layout { display:grid; grid-template-columns:minmax(360px,.62fr) minmax(0,1.38fr); gap:56px; align-items:start; }.remover-preview { min-width:0; background:var(--panel); border:1px solid var(--line); }.comparison-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; padding:20px; }.image-card { min-width:0; }.image-label { display:flex; justify-content:space-between; margin-bottom:10px; font:10px var(--font-mono); color:var(--muted); }.image-label span { color:var(--blue); }.image-label b { font-weight:400; }.remover-canvas { position:relative; min-height:clamp(360px,30vw,560px); overflow:hidden; display:grid; place-items:center; border:1px solid var(--line); }.source-canvas { background:#e8eef2; }.subject { width:74%; height:68%; display:grid; place-items:center; color:rgba(255,255,255,.85); font:600 14px var(--font-mono); text-shadow:0 1px 2px #17212b; transition:all .2s ease; }.subject-source { transform:rotate(-3deg); }.canvas-size { position:absolute; right:10px; bottom:9px; font:9px var(--font-mono); color:var(--muted); }.result-meta { display:flex; gap:24px; padding:16px 20px; border-top:1px solid var(--line); font:10px var(--font-mono); color:var(--muted); }.result-meta b { color:var(--foreground); font-weight:600; margin-left:6px; }.processed { display:flex; align-items:center; gap:5px; color:#25a96a; font:10px var(--font-mono); }.color-reference,.range-hints { display:flex; justify-content:space-between; margin-top:10px; color:var(--muted); font:10px var(--font-mono); }.color-reference { justify-content:flex-start; gap:8px; }.color-reference span { width:9px; height:9px; border:1px solid var(--line); }.native-color { width:30px; padding:0!important; border:0!important; }.toggle-group label { align-items:center; cursor:pointer; }.toggle-group input { display:none; }.toggle { width:32px; height:18px; border:1px solid var(--line); position:relative; }.toggle:after { content:''; position:absolute; width:10px; height:10px; background:var(--muted); top:3px; left:3px; transition:transform .2s; }.toggle-group input:checked + .toggle { background:var(--blue); border-color:var(--blue); }.toggle-group input:checked + .toggle:after { background:white; transform:translateX(14px); }.toggle-group p { margin:8px 0 0; color:var(--muted); font-size:12px; line-height:1.5; }.catalog-nav { display:flex; align-items:center; justify-content:space-between; gap:24px; margin:-64px 0 64px; padding:18px 0; border-bottom:1px solid var(--line); }.catalog-brand { color:var(--foreground); font:600 14px var(--font-mono); text-decoration:none; }.catalog-nav nav { display:flex; gap:24px; }.catalog-nav nav a,.catalog-nav-status { color:var(--muted); font:10px var(--font-mono); text-decoration:none; }.catalog-nav nav a:hover,.catalog-nav nav a.current { color:var(--blue); }.catalog-nav-status { color:#25a96a; }.catalog-page { width:100%; max-width:none; margin:0; padding:60px clamp(24px,4vw,72px) 72px; }.catalog-head { display:flex; align-items:flex-end; justify-content:space-between; gap:40px; padding-bottom:42px; border-bottom:1px solid var(--line); }.catalog-head h1 { margin:12px 0 14px; }.catalog-head p { max-width:660px; margin:0; color:var(--muted); font:14px/1.6 var(--font-mono); }.catalog-total { display:flex; align-items:center; gap:14px; color:var(--muted); font:10px/1.4 var(--font-mono); text-align:right; }.catalog-total b { color:var(--blue); font:400 clamp(48px,5vw,76px)/.9 var(--font-mono); letter-spacing:-.08em; }.catalog-toolbar { display:flex; align-items:center; justify-content:space-between; gap:24px; padding:24px 0 42px; }.catalog-search { display:flex; align-items:center; gap:12px; width:min(420px,100%); padding:12px 14px; border:1px solid var(--line); color:var(--muted); }.catalog-search input { width:100%; border:0; outline:0; background:transparent; color:var(--foreground); font:12px var(--font-mono); }.catalog-filters { display:flex; align-items:center; gap:6px; flex-wrap:wrap; color:var(--muted); }.catalog-filters button { padding:8px 10px; border:1px solid transparent; background:transparent; color:var(--muted); font:10px var(--font-mono); }.catalog-filters button:hover,.catalog-filters button.active { border-color:var(--blue); color:var(--blue); }.catalog-groups { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:56px 28px; }.catalog-group { min-width:0; }.group-title { display:flex; justify-content:space-between; align-items:center; padding-bottom:12px; border-bottom:1px solid var(--line); color:var(--foreground); font:600 11px var(--font-mono); letter-spacing:.12em; }.group-title i { color:var(--muted); font:10px var(--font-mono); font-style:normal; }.tool-cards { display:grid; gap:10px; padding-top:14px; }.tool-card { display:grid; grid-template-columns:42px minmax(0,1fr) 24px 18px; align-items:center; gap:14px; min-height:106px; padding:16px; border:1px solid var(--line); background:var(--panel); color:var(--foreground); text-decoration:none; transition:border-color .18s,transform .18s,background .18s; }.tool-card:hover { border-color:var(--blue); background:var(--panel-strong); transform:translateY(-2px); }.tool-icon { display:grid; place-items:center; width:42px; height:42px; background:color-mix(in srgb,var(--blue) 12%,transparent); color:var(--blue); }.tool-copy { min-width:0; display:grid; gap:8px; }.tool-copy strong { font:600 13px var(--font-mono); }.tool-copy span { color:var(--muted); font:12px/1.5 var(--font-mono); }.tool-index { color:var(--muted); font:10px var(--font-mono); align-self:start; }.tool-arrow { color:var(--blue); opacity:0; transition:opacity .18s,transform .18s; }.tool-card:hover .tool-arrow { opacity:1; transform:translate(2px,-2px); }.catalog-empty { display:flex; gap:10px; align-items:center; padding:40px; border:1px dashed var(--line); color:var(--muted); font:12px var(--font-mono); }.catalog-footer { margin-top:64px; padding-top:20px; border-top:1px solid var(--line); color:var(--muted); font:10px var(--font-mono); }.catalog-footer span { margin:0 8px; color:var(--blue); } @media (max-width:800px) { .catalog-nav { margin:-36px 0 36px; }.catalog-nav-status { display:none; }.catalog-nav nav { gap:14px; }.catalog-page { padding:36px 16px 48px; }.catalog-head { align-items:flex-start; flex-direction:column; gap:24px; }.catalog-total { text-align:left; }.catalog-toolbar { align-items:stretch; flex-direction:column; padding-bottom:30px; }.catalog-search { width:100%; }.catalog-groups { grid-template-columns:1fr; gap:36px; }.tool-card { min-height:96px; grid-template-columns:38px minmax(0,1fr) 18px; gap:12px; }.tool-icon { width:38px; height:38px; }.tool-index { display:none; }.tool-arrow { opacity:1; } } @media (max-width:800px) { .tool-page { padding:36px 16px 48px; }.tool-title { display:block; }.tool-status { margin-top:22px; }.gradient-layout,.remover-layout { grid-template-columns:1fr; gap:24px; }.gradient-preview,.remover-preview { order:-1; }.gradient-art { min-height:340px; }.preview-toolbar { align-items:flex-start; flex-direction:column; gap:16px; }.preview-actions { width:100%; justify-content:flex-end; }.comparison-grid { grid-template-columns:1fr; } .remover-canvas { min-height:300px; } .result-meta { flex-wrap:wrap; gap:12px 18px; } } diff --git a/refs/app/page.tsx b/refs/app/page.tsx index e85d25f..d509d22 100644 --- a/refs/app/page.tsx +++ b/refs/app/page.tsx @@ -1,7 +1,8 @@ 'use client' +import TopBar from '@/components/top-bar' import { useMemo, useState } from 'react' -import { ArrowDownToLine, Check, ChevronDown, CircleHelp, Download, GripVertical, Link2, Moon, MoreHorizontal, Plus, RotateCcw, Settings2, SlidersHorizontal, Sun, Upload, X } from 'lucide-react' +import { ArrowDownToLine, Check, ChevronDown, Download, GripVertical, Link2, MoreHorizontal, Plus, RotateCcw, Settings2, SlidersHorizontal, Upload, X } from 'lucide-react' const initialSteps = [ { id: 1, title: 'Gradient background', type: 'BACKGROUND' }, @@ -20,14 +21,13 @@ export default function Page() { const [radius, setRadius] = useState(18) const [outline, setOutline] = useState(2) const [language, setLanguage] = useState('RU') - const [dark, setDark] = useState(false) const [showIntermediate, setShowIntermediate] = useState(true) const [gradient, setGradient] = useState('#DCEBFF') const gradientStyle = useMemo(() => ({ background: `linear-gradient(${angle}deg, ${gradient}, #8BC8F5)` }), [angle, gradient]) const finalStyle = { ...gradientStyle, borderRadius: radius, boxShadow: `0 0 0 ${outline}px #16202B` } - return
-
EPeasy-png-tools/ DEMO
AUTO PIPELINE
+ return
+
PNG PROCESSING / WORKSPACE

Build your image pipeline.

Chain simple tools together. Every change is processed automatically and previewed at each stage.

source.png1.8 MB
PROCESSING PIPELINE{steps.length} active steps • LIVE
diff --git a/refs/components/top-bar.tsx b/refs/components/top-bar.tsx new file mode 100644 index 0000000..0c1a619 --- /dev/null +++ b/refs/components/top-bar.tsx @@ -0,0 +1,36 @@ +"use client" + +import Link from "next/link" +import { CircleHelp, Moon, Sun } from "lucide-react" +import { usePathname } from "next/navigation" +import { useEffect, useState } from "react" + +const links = [ + ["Workspace", "/"], + ["Catalog", "/easy-png-tools/list-tools"], + ["Gradient", "/easy-png-tools/gradient"], + ["Background remover", "/easy-png-tools/background-remover"], +] as const + +export function TopBar({ section = "WORKSPACE", status = "LOCAL MODE / READY" }: { section?: string; status?: string }) { + const pathname = usePathname() + const [dark, setDark] = useState(false) + + useEffect(() => { + const stored = window.localStorage.getItem("ep-theme") + const isDark = stored === "dark" + setDark(isDark) + document.documentElement.classList.toggle("dark-mode", isDark) + }, []) + + const toggleTheme = () => { + const next = !dark + setDark(next) + document.documentElement.classList.toggle("dark-mode", next) + window.localStorage.setItem("ep-theme", next ? "dark" : "light") + } + + return
EPeasy-png-tools/ {section}
{status}
/
+} + +export default TopBar diff --git a/refs/package.json b/refs/package.json index 5b6a16f..b096553 100644 --- a/refs/package.json +++ b/refs/package.json @@ -5,7 +5,6 @@ "scripts": { "dev": "next dev", "build": "next build", - "html": "node extract-static.mjs .next\\server\\app ..\\refs-html", "start": "next start" }, "dependencies": { diff --git a/refs/pnpm-lock.yaml b/refs/pnpm-lock.yaml index d1da2f4..2b634a8 100644 --- a/refs/pnpm-lock.yaml +++ b/refs/pnpm-lock.yaml @@ -4,9 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - hono: 4.12.25 - importers: .: @@ -268,7 +265,7 @@ packages: resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==} engines: {node: '>=18.14.1'} peerDependencies: - hono: 4.12.25 + hono: ^4 '@img/colour@1.1.0': resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} diff --git a/refs/public/placeholder.jpg b/refs/public/placeholder.jpg new file mode 100644 index 0000000..6bfe963 Binary files /dev/null and b/refs/public/placeholder.jpg differ diff --git a/refs/extract-static.mjs b/scripts/extract-static.mjs similarity index 100% rename from refs/extract-static.mjs rename to scripts/extract-static.mjs