mobile: iOS-style widget + animations, 2-click desktop icons, new wallpapers
Mobile: - iOS-style open/close animation for app views (grows from the tapped icon, always slides straight down out of view and shrinks on close) - digital 2x1 clock widget in an iOS-style frosted-glass panel - new phone wallpaper (phonewallpaper.jpg) - larger notch Desktop: - desktop icons and shortcuts now launch on the second click - open/close/launcher animations - windows keep their state when toggling Gruvbox/Desktop themes, and the Welcome window only appears on the first page load Other: - update wallpaper credits to wallpapercave - allow LAN hosts in dev (allowedDevOrigins) so phones can load the dev bundle instead of getting a 403 and an inert page
This commit is contained in:
parent
784334d4be
commit
6b645ac636
11 changed files with 397 additions and 159 deletions
|
|
@ -81,29 +81,35 @@ html[data-device="phone"] .skeuo-mobile-root { display: block; }
|
|||
}
|
||||
.win-icon {
|
||||
width: 92px;
|
||||
padding: 6px 4px 7px;
|
||||
padding: 6px 4px 9px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
gap: 8px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
color: #ffffff;
|
||||
cursor: default;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95);
|
||||
transition: transform 0.12s ease, background-color 0.12s ease,
|
||||
border-color 0.12s ease;
|
||||
}
|
||||
.win-icon:hover,
|
||||
.win-icon.selected {
|
||||
background: rgba(61, 174, 233, 0.16);
|
||||
border-color: rgba(61, 174, 233, 0.4);
|
||||
}
|
||||
.win-icon:active {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
.win-icon-glyph {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-size: 40px;
|
||||
line-height: 1;
|
||||
background: transparent !important;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
|
|
@ -167,6 +173,7 @@ a.win-icon {
|
|||
box-shadow: 0 10px 32px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.04);
|
||||
overflow: hidden;
|
||||
user-select: text;
|
||||
animation: winOpen 0.16s ease-out;
|
||||
}
|
||||
.win-window.active {
|
||||
border-color: #3a444d;
|
||||
|
|
@ -180,9 +187,36 @@ a.win-icon {
|
|||
height: calc(100% - 54px) !important;
|
||||
}
|
||||
.win-window.centered {
|
||||
left: 50%;
|
||||
top: calc(50% - 27px);
|
||||
transform: translate(-50%, -50%);
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 54px;
|
||||
margin: auto;
|
||||
}
|
||||
.win-window.closing {
|
||||
animation: winClose 0.14s ease-in forwards;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes winOpen {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes winClose {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
|
||||
.win-titlebar {
|
||||
|
|
@ -979,6 +1013,18 @@ a.win-icon {
|
|||
backdrop-filter: blur(28px) saturate(150%);
|
||||
color: #eff0f1;
|
||||
overflow: hidden;
|
||||
transform-origin: bottom left;
|
||||
animation: kickoffIn 0.16s ease-out;
|
||||
}
|
||||
@keyframes kickoffIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px) scale(0.98);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
.kickoff-content {
|
||||
max-height: 60vh;
|
||||
|
|
@ -1072,20 +1118,20 @@ a.win-icon {
|
|||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 132px;
|
||||
height: 27px;
|
||||
width: 164px;
|
||||
height: 34px;
|
||||
z-index: 60;
|
||||
background: #000;
|
||||
border-radius: 0 0 18px 18px;
|
||||
border-radius: 0 0 22px 22px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.mobile-notch::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 22px;
|
||||
top: 9px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
right: 26px;
|
||||
top: 11px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 35% 30%, #2b3a55, #05070b 70%);
|
||||
}
|
||||
|
|
@ -1117,49 +1163,47 @@ a.win-icon {
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* 2x1 iOS-style clock widget */
|
||||
.mobile-widget {
|
||||
grid-column: span 2;
|
||||
grid-row: span 2;
|
||||
border-radius: 26px;
|
||||
padding: 14px 16px;
|
||||
grid-row: span 1;
|
||||
border-radius: 22px;
|
||||
padding: 10px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
gap: 1px;
|
||||
overflow: hidden;
|
||||
color: #ffffff;
|
||||
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
|
||||
border: 1px solid rgba(255, 255, 255, 0.28);
|
||||
background-color: rgba(24, 26, 32, 0.62);
|
||||
border: 1px solid rgba(255, 255, 255, 0.22);
|
||||
background-color: rgba(28, 30, 38, 0.42);
|
||||
background-image: linear-gradient(
|
||||
155deg,
|
||||
rgba(255, 255, 255, 0.24),
|
||||
rgba(255, 255, 255, 0.05) 46%,
|
||||
rgba(0, 0, 0, 0.3)
|
||||
160deg,
|
||||
rgba(255, 255, 255, 0.22),
|
||||
rgba(255, 255, 255, 0.06) 52%,
|
||||
rgba(0, 0, 0, 0.18)
|
||||
);
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.45),
|
||||
0 10px 26px rgba(0, 0, 0, 0.4);
|
||||
-webkit-backdrop-filter: blur(18px) saturate(150%);
|
||||
backdrop-filter: blur(18px) saturate(150%);
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.35),
|
||||
0 6px 18px rgba(0, 0, 0, 0.32);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(150%);
|
||||
backdrop-filter: blur(20px) saturate(150%);
|
||||
}
|
||||
.mobile-widget-time {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 300;
|
||||
line-height: 1;
|
||||
font-size: 1.65rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.02em;
|
||||
font-variant-numeric: tabular-nums;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
.mobile-widget-date {
|
||||
font-size: 0.78rem;
|
||||
font-size: 0.66rem;
|
||||
font-weight: 500;
|
||||
opacity: 0.95;
|
||||
}
|
||||
.mobile-widget-foot {
|
||||
margin-top: 4px;
|
||||
font-size: 0.62rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.02em;
|
||||
opacity: 0.72;
|
||||
line-height: 1.1;
|
||||
letter-spacing: 0.03em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.mobile-grid {
|
||||
|
|
@ -1308,6 +1352,57 @@ a.win-icon {
|
|||
background: #fef7ff;
|
||||
color: #1d1b20;
|
||||
font-family: Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
will-change: transform, opacity, border-radius;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
.mobile-app-view.opening {
|
||||
animation: mobileAppOpen 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
|
||||
/* Grow out of the tapped icon. */
|
||||
transform-origin: var(--app-origin, 50% 50%);
|
||||
}
|
||||
.mobile-app-view.closing {
|
||||
animation: mobileAppClose 0.36s cubic-bezier(0.4, 0, 0.7, 0.2) forwards;
|
||||
pointer-events: none;
|
||||
/* Always shrink straight down from the centre, never toward the icon. */
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
.mobile-app-view .mobile-appbar,
|
||||
.mobile-app-view .mobile-app-body {
|
||||
animation: mobileAppContentIn 0.3s ease-out both;
|
||||
}
|
||||
|
||||
@keyframes mobileAppOpen {
|
||||
from {
|
||||
transform: scale(var(--app-scale, 0.2));
|
||||
border-radius: 27px;
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
@keyframes mobileAppClose {
|
||||
from {
|
||||
translate: 0 0;
|
||||
scale: 1;
|
||||
border-radius: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
/* One full viewport height guarantees it clears the bottom edge entirely. */
|
||||
translate: 0 100vh;
|
||||
scale: var(--app-scale, 0.2);
|
||||
border-radius: 27px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes mobileAppContentIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.mobile-appbar {
|
||||
flex: 0 0 auto;
|
||||
|
|
@ -1400,11 +1495,27 @@ a.win-icon {
|
|||
.mobile-app { gap: 3px; }
|
||||
.mobile-app-icon { width: 42px; height: 42px; border-radius: 15px; font-size: 20px; }
|
||||
.mobile-app-label { font-size: 0.58rem; }
|
||||
.mobile-widget { border-radius: 20px; padding: 10px 12px; }
|
||||
.mobile-widget-time { font-size: 1.6rem; }
|
||||
.mobile-widget-date { font-size: 0.66rem; }
|
||||
.mobile-widget-foot { display: none; }
|
||||
.mobile-widget { border-radius: 16px; padding: 6px 10px; }
|
||||
.mobile-widget-time { font-size: 1.1rem; }
|
||||
.mobile-widget-date { font-size: 0.55rem; }
|
||||
.mobile-dock { bottom: 14px; padding: 7px 12px; border-radius: 24px; }
|
||||
.mobile-app.in-dock .mobile-app-icon { width: 40px; height: 40px; border-radius: 14px; font-size: 19px; }
|
||||
.mobile-pagedots { display: none; }
|
||||
}
|
||||
|
||||
/* Respect reduced-motion preferences without breaking animationend callbacks
|
||||
(a near-zero duration still fires them so closing windows/apps unmount). */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.win-window,
|
||||
.win-window.closing,
|
||||
.kickoff,
|
||||
.mobile-app-view.opening,
|
||||
.mobile-app-view.closing,
|
||||
.mobile-app-view .mobile-appbar,
|
||||
.mobile-app-view .mobile-app-body {
|
||||
animation-duration: 0.01ms !important;
|
||||
}
|
||||
.win-icon {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue