From 0d56082963b5397db5f5c0b95684bce7d5cc2c36 Mon Sep 17 00:00:00 2001 From: Max P Date: Wed, 10 Jun 2026 00:14:32 +0200 Subject: [PATCH] Refine Nyancat pixel art --- crates/aster-webui/src/main.rs | 231 +++++++++++++++++++++++---------- 1 file changed, 160 insertions(+), 71 deletions(-) diff --git a/crates/aster-webui/src/main.rs b/crates/aster-webui/src/main.rs index 09eb9f1..32e351c 100644 --- a/crates/aster-webui/src/main.rs +++ b/crates/aster-webui/src/main.rs @@ -1413,28 +1413,50 @@ const INDEX_HTML: &str = r##" position: fixed; right: 24px; bottom: 18px; - width: 220px; - height: 84px; + width: 248px; + height: 108px; pointer-events: none; z-index: 30; - opacity: 0.92; + opacity: 0.96; filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.35)); + image-rendering: pixelated; } + .nyan-space { + position: absolute; + inset: 0; + } + + .nyan-star { + position: absolute; + width: 6px; + height: 6px; + background: #f8fafc; + box-shadow: + 6px 0 0 #f8fafc, + 0 6px 0 #f8fafc, + 6px 6px 0 #f8fafc; + animation: nyan-star 1.2s steps(2) infinite; + } + + .nyan-star.s1 { left: 10px; top: 16px; transform: scale(0.8); } + .nyan-star.s2 { left: 48px; top: 72px; transform: scale(0.6); animation-delay: 0.25s; } + .nyan-star.s3 { left: 168px; top: 8px; transform: scale(0.7); animation-delay: 0.55s; } + .nyan-rainbow { position: absolute; - left: 0; - top: 24px; - width: 132px; - height: 36px; + left: 14px; + top: 37px; + width: 126px; + height: 30px; display: grid; grid-template-rows: repeat(6, 1fr); - gap: 2px; - animation: nyan-rainbow 0.8s steps(2) infinite; + gap: 1px; + animation: nyan-rainbow 0.55s steps(2) infinite; } .nyan-rainbow .stripe { - border-radius: 999px; + border-radius: 0; } .nyan-rainbow .s1 { background: #ff4d6d; } @@ -1447,37 +1469,75 @@ const INDEX_HTML: &str = r##" .nyan-cat { position: absolute; right: 0; - top: 8px; - width: 110px; - height: 64px; - animation: nyan-float 0.9s steps(2) infinite; + top: 18px; + width: 124px; + height: 76px; + animation: nyan-float 0.55s steps(2) infinite; + } + + .nyan-cat::before, + .nyan-cat::after { + content: ""; + position: absolute; + left: 0; + width: 18px; + height: 8px; + background: #9ca3af; + border: 3px solid #111827; + border-right: none; + box-sizing: border-box; + } + + .nyan-cat::before { + top: 25px; + animation: nyan-tail 0.35s steps(2) infinite; + } + + .nyan-cat::after { + top: 37px; + width: 12px; } .nyan-body { position: absolute; - left: 30px; + left: 20px; top: 14px; - width: 52px; - height: 32px; - background: - radial-gradient(circle at 12px 11px, #ff7aa2 0 3px, transparent 3px), - radial-gradient(circle at 38px 11px, #ff7aa2 0 3px, transparent 3px), - radial-gradient(circle at 25px 22px, #ff7aa2 0 3px, transparent 3px), - linear-gradient(135deg, #ffb3c7, #ff99bc); - border: 3px solid #1f2937; - border-radius: 8px; + width: 56px; + height: 42px; + background: #d4a574; + border: 3px solid #111827; box-sizing: border-box; } + .nyan-icing { + position: absolute; + inset: 6px; + background: #f6a5c0; + border: 3px solid #111827; + box-sizing: border-box; + } + + .nyan-icing .sprinkle { + position: absolute; + width: 4px; + height: 4px; + } + + .nyan-icing .sp1 { left: 8px; top: 8px; background: #f8fafc; } + .nyan-icing .sp2 { left: 24px; top: 10px; background: #fde047; } + .nyan-icing .sp3 { left: 38px; top: 8px; background: #60a5fa; } + .nyan-icing .sp4 { left: 14px; top: 20px; background: #fb7185; } + .nyan-icing .sp5 { left: 32px; top: 22px; background: #4ade80; } + .nyan-icing .sp6 { left: 42px; top: 18px; background: #f8fafc; } + .nyan-head { position: absolute; - left: 74px; + left: 72px; top: 8px; - width: 28px; - height: 24px; + width: 36px; + height: 30px; background: #9ca3af; - border: 3px solid #1f2937; - border-radius: 8px; + border: 3px solid #111827; box-sizing: border-box; } @@ -1485,89 +1545,97 @@ const INDEX_HTML: &str = r##" .nyan-head::after { content: ""; position: absolute; - top: -8px; + top: -10px; width: 0; height: 0; - border-left: 6px solid transparent; - border-right: 6px solid transparent; - border-bottom: 10px solid #1f2937; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 12px solid #111827; } - .nyan-head::before { left: 1px; transform: rotate(-12deg); } - .nyan-head::after { right: 1px; transform: rotate(12deg); } + .nyan-head::before { left: 1px; } + .nyan-head::after { right: 1px; } + + .nyan-head .face { + position: absolute; + inset: 3px; + background: #b8bec7; + } .nyan-head .eye, .nyan-head .blush { position: absolute; display: block; - border-radius: 999px; } .nyan-head .eye { - top: 8px; - width: 3px; - height: 3px; - background: #111827; + top: 9px; + width: 4px; + height: 4px; + background: #0f172a; } - .nyan-head .e1 { left: 6px; } - .nyan-head .e2 { right: 6px; } + .nyan-head .e1 { left: 7px; } + .nyan-head .e2 { right: 7px; } .nyan-head .blush { - top: 12px; - width: 5px; + top: 16px; + width: 6px; height: 3px; background: #ff8fab; - opacity: 0.9; } - .nyan-head .b1 { left: 3px; } - .nyan-head .b2 { right: 3px; } + .nyan-head .b1 { left: 2px; } + .nyan-head .b2 { right: 2px; } - .nyan-tail { + .nyan-head .nose { position: absolute; - left: 20px; - top: 24px; - width: 16px; - height: 8px; - background: #9ca3af; - border: 3px solid #1f2937; - border-right: none; - border-radius: 8px 0 0 8px; + left: 13px; + top: 14px; + width: 4px; + height: 4px; + background: #0f172a; + } + + .nyan-head .mouth { + position: absolute; + left: 10px; + top: 19px; + width: 10px; + height: 4px; + border-bottom: 3px solid #0f172a; box-sizing: border-box; - animation: nyan-tail 0.5s steps(2) infinite; } .nyan-leg { position: absolute; width: 8px; - height: 14px; + height: 12px; background: #9ca3af; - border: 3px solid #1f2937; + border: 3px solid #111827; border-top: none; - border-radius: 0 0 6px 6px; box-sizing: border-box; - animation: nyan-legs 0.5s steps(2) infinite; + animation: nyan-legs 0.35s steps(2) infinite; } - .nyan-leg.l1 { left: 38px; top: 42px; } - .nyan-leg.l2 { left: 54px; top: 42px; animation-delay: 0.12s; } - .nyan-leg.l3 { left: 72px; top: 38px; } - .nyan-leg.l4 { left: 88px; top: 38px; animation-delay: 0.12s; } + .nyan-leg.l1 { left: 30px; top: 56px; } + .nyan-leg.l2 { left: 48px; top: 56px; animation-delay: 0.12s; } + .nyan-leg.l3 { left: 82px; top: 44px; } + .nyan-leg.l4 { left: 98px; top: 44px; animation-delay: 0.12s; } @keyframes nyan-float { 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-4px); } + 50% { transform: translateY(-3px); } } @keyframes nyan-rainbow { - 0%, 100% { transform: translateX(0); } - 50% { transform: translateX(-6px); } + 0%, 100% { transform: translateX(0); opacity: 1; } + 50% { transform: translateX(-8px); opacity: 0.96; } } @keyframes nyan-tail { 0%, 100% { transform: translateY(0) scaleX(1); } - 50% { transform: translateY(-2px) scaleX(0.92); } + 50% { transform: translateY(-2px) scaleX(0.88); } } @keyframes nyan-legs { @@ -1575,6 +1643,11 @@ const INDEX_HTML: &str = r##" 50% { transform: translateY(2px); } } + @keyframes nyan-star { + 0%, 100% { opacity: 0.35; transform: translateX(0) scale(1); } + 50% { opacity: 1; transform: translateX(-4px) scale(1.1); } + } + @media (max-width: 900px) { .nyan-wrap { right: 14px; @@ -1643,6 +1716,11 @@ const INDEX_HTML: &str = r##"