Compare commits
2 Commits
e4d50f047c
...
7b12dcbe40
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b12dcbe40 | ||
|
|
e780a3c96f |
92
src/App.css
92
src/App.css
@@ -2778,10 +2778,102 @@ body.has-player .chat-fab {
|
|||||||
padding: 0.35rem 0.85rem;
|
padding: 0.35rem 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Amplitude of the header button's idle rocking, as a 0–1 scale. Registered
|
||||||
|
so it can be transitioned: the keyframes below multiply their offsets by it,
|
||||||
|
which turns a hard switch between still and rocking into a fade. */
|
||||||
|
@property --btn-bob {
|
||||||
|
syntax: "<number>";
|
||||||
|
inherits: false;
|
||||||
|
initial-value: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.app-header-nav .btn-primary {
|
.app-header-nav .btn-primary {
|
||||||
padding: 0.35rem 1rem;
|
padding: 0.35rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* `:not(:disabled)` earns this rule a third class's worth of weight, which it
|
||||||
|
needs: geocities and brutalist re-declare the whole `transition` shorthand
|
||||||
|
on every button at one class plus one element plus a :not, and neither list
|
||||||
|
mentions `translate`, so without it their lists win and the lift lands
|
||||||
|
instantly instead of easing. Nothing here applies to a disabled button
|
||||||
|
anyway — it can't be hovered. */
|
||||||
|
.app-header-nav .btn-primary:not(:disabled) {
|
||||||
|
/* Pivot at the bottom edge, so the rock below reads as a head on a neck
|
||||||
|
rather than as the whole button spinning about its middle. */
|
||||||
|
transform-origin: 50% 100%;
|
||||||
|
/* Both motions are declared here rather than on :hover, and held paused, so
|
||||||
|
that leaving the button fades the rocking out instead of cutting it: the
|
||||||
|
amplitude eases to zero under an animation that is merely frozen. Paused
|
||||||
|
also means an untouched button isn't animating a thing. */
|
||||||
|
animation:
|
||||||
|
btn-hover-tilt 2.6s ease-in-out infinite,
|
||||||
|
btn-hover-float 3.4s ease-in-out infinite;
|
||||||
|
animation-play-state: paused;
|
||||||
|
/* The lift is carried by `translate` rather than `transform` so the rocking,
|
||||||
|
which needs `transform` and `rotate` to itself, composes with it instead
|
||||||
|
of replacing it. It eases in and out rather than out alone — a fast start
|
||||||
|
is what made the button feel like it snapped up to meet the cursor. */
|
||||||
|
transition:
|
||||||
|
background var(--dur-base),
|
||||||
|
color var(--dur-base),
|
||||||
|
border-color var(--dur-base),
|
||||||
|
box-shadow var(--dur-base),
|
||||||
|
translate var(--dur-lift) var(--ease-in-out),
|
||||||
|
--btn-bob var(--dur-bob-fade) var(--ease-in-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-header-nav .btn-primary:hover:not(:disabled) {
|
||||||
|
translate: 0 -2px;
|
||||||
|
/* The rocking starts the moment the lift does, but from nothing, and takes
|
||||||
|
longer than the lift to reach full throw — so the button is already
|
||||||
|
drifting as it settles, and never visibly changes gear. */
|
||||||
|
--btn-bob: 1;
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pressing puts it back down flat — the base :active transform can only take
|
||||||
|
effect once the animation stops claiming `transform`. */
|
||||||
|
.app-header-nav .btn-primary:active:not(:disabled) {
|
||||||
|
translate: none;
|
||||||
|
animation: none;
|
||||||
|
--btn-bob: 0;
|
||||||
|
/* The press has to land at once — at the lift's own easing it would float
|
||||||
|
back down under the finger. */
|
||||||
|
transition-duration: var(--dur-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The rock is the motion; the float underneath it is small and on a period
|
||||||
|
that doesn't divide the rock's, so the two never line up the same way twice
|
||||||
|
and it never settles into a metronome. */
|
||||||
|
@keyframes btn-hover-tilt {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
rotate: 0deg;
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
rotate: calc(var(--btn-bob, 0) * 2.5deg);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
rotate: calc(var(--btn-bob, 0) * -2.5deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes btn-hover-float {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(calc(var(--btn-bob, 0) * -2px));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.app-header-nav .btn-primary {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Icon-only controls are square, so the row reads as a tidy set. */
|
/* Icon-only controls are square, so the row reads as a tidy set. */
|
||||||
.app-header-nav .nav-search-btn,
|
.app-header-nav .nav-search-btn,
|
||||||
.app-header-nav .notification-bell,
|
.app-header-nav .notification-bell,
|
||||||
|
|||||||
@@ -364,6 +364,13 @@
|
|||||||
transform: translate(2px, 2px);
|
transform: translate(2px, 2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The header's dump button floats in the base theme; here it presses into the
|
||||||
|
page instead, so neither the lift nor the idle drift applies. */
|
||||||
|
[data-style="brutalist"] .app-header-nav .btn-primary:hover:not(:disabled) {
|
||||||
|
translate: none;
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── btn-border ──────────────────────────────────────────────────── */
|
/* ── btn-border ──────────────────────────────────────────────────── */
|
||||||
[data-style="brutalist"] .btn-border {
|
[data-style="brutalist"] .btn-border {
|
||||||
box-shadow: 2px 2px 0 var(--color-border);
|
box-shadow: 2px 2px 0 var(--color-border);
|
||||||
|
|||||||
@@ -101,6 +101,10 @@
|
|||||||
--kngw-number: light-dark(#b35b79, #d27e99);
|
--kngw-number: light-dark(#b35b79, #d27e99);
|
||||||
--kngw-chrome: light-dark(#e5ddb0, #181820);
|
--kngw-chrome: light-dark(#e5ddb0, #181820);
|
||||||
--kngw-selection: light-dark(#c9cbd1, #223249);
|
--kngw-selection: light-dark(#c9cbd1, #223249);
|
||||||
|
/* Over a photo the ground is the black scrim in either scheme, so the
|
||||||
|
accent there stays Wave's crystalBlue — Lotus's lotusBlue4 is picked to
|
||||||
|
sit on warm paper and goes muddy on black. */
|
||||||
|
--kngw-accent-on-photo: #7e9cd8;
|
||||||
|
|
||||||
/* Shape & depth — flat like an editor, deep only where things float */
|
/* Shape & depth — flat like an editor, deep only where things float */
|
||||||
--border-width: 1px;
|
--border-width: 1px;
|
||||||
@@ -156,6 +160,19 @@
|
|||||||
color: var(--kngw-comment);
|
color: var(--kngw-comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── On the scrim, links hover in the dark scheme's blue ─────────── */
|
||||||
|
[data-style="kanagawa"] .journal-card--image .journal-card-title:hover {
|
||||||
|
color: var(--kngw-accent-on-photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-style="kanagawa"]
|
||||||
|
.journal-card--image
|
||||||
|
.journal-card-overlay
|
||||||
|
.vote-btn:not(.vote-btn--active):hover:not(:disabled) {
|
||||||
|
color: var(--kngw-accent-on-photo);
|
||||||
|
border-color: var(--kngw-accent-on-photo);
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Quotes read as string literals ──────────────────────────────── */
|
/* ── Quotes read as string literals ──────────────────────────────── */
|
||||||
[data-style="kanagawa"] .journal-card--quote {
|
[data-style="kanagawa"] .journal-card--quote {
|
||||||
background: var(--color-surface);
|
background: var(--color-surface);
|
||||||
|
|||||||
@@ -356,6 +356,12 @@
|
|||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flat ink on paper: the header's dump button doesn't lift or drift either. */
|
||||||
|
[data-style="nyt"] .app-header-nav .btn-primary:hover:not(:disabled) {
|
||||||
|
translate: none;
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Secondary / outline buttons — plain hairline box */
|
/* Secondary / outline buttons — plain hairline box */
|
||||||
|
|
||||||
/* ── Inputs — clean field, ink focus ─────────────────────────────── */
|
/* ── Inputs — clean field, ink focus ─────────────────────────────── */
|
||||||
|
|||||||
@@ -86,6 +86,10 @@
|
|||||||
--dur-base: 0.15s;
|
--dur-base: 0.15s;
|
||||||
--dur-slow: 0.2s;
|
--dur-slow: 0.2s;
|
||||||
--dur-reveal: 0.25s;
|
--dur-reveal: 0.25s;
|
||||||
|
/* A hover lift long enough not to snap, and the slower fade that brings the
|
||||||
|
idle rocking in over the top of it. */
|
||||||
|
--dur-lift: 0.4s;
|
||||||
|
--dur-bob-fade: 0.9s;
|
||||||
|
|
||||||
/* ── Layers ── */
|
/* ── Layers ── */
|
||||||
--z-raised: 1;
|
--z-raised: 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user