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;
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
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. */
|
||||
.app-header-nav .nav-search-btn,
|
||||
.app-header-nav .notification-bell,
|
||||
|
||||
@@ -364,6 +364,13 @@
|
||||
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 ──────────────────────────────────────────────────── */
|
||||
[data-style="brutalist"] .btn-border {
|
||||
box-shadow: 2px 2px 0 var(--color-border);
|
||||
|
||||
@@ -101,6 +101,10 @@
|
||||
--kngw-number: light-dark(#b35b79, #d27e99);
|
||||
--kngw-chrome: light-dark(#e5ddb0, #181820);
|
||||
--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 */
|
||||
--border-width: 1px;
|
||||
@@ -156,6 +160,19 @@
|
||||
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 ──────────────────────────────── */
|
||||
[data-style="kanagawa"] .journal-card--quote {
|
||||
background: var(--color-surface);
|
||||
|
||||
@@ -356,6 +356,12 @@
|
||||
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 */
|
||||
|
||||
/* ── Inputs — clean field, ink focus ─────────────────────────────── */
|
||||
|
||||
@@ -86,6 +86,10 @@
|
||||
--dur-base: 0.15s;
|
||||
--dur-slow: 0.2s;
|
||||
--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 ── */
|
||||
--z-raised: 1;
|
||||
|
||||
Reference in New Issue
Block a user