style(site): pushable 3D neon buttons (lifting face + ::before wall, spring curves)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
andreandClaude Sonnet 5.5 committed 2026-10-13 18:18:17 +01:00
1 parent 251644c393
commit acac3a191a
1 file changed
+58 -25
+58 -25
View File
@@ -354,48 +354,81 @@ section[id] {
color: var(--fitme-accent);
}
/* ── 3D neon extrusion on hover ────────────────────────────────────────────────
The button lifts off the "wall" toward the viewer; the faces it leaves behind
(the extruded sides) are drawn with stacked hard shadows in the brand colour
and lit like neon tubes (glow on top). Colours come from the gym's brand
tokens, so each gym glows in its own colour. */
/* ── 3D "pushable" neon button ─────────────────────────────────────────────────
The element itself is the face. On hover it lifts straight up by --depth and
a ::before strip, hanging off the face's bottom edge, grows to fill the gap:
that strip is the extruded wall, lit in the brand colour with a neon glow
(darker at both ends like a rounded edge). Only transform / opacity animate
(compositor-only). Lift springs (overshoot curve), release is slow, press is
instant — same feel as a physical key. Colours come from --fitme-accent, so
each gym glows in its own colour. */
:where(.site-btn, .gym-switch-btn) { position: relative; }
.site-btn,
.gym-switch-btn {
--neon: color-mix(in srgb, var(--fitme-accent) 70%, #fff);
--neon-edge: var(--fitme-accent-dark);
--depth: 4px;
--depth: 5px;
--bw: 0px; /* the element's own border, so the wall starts below it */
--wall-hi: color-mix(in srgb, var(--fitme-accent) 70%, #fff);
--wall: var(--fitme-accent);
--wall-lo: color-mix(in srgb, var(--fitme-accent) 45%, #000);
}
.site-btn.sb-line,
.site-btn.sb-ghost { --bw: 2px; }
.site-btn::before,
.gym-switch-btn::before {
content: "";
position: absolute;
left: 0;
right: 0;
top: calc(100% + var(--bw));
height: var(--depth);
border-radius: 0 0 var(--fitme-radius) var(--fitme-radius);
background: linear-gradient(to right, var(--wall-lo) 0%, var(--wall) 10%, var(--wall-hi) 50%, var(--wall) 90%, var(--wall-lo) 100%);
box-shadow: 0 2px 14px 1px rgba(var(--fitme-accent-rgb), .6);
transform: scaleY(0);
transform-origin: top;
pointer-events: none;
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
.site-btn,
.gym-switch-btn {
transition: transform .18s ease, box-shadow .18s ease, background var(--fitme-transition), color var(--fitme-transition);
will-change: transform;
transition: transform 600ms cubic-bezier(.3, .7, .4, 1), box-shadow 600ms cubic-bezier(.3, .7, .4, 1),
background var(--fitme-transition), color var(--fitme-transition);
}
.site-btn::before,
.gym-switch-btn::before {
transition: transform 600ms cubic-bezier(.3, .7, .4, 1);
}
.site-btn:hover,
.site-btn:focus-visible,
.gym-switch-btn:hover,
.gym-switch-btn:focus-visible {
transform: translate(calc(var(--depth) * -1), calc(var(--depth) * -1));
/* The extruded sides ARE the neon: three lit steps (bright at the face,
settling toward the wall) and a soft glow round the whole solid. The
face itself stays plain — no second outline, so nothing reads as a copy. */
box-shadow:
inset 1px 1px 0 rgba(var(--fitme-accent-rgb), .55), /* lit top-left bevel on the face */
1px 1px 0 var(--neon),
2px 2px 0 var(--fitme-accent),
3px 3px 0 color-mix(in srgb, var(--fitme-accent) 75%, #000),
4px 4px 0 color-mix(in srgb, var(--fitme-accent) 50%, #000),
0 0 18px 3px rgba(var(--fitme-accent-rgb), .4),
4px 4px 22px 2px rgba(var(--fitme-accent-rgb), .3);
transform: translateY(calc(var(--depth) * -1));
box-shadow: 0 0 18px 2px rgba(var(--fitme-accent-rgb), .35);
transition-duration: 250ms, 250ms, var(--fitme-transition), var(--fitme-transition);
transition-timing-function: cubic-bezier(.3, .7, .4, 1.5);
}
.site-btn:hover::before,
.site-btn:focus-visible::before,
.gym-switch-btn:hover::before,
.gym-switch-btn:focus-visible::before {
transform: scaleY(1);
transition: transform 250ms cubic-bezier(.3, .7, .4, 1.5);
}
.site-btn:active,
.gym-switch-btn:active {
transform: translate(-1px, -1px);
box-shadow:
1px 1px 0 var(--neon),
0 0 10px 1px rgba(var(--fitme-accent-rgb), .5);
transform: translateY(-1px);
transition-duration: 34ms;
}
.site-btn:active::before,
.gym-switch-btn:active::before {
transform: scaleY(.2);
transition-duration: 34ms;
}
}