-

+
+

+

+
Cloud is live in public
@@ -64,17 +74,38 @@
-
-
+ {#if !cardActive}
+
+
+
+ {/if}
+
+
+ {#if cardActive}
+
(cardActive = false)}
+ on:keydown={() => {
+ /* no-op */
+ }}
+ transition:fade />
+ {/if}
+
+
@@ -85,7 +116,19 @@
flex-direction: column;
}
+ :global(.theme-dark) .wrapper {
+ --glow: hsl(var(--color-primary-100));
+ --beta-bg: hsl(var(--color-neutral-120));
+ --beta-fg: hsl(var(--color-neutral-0));
+ --sep-clr: hsl(var(--color-neutral-150));
+ }
+
.wrapper {
+ --glow: transparent;
+ --beta-bg: rgba(240, 46, 101, 0.16);
+ --beta-fg: rgba(240, 46, 101, 0.8);
+ --sep-clr: hsl(var(--color-neutral-10));
+
display: grid;
place-items: center;
justify-content: center;
@@ -107,7 +150,8 @@
}
.beta-tag {
- background-color: hsl(var(--color-neutral-120));
+ background-color: var(--beta-bg);
+ color: var(--beta-fg);
padding-inline: 0.75rem; // 12px
padding-block: 0.25rem; // 4px
border-radius: 0.375rem; // 6px
@@ -117,11 +161,59 @@
font-size: 1rem;
}
+ .hoodie-container {
+ background-image: url('/images/hoodies-bg.png');
+ background-size: contain;
+ background-repeat: no-repeat;
+ position: relative;
+ width: 9.9375rem; // 159px
+ height: 7.375rem; // 118px
+ flex-shrink: 0;
+
+ transition: 300ms ease;
+
+ img {
+ display: block;
+ position: absolute;
+ object-fit: contain;
+ width: 5.8125rem; // 93px
+ height: 5.8125rem; // 93px
+
+ transition: 300ms ease;
+
+ &:first-child {
+ top: 1rem;
+ left: 0.1875rem;
+ }
+
+ &:last-child {
+ top: 0.5625rem; // 9px
+ right: 0.1875rem; // 3px
+ }
+ }
+
+ &:hover {
+ box-shadow: 0 0 30px var(--glow);
+
+ img:first-child {
+ scale: 1.5;
+ rotate: -5deg;
+ translate: -1rem 1rem;
+ }
+
+ img:last-child {
+ scale: 1.5;
+ rotate: 5deg;
+ translate: 1rem -1rem;
+ }
+ }
+ }
+
.card-footer {
display: flex;
justify-content: flex-end;
- border-top: 1px solid hsl(var(--color-neutral-150));
+ border-top: 1px solid var(--sep-clr);
margin-block-start: 2rem;
padding-block-start: 2rem;
@@ -136,11 +228,6 @@
align-items: center;
}
- .confetti-wrapper {
- position: relative;
- // z-index: 9999;
- }
-
@keyframes shake {
0% {
translate: 0;
@@ -179,4 +266,33 @@
align-items: center;
gap: 0.5rem;
}
+
+ .controls {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+
+ position: absolute;
+ top: 80%;
+ left: 50%;
+ translate: -50% -50%;
+
+ transition: opacity 250ms ease;
+
+ &.invisible {
+ opacity: 0;
+ }
+ }
+
+ .overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+
+ background-color: hsl(var(--p-body-bg-color));
+ backdrop-filter: blur(80px);
+ opacity: 0.5;
+ }
diff --git a/src/routes/console/cloud-beta-card/Card.svelte b/src/routes/console/cloud-beta-card/Card.svelte
index 35d02e2ba..1c8a441df 100644
--- a/src/routes/console/cloud-beta-card/Card.svelte
+++ b/src/routes/console/cloud-beta-card/Card.svelte
@@ -22,12 +22,14 @@
import { spring } from 'svelte/motion';
let cardEl: HTMLDivElement | undefined;
- let active = false;
+ export let active = false;
+ export let isFlipped = false;
+
let interacting = false;
const springR = { stiffness: 0.066, damping: 0.25 };
const springD = { stiffness: 0.033, damping: 0.45 };
- const THICKNESS = 6;
+ const THICKNESS = 3;
let springRotate = spring({ x: 0, y: 0 }, springR);
let springGlare = spring({ x: 50, y: 50, o: 0.25 }, springR);
@@ -39,8 +41,6 @@
let centerProximity = spring(0, springR);
let springRotateZ = spring(-15, springD);
- let isBackwards = false;
-
// Events
const interact = (e: MouseEvent | TouchEvent) => {
if (!active) return;
@@ -61,7 +61,7 @@
};
const center = {
x: percent.x - 50,
- y: (percent.y - 50) * (isBackwards ? -1 : 1)
+ y: (percent.y - 50) * (isFlipped ? -1 : 1)
};
springBackground.stiffness = springR.stiffness;
@@ -153,6 +153,7 @@
springTranslate.set({ x: 0, y: 0 });
springRotateDelta.set({ x: 0, y: 0 });
springRotate.set({ x: 0, y: 0 });
+ springGlare.set({ x: 50, y: 50, o: 0 });
$centerProximity = 0;
springRotateZ.set(-15);
};
@@ -161,23 +162,19 @@
active = !active;
};
- const handleBlur = () => {
- active = false;
- };
-
const windowKeyDown = (e: KeyboardEvent) => {
if (!active) return;
// If user presses q, rotate card
if (e.key === 'q') {
- isBackwards = !isBackwards;
+ isFlipped = !isFlipped;
}
};
$: if (!active) {
- isBackwards = false;
+ isFlipped = false;
} else {
springRotateDelta.update((old) => ({
- x: isBackwards ? 180 : 360,
+ x: isFlipped ? 180 : 360,
y: old.y
}));
}
@@ -273,7 +270,9 @@
on:pointermove={interact}
on:mouseout={interactEnd}
on:click={handleClick}
- on:blur={handleBlur}>
+ on:blur={() => {
+ /* noop */
+ }}>

diff --git a/static/images/hoodie-1.png b/static/images/hoodie-1.png
new file mode 100644
index 000000000..56e97a962
Binary files /dev/null and b/static/images/hoodie-1.png differ
diff --git a/static/images/hoodie-2.png b/static/images/hoodie-2.png
new file mode 100644
index 000000000..8b9d9461e
Binary files /dev/null and b/static/images/hoodie-2.png differ
diff --git a/static/images/hoodies-bg.png b/static/images/hoodies-bg.png
new file mode 100644
index 000000000..b52e3bd9d
Binary files /dev/null and b/static/images/hoodies-bg.png differ