Theme-Stuff #4
394
app/globals.css
394
app/globals.css
|
|
@ -1023,6 +1023,48 @@ html.theme-blueprint .line-through {
|
||||||
text-decoration-thickness: 1.5px;
|
text-decoration-thickness: 1.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Then a red-ink "APPROVED" stamp thuds onto the row a beat after the strike
|
||||||
|
-- a hard scale-down with a small overshoot, settling tilted a few degrees
|
||||||
|
like a QC stamp pressed onto the drawing. Scoped to the board's to-do rows:
|
||||||
|
the title button is a flex row, so the stamp rides at its right end (the
|
||||||
|
scheduled panel's completed rows are truncate buttons, where a flex item
|
||||||
|
would get clipped by the ellipsis). */
|
||||||
|
html.theme-blueprint [data-group-card] .line-through::after {
|
||||||
|
content: "APPROVED";
|
||||||
|
flex: none;
|
||||||
|
margin-left: 4px;
|
||||||
|
padding: 1px 6px;
|
||||||
|
border: 1.5px solid oklch(0.58 0.2 25 / 0.75);
|
||||||
|
box-shadow: inset 0 0 0 1px oklch(0.58 0.2 25 / 0.28);
|
||||||
|
border-radius: 2px;
|
||||||
|
color: oklch(0.58 0.2 25 / 0.9);
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 1.6;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
opacity: 0.9;
|
||||||
|
transform: rotate(-6deg);
|
||||||
|
animation: bp-stamp 380ms cubic-bezier(0.3, 0.9, 0.4, 1) 160ms backwards;
|
||||||
|
mix-blend-mode: multiply;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
@keyframes bp-stamp {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: rotate(-14deg) scale(2.1);
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
opacity: 0.9;
|
||||||
|
transform: rotate(-5deg) scale(0.92);
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: rotate(-6.5deg) scale(1.06);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0.9;
|
||||||
|
transform: rotate(-6deg) scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* To-do checkbox: a small technical box -- squarer corner, crisp stroke, and
|
/* To-do checkbox: a small technical box -- squarer corner, crisp stroke, and
|
||||||
registration ticks that snap in on hover/focus like a plotter aligning to a
|
registration ticks that snap in on hover/focus like a plotter aligning to a
|
||||||
point. (The box is the base-ui checkbox button; its stroke/fill already come
|
point. (The box is the base-ui checkbox button; its stroke/fill already come
|
||||||
|
|
@ -1512,21 +1554,25 @@ html.theme-vaporwave body {
|
||||||
oklch(0.955 0.055 190) 100%
|
oklch(0.955 0.055 190) 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
/* Faint scanlines rolling slowly, like a monitor left on in the morning. */
|
/* Rolling scanlines: a fixed overlay over the whole app -- the "monitor"
|
||||||
|
sits over everything (cards, dialogs, toasts), the same move as cyberpunk's
|
||||||
|
CRT layer, so the texture is actually visible instead of hiding behind the
|
||||||
|
content. A 1px plum line every 4px, rolling downward at about 1px/s like a
|
||||||
|
monitor left on all morning. */
|
||||||
html.theme-vaporwave body::before {
|
html.theme-vaporwave body::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: -1;
|
z-index: 999;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background-image: repeating-linear-gradient(
|
background-image: repeating-linear-gradient(
|
||||||
0deg,
|
0deg,
|
||||||
oklch(0.42 0.16 320 / 0.035) 0px,
|
oklch(0.35 0.16 330 / 0.06) 0px,
|
||||||
oklch(0.42 0.16 320 / 0.035) 1px,
|
oklch(0.35 0.16 330 / 0.06) 1px,
|
||||||
transparent 1px,
|
transparent 1px,
|
||||||
transparent 4px
|
transparent 4px
|
||||||
);
|
);
|
||||||
animation: vw-roll 16s linear infinite;
|
animation: vw-roll 4s linear infinite;
|
||||||
}
|
}
|
||||||
@keyframes vw-roll {
|
@keyframes vw-roll {
|
||||||
from {
|
from {
|
||||||
|
|
@ -1537,6 +1583,260 @@ html.theme-vaporwave body::before {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The striped synth sun: the vaporwave icon, fixed in the sky behind the
|
||||||
|
content (it shows through the translucent lanes like light through glass).
|
||||||
|
Big and low, sitting on the outrun floor's horizon line. Solid across the
|
||||||
|
top, classic horizontal slats below, the slats drifting slowly downward
|
||||||
|
like the sun melting toward the horizon. Muted pastels close to the sky's
|
||||||
|
own lightness, so it reads as part of the sky rather than a sticker on it. */
|
||||||
|
html.theme-vaporwave body::after {
|
||||||
|
content: "";
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 7vh;
|
||||||
|
width: 320px;
|
||||||
|
height: 320px;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
oklch(0.93 0.055 90) 0%,
|
||||||
|
oklch(0.91 0.075 48) 38%,
|
||||||
|
oklch(0.89 0.09 30) 68%,
|
||||||
|
oklch(0.86 0.085 350) 100%
|
||||||
|
);
|
||||||
|
filter: drop-shadow(0 0 26px oklch(0.85 0.1 40 / 0.3));
|
||||||
|
-webkit-mask-image: linear-gradient(180deg, #000 0 55%, rgba(0, 0, 0, 0) 55%),
|
||||||
|
repeating-linear-gradient(180deg, #000 0 10px, rgba(0, 0, 0, 0) 10px 18px);
|
||||||
|
mask-image: linear-gradient(180deg, #000 0 55%, rgba(0, 0, 0, 0) 55%),
|
||||||
|
repeating-linear-gradient(180deg, #000 0 10px, rgba(0, 0, 0, 0) 10px 18px);
|
||||||
|
animation: vw-sun 5s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes vw-sun {
|
||||||
|
from {
|
||||||
|
-webkit-mask-position: 0 0, 0 0;
|
||||||
|
mask-position: 0 0, 0 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
-webkit-mask-position: 0 0, 0 18px;
|
||||||
|
mask-position: 0 0, 0 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The outrun floor: a perspective grid across the bottom of the viewport,
|
||||||
|
behind the content (it shows through the translucent lanes). The horizontal
|
||||||
|
lines crawl toward the viewer while the verticals converge on the
|
||||||
|
vanishing point. Rendered by the .vw-floor element in app/layout.tsx,
|
||||||
|
visible only under this theme. */
|
||||||
|
.vw-floor {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave .vw-floor {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 0;
|
||||||
|
width: 200vw;
|
||||||
|
height: 75vh;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateX(-50%) perspective(300px) rotateX(60deg);
|
||||||
|
transform-origin: 50% 100%;
|
||||||
|
opacity: 0.8;
|
||||||
|
background-image:
|
||||||
|
repeating-linear-gradient(90deg, oklch(0.62 0.25 350 / 0.5) 0 2px, transparent 2px 90px),
|
||||||
|
repeating-linear-gradient(0deg, oklch(0.62 0.25 350 / 0.5) 0 2px, transparent 2px 44px);
|
||||||
|
-webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 35%);
|
||||||
|
mask-image: linear-gradient(180deg, transparent 0%, #000 35%);
|
||||||
|
animation: vw-floor 2.2s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes vw-floor {
|
||||||
|
from {
|
||||||
|
background-position: 0 0, 0 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-position: 0 0, 0 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Palm silhouettes: a couple of minimal palms rooted at either side of the
|
||||||
|
horizon -- the classic vaporwave framing, kept faint so they read as
|
||||||
|
scenery, not stickers. Drawn as stroked arcs in the .vw-palm SVGs in
|
||||||
|
app/layout.tsx; they paint above the floor grid (DOM order) but stay
|
||||||
|
behind the content. Visible only under this theme. */
|
||||||
|
.vw-palm {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.vw-palm-defs {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave .vw-palm {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1vh;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
color: oklch(0.47 0.12 325);
|
||||||
|
}
|
||||||
|
html.theme-vaporwave .vw-palm--left-main {
|
||||||
|
left: 18vw;
|
||||||
|
width: 150px;
|
||||||
|
height: 187px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave .vw-palm--left-small {
|
||||||
|
left: 26vw;
|
||||||
|
width: 90px;
|
||||||
|
height: 112px;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave .vw-palm--right-main {
|
||||||
|
right: 2vw;
|
||||||
|
width: 150px;
|
||||||
|
height: 187px;
|
||||||
|
opacity: 0.5;
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
html.theme-vaporwave .vw-palm--right-small {
|
||||||
|
right: 10vw;
|
||||||
|
width: 90px;
|
||||||
|
height: 112px;
|
||||||
|
opacity: 0.3;
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VHS hiccup: every so often a card drops out of the signal for half a
|
||||||
|
second -- a 1-2px jitter, a red/cyan split on the title, and a tracking
|
||||||
|
band sweeping down the panel, all inside one short window (the first 5%
|
||||||
|
of each cycle). Cards run three alternating phases with different periods
|
||||||
|
and offsets, so the board flickers organically instead of in lockstep.
|
||||||
|
The :not(.opacity-50) guard matters: while dnd-kit drives a drag it sets
|
||||||
|
an inline `transform` on the card, and a running animation would override
|
||||||
|
that inline value (animations sit above inline styles in the cascade) --
|
||||||
|
the card stops following the pointer. opacity-50 is exactly the class the
|
||||||
|
card gets while dragging, so the hiccup stands down for the duration.
|
||||||
|
(overflow: hidden keeps the tracking band clipped to the card while it
|
||||||
|
sweeps; the hover lift uses the separate `translate` property, so the
|
||||||
|
jitter doesn't fight it.) */
|
||||||
|
html.theme-vaporwave [data-group-card]:not(.opacity-50) {
|
||||||
|
overflow: hidden;
|
||||||
|
animation: vw-card-glitch 10s linear infinite;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave [data-group-card]:not(.opacity-50) > div:first-child h3 {
|
||||||
|
animation: vw-title-glitch 10s linear infinite;
|
||||||
|
}
|
||||||
|
html.theme-vaporwave [data-group-card]:not(.opacity-50)::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: -12%;
|
||||||
|
height: 12px;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(0deg, oklch(0.45 0.15 330 / 0.28) 0 1px, transparent 1px 3px),
|
||||||
|
linear-gradient(
|
||||||
|
180deg,
|
||||||
|
transparent 0%,
|
||||||
|
oklch(0.72 0.2 350 / 0.22) 20%,
|
||||||
|
oklch(0.99 0.01 220 / 0.4) 50%,
|
||||||
|
oklch(0.78 0.15 200 / 0.22) 80%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
animation: vw-tracking 10s linear infinite;
|
||||||
|
}
|
||||||
|
/* Phase B: a longer period and an offset start, so neighbors don't hiccup
|
||||||
|
together. (Static styles above are the idle state -- before a card's
|
||||||
|
first delay elapses, and under reduced motion, everything just sits still.) */
|
||||||
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50),
|
||||||
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
||||||
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n + 2) [data-group-card]:not(.opacity-50)::after {
|
||||||
|
animation-duration: 13s;
|
||||||
|
animation-delay: 3s;
|
||||||
|
}
|
||||||
|
/* Phase C: the longest period, offset furthest. */
|
||||||
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50),
|
||||||
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50) > div:first-child h3,
|
||||||
|
html.theme-vaporwave [data-category-lane] .overflow-y-auto > div:nth-child(3n) [data-group-card]:not(.opacity-50)::after {
|
||||||
|
animation-duration: 17s;
|
||||||
|
animation-delay: 7s;
|
||||||
|
}
|
||||||
|
@keyframes vw-card-glitch {
|
||||||
|
0%,
|
||||||
|
5%,
|
||||||
|
100% {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
0.8% {
|
||||||
|
transform: translateX(-1.5px);
|
||||||
|
}
|
||||||
|
1.6% {
|
||||||
|
transform: translateX(-1.5px);
|
||||||
|
}
|
||||||
|
2.4% {
|
||||||
|
transform: translateX(1px);
|
||||||
|
}
|
||||||
|
3.2% {
|
||||||
|
transform: translateX(1px);
|
||||||
|
}
|
||||||
|
4% {
|
||||||
|
transform: translateX(-0.75px);
|
||||||
|
}
|
||||||
|
4.6% {
|
||||||
|
transform: translateX(0.5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes vw-title-glitch {
|
||||||
|
0%,
|
||||||
|
5%,
|
||||||
|
100% {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
0.8% {
|
||||||
|
text-shadow:
|
||||||
|
1.5px 0 oklch(0.68 0.2 350 / 0.55),
|
||||||
|
-1.5px 0 oklch(0.85 0.15 200 / 0.55);
|
||||||
|
}
|
||||||
|
1.6% {
|
||||||
|
text-shadow:
|
||||||
|
-1.5px 0 oklch(0.68 0.2 350 / 0.55),
|
||||||
|
1.5px 0 oklch(0.85 0.15 200 / 0.55);
|
||||||
|
}
|
||||||
|
2.4% {
|
||||||
|
text-shadow:
|
||||||
|
1px 0 oklch(0.68 0.2 350 / 0.55),
|
||||||
|
-1px 0 oklch(0.85 0.15 200 / 0.55);
|
||||||
|
}
|
||||||
|
3.2% {
|
||||||
|
text-shadow:
|
||||||
|
-0.5px 0 oklch(0.68 0.2 350 / 0.55),
|
||||||
|
0.5px 0 oklch(0.85 0.15 200 / 0.55);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes vw-tracking {
|
||||||
|
0% {
|
||||||
|
top: -12%;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
0.8% {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
4.8% {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
5%,
|
||||||
|
100% {
|
||||||
|
top: 112%;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Primary blooms with a soft magenta glow; focus glows electric cyan. */
|
/* Primary blooms with a soft magenta glow; focus glows electric cyan. */
|
||||||
html.theme-vaporwave .bg-primary {
|
html.theme-vaporwave .bg-primary {
|
||||||
box-shadow: 0 4px 18px oklch(0.62 0.25 350 / 0.35);
|
box-shadow: 0 4px 18px oklch(0.62 0.25 350 / 0.35);
|
||||||
|
|
@ -1731,18 +2031,58 @@ html.theme-notebook body {
|
||||||
background-image: linear-gradient(180deg, oklch(0.88 0.024 82), oklch(0.84 0.028 80));
|
background-image: linear-gradient(180deg, oklch(0.88 0.024 82), oklch(0.84 0.028 80));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ruled paper on the white card surfaces: blue rules + a red margin line on
|
/* The lane is the notebook page itself: white paper over the warm desk with
|
||||||
the left, the classic notebook page. */
|
the classic ruling -- blue lines + a red margin rule running down the left
|
||||||
html.theme-notebook [data-slot="card"],
|
(inside the lane's own padding, so the post-its never cover it). Group
|
||||||
html.theme-notebook [data-slot="dialog-content"] {
|
cards sit on top as post-its (below), so the ruling shows around them. */
|
||||||
|
html.theme-notebook [data-category-lane] {
|
||||||
|
background-color: oklch(0.978 0.008 90);
|
||||||
background-image:
|
background-image:
|
||||||
linear-gradient(90deg, transparent 24px, oklch(0.6 0.19 25 / 0.4) 24px 26px, transparent 26px),
|
linear-gradient(90deg, transparent 6px, oklch(0.6 0.19 25 / 0.4) 6px 8px, transparent 8px),
|
||||||
repeating-linear-gradient(180deg, transparent 0 27px, oklch(0.68 0.09 250 / 0.4) 27px 28px);
|
repeating-linear-gradient(180deg, transparent 0 27px, oklch(0.68 0.09 250 / 0.4) 27px 28px);
|
||||||
|
box-shadow:
|
||||||
|
0 1px 2px rgb(96 74 40 / 0.14),
|
||||||
|
0 10px 24px -10px rgb(96 74 40 / 0.3);
|
||||||
}
|
}
|
||||||
/* Group cards keep their own pastel tint (they read as index cards) but carry
|
|
||||||
a faint red margin line so they stay in the stationery family. */
|
/* Group cards are post-its stuck onto the page: a slightly darker adhesive
|
||||||
|
band along the top, and a soft lift shadow that runs heavier to one side,
|
||||||
|
like a sheet curling off the paper. (:not(.ring-2) keeps the drag
|
||||||
|
drop-target ring -- a box-shadow utility -- from being overpainted.) */
|
||||||
html.theme-notebook [data-group-card] {
|
html.theme-notebook [data-group-card] {
|
||||||
background-image: linear-gradient(90deg, transparent 20px, oklch(0.6 0.19 25 / 0.3) 20px 22px, transparent 22px);
|
border-width: 2px;
|
||||||
|
background-image: linear-gradient(180deg, rgb(96 74 40 / 0.07) 0 15%, transparent 15%);
|
||||||
|
}
|
||||||
|
html.theme-notebook [data-group-card]:not(.ring-2) {
|
||||||
|
box-shadow:
|
||||||
|
1px 1px 2px rgb(96 74 40 / 0.12),
|
||||||
|
6px 9px 16px -6px rgb(96 74 40 / 0.32);
|
||||||
|
}
|
||||||
|
html.theme-notebook [data-group-card]:not(.ring-2):hover {
|
||||||
|
box-shadow:
|
||||||
|
1px 2px 3px rgb(96 74 40 / 0.14),
|
||||||
|
8px 12px 20px -6px rgb(96 74 40 / 0.4);
|
||||||
|
}
|
||||||
|
/* A post-it is never stuck perfectly straight: alternate a hair of tilt down
|
||||||
|
the column so a boardful don't all lean the same way. (While a card is
|
||||||
|
being dragged, dnd-kit's inline transform overrides this -- the post-it
|
||||||
|
straightens out in your hand.) */
|
||||||
|
html.theme-notebook [data-category-lane] .overflow-y-auto > div:nth-child(2n) [data-group-card] {
|
||||||
|
transform: rotate(0.4deg);
|
||||||
|
}
|
||||||
|
html.theme-notebook [data-category-lane] .overflow-y-auto > div:nth-child(2n + 1) [data-group-card] {
|
||||||
|
transform: rotate(-0.4deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hand-cut paper edges: the classic uneven border-radius so pages, cards, and
|
||||||
|
dialogs look drawn by hand instead of machine-rounded. */
|
||||||
|
html.theme-notebook [data-category-lane] {
|
||||||
|
border-radius: 170px 10px 150px 10px / 10px 150px 10px 170px;
|
||||||
|
}
|
||||||
|
html.theme-notebook [data-slot="card"],
|
||||||
|
html.theme-notebook [data-slot="dialog-content"],
|
||||||
|
html.theme-notebook [data-group-card] {
|
||||||
|
border-radius: 255px 15px 225px 15px / 15px 225px 15px 255px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Blue-ink focus. */
|
/* Blue-ink focus. */
|
||||||
|
|
@ -1783,6 +2123,34 @@ html.theme-notebook .line-through {
|
||||||
background-size: 100% 60%;
|
background-size: 100% 60%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Then a red pen draws a quick check at the end of the line -- grading the
|
||||||
|
homework. (Scoped to the board's to-do rows: the title button is a flex
|
||||||
|
row, so the check rides at its right end. It starts fully clipped and
|
||||||
|
reveals left-to-right, timed to land as the highlighter sweep finishes.) */
|
||||||
|
html.theme-notebook [data-group-card] .line-through::after {
|
||||||
|
content: "✓";
|
||||||
|
flex: none;
|
||||||
|
margin-left: 2px;
|
||||||
|
color: oklch(0.55 0.22 27 / 0.95);
|
||||||
|
font-size: 1.15em;
|
||||||
|
line-height: 1;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
clip-path: inset(-25% 100% -25% 0);
|
||||||
|
animation: nb-check 300ms ease-out 300ms forwards;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
@keyframes nb-check {
|
||||||
|
to {
|
||||||
|
clip-path: inset(-25% -5% -25% 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* The global reduced-motion guard kills the reveal animation -- fall back to
|
||||||
|
the check simply sitting there, already drawn. */
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
html.theme-notebook [data-group-card] .line-through::after {
|
||||||
|
clip-path: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,36 @@ export default function RootLayout({ children }: LayoutProps<"/">) {
|
||||||
__html: `!(function(){try{var r=document.documentElement,c=['theme-default','theme-sunset','theme-meadow','theme-honey','theme-rose','theme-lavender','theme-slate','theme-blueprint','theme-vaporwave','theme-notebook','dark','ocean','theme-pine','theme-plum','theme-midnight','theme-ember','theme-rosewood','theme-cyberpunk','theme-starfield','light'];for(var i=0;i<c.length;i++){r.classList.remove(c[i]);}var v=null;try{v=localStorage.getItem('theme');}catch(e){}var m={default:'theme-default',sunset:'theme-sunset',meadow:'theme-meadow',honey:'theme-honey',rose:'theme-rose',lavender:'theme-lavender',slate:'theme-slate',blueprint:'theme-blueprint',vaporwave:'theme-vaporwave',notebook:'theme-notebook',dark:'dark',ocean:'ocean',pine:'theme-pine',plum:'theme-plum',midnight:'theme-midnight',ember:'theme-ember',rosewood:'theme-rosewood',cyberpunk:'theme-cyberpunk',starfield:'theme-starfield'};var d=['dark','ocean','pine','plum','midnight','ember','rosewood','cyberpunk','starfield'];if(v==='system'||!v){v=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'default';}if(m[v]){r.classList.add(m[v]);r.style.colorScheme=d.indexOf(v)>=0?'dark':'light';}}catch(e){}})();`,
|
__html: `!(function(){try{var r=document.documentElement,c=['theme-default','theme-sunset','theme-meadow','theme-honey','theme-rose','theme-lavender','theme-slate','theme-blueprint','theme-vaporwave','theme-notebook','dark','ocean','theme-pine','theme-plum','theme-midnight','theme-ember','theme-rosewood','theme-cyberpunk','theme-starfield','light'];for(var i=0;i<c.length;i++){r.classList.remove(c[i]);}var v=null;try{v=localStorage.getItem('theme');}catch(e){}var m={default:'theme-default',sunset:'theme-sunset',meadow:'theme-meadow',honey:'theme-honey',rose:'theme-rose',lavender:'theme-lavender',slate:'theme-slate',blueprint:'theme-blueprint',vaporwave:'theme-vaporwave',notebook:'theme-notebook',dark:'dark',ocean:'ocean',pine:'theme-pine',plum:'theme-plum',midnight:'theme-midnight',ember:'theme-ember',rosewood:'theme-rosewood',cyberpunk:'theme-cyberpunk',starfield:'theme-starfield'};var d=['dark','ocean','pine','plum','midnight','ember','rosewood','cyberpunk','starfield'];if(v==='system'||!v){v=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'default';}if(m[v]){r.classList.add(m[v]);r.style.colorScheme=d.indexOf(v)>=0?'dark':'light';}}catch(e){}})();`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
{/* Vaporwave scenery (see app/globals.css): the outrun floor grid,
|
||||||
|
plus palm silhouettes at either side of the horizon. All fixed
|
||||||
|
behind the content, hidden by default; the theme class on <html>
|
||||||
|
switches them on. */}
|
||||||
|
<div className="vw-floor" aria-hidden />
|
||||||
|
<svg className="vw-palm-defs" aria-hidden>
|
||||||
|
<symbol id="vw-palm" viewBox="0 0 120 150">
|
||||||
|
<g fill="none" stroke="currentColor" strokeLinecap="round">
|
||||||
|
<path d="M60 150C57 110 56 80 60 45" strokeWidth="8" />
|
||||||
|
<path d="M60 45Q38 30 10 48" strokeWidth="9" />
|
||||||
|
<path d="M60 45Q44 18 20 12" strokeWidth="9" />
|
||||||
|
<path d="M60 45Q56 14 42 4" strokeWidth="9" />
|
||||||
|
<path d="M60 45Q66 12 84 6" strokeWidth="9" />
|
||||||
|
<path d="M60 45Q78 16 100 12" strokeWidth="9" />
|
||||||
|
<path d="M60 45Q84 30 110 50" strokeWidth="9" />
|
||||||
|
</g>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
<svg className="vw-palm vw-palm--left-main" aria-hidden>
|
||||||
|
<use href="#vw-palm" />
|
||||||
|
</svg>
|
||||||
|
<svg className="vw-palm vw-palm--left-small" aria-hidden>
|
||||||
|
<use href="#vw-palm" />
|
||||||
|
</svg>
|
||||||
|
<svg className="vw-palm vw-palm--right-main" aria-hidden>
|
||||||
|
<use href="#vw-palm" />
|
||||||
|
</svg>
|
||||||
|
<svg className="vw-palm vw-palm--right-small" aria-hidden>
|
||||||
|
<use href="#vw-palm" />
|
||||||
|
</svg>
|
||||||
<ThemeProvider defaultTheme="system">
|
<ThemeProvider defaultTheme="system">
|
||||||
<TooltipProvider delay={200}>
|
<TooltipProvider delay={200}>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ export function CategoryLane({ category }: { category: CategoryDTO }) {
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
ref={setNodeRef}
|
ref={setNodeRef}
|
||||||
|
data-category-lane=""
|
||||||
style={{ transform: CSS.Transform.toString(transform), transition }}
|
style={{ transform: CSS.Transform.toString(transform), transition }}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-72 shrink-0 flex-col overflow-hidden rounded-2xl border bg-lane",
|
"flex h-full w-72 shrink-0 flex-col overflow-hidden rounded-2xl border bg-lane",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue