release: promote beta to main (gyms, brand colours, JPEG XL, SEO per gym) #3

Merged
andre merged 74 commits from beta into main 2026-10-26 19:47:48 +00:00
Showing only changes of commit 7bf2a8542e - Show all commits
+58 -34
View File
@@ -354,20 +354,23 @@ section[id] {
color: var(--fitme-accent); color: var(--fitme-accent);
} }
/* ── 3D "pushable" neon button ───────────────────────────────────────────────── /* ── 3D "pushable" neon button (seen at an angle) ──────────────────────────────
The element itself is the face. On hover it lifts straight up by --depth and The element itself is the face. On hover it lifts toward the viewer — up by
a ::before strip, hanging off the face's bottom edge, grows to fill the gap: --depth and left by --depth-x — and two pseudo-elements grow to fill the gap:
that strip is the extruded wall, lit in the brand colour with a neon glow ::before is the bottom wall, ::after the right wall. Each is a parallelogram
(darker at both ends like a rounded edge). Only transform / opacity animate (clip-path) joining the face's edge to where the face used to be, so the
(compositor-only). Lift springs (overshoot curve), release is slow, press is solid reads as an extruded block viewed from the right. Walls are lit in the
instant — same feel as a physical key. Colours come from --fitme-accent, so brand colour with a neon glow; the right one is a shade darker (light comes
each gym glows in its own colour. */ from the top-left). Only transform animates (compositor-only): lift springs
(overshoot curve), release is slow, press is instant. Colours come from
--fitme-accent, so each gym glows in its own colour. */
:where(.site-btn, .gym-switch-btn) { position: relative; } :where(.site-btn, .gym-switch-btn) { position: relative; }
.site-btn, .site-btn,
.gym-switch-btn { .gym-switch-btn {
--depth: 5px; --depth: 5px; /* lift (and bottom wall height) */
--bw: 0px; /* the element's own border, so the wall starts below it */ --depth-x: 4px; /* shift to the left (and right wall width) */
--bw: 0px; /* the element's own border, so the walls start outside it */
--wall-hi: color-mix(in srgb, var(--fitme-accent) 70%, #fff); --wall-hi: color-mix(in srgb, var(--fitme-accent) 70%, #fff);
--wall: var(--fitme-accent); --wall: var(--fitme-accent);
--wall-lo: color-mix(in srgb, var(--fitme-accent) 45%, #000); --wall-lo: color-mix(in srgb, var(--fitme-accent) 45%, #000);
@@ -376,30 +379,51 @@ section[id] {
.site-btn.sb-ghost { --bw: 2px; } .site-btn.sb-ghost { --bw: 2px; }
.site-btn::before, .site-btn::before,
.gym-switch-btn::before { .site-btn::after,
.gym-switch-btn::before,
.gym-switch-btn::after {
content: ""; content: "";
position: absolute; 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; pointer-events: none;
transform-origin: top left;
}
/* bottom wall */
.site-btn::before,
.gym-switch-btn::before {
left: calc(var(--bw) * -1);
top: calc(100% + var(--bw));
width: calc(100% + var(--bw) * 2 + var(--depth-x));
height: var(--depth);
background: linear-gradient(to right, var(--wall-lo) 0%, var(--wall) 12%, var(--wall-hi) 50%, var(--wall) 88%, var(--wall-lo) 100%);
clip-path: polygon(0 0, calc(100% - var(--depth-x)) 0, 100% 100%, var(--depth-x) 100%);
transform: scaleY(0);
}
/* right wall */
.site-btn::after,
.gym-switch-btn::after {
left: calc(100% + var(--bw));
top: calc(var(--bw) * -1);
width: var(--depth-x);
height: calc(100% + var(--bw) * 2 + var(--depth));
background: linear-gradient(to bottom, var(--wall) 0%, var(--wall-lo) 100%);
clip-path: polygon(0 0, 100% var(--depth), 100% 100%, 0 calc(100% - var(--depth)));
transform: scaleX(0);
} }
@media (hover: hover) and (prefers-reduced-motion: no-preference) { @media (hover: hover) and (prefers-reduced-motion: no-preference) {
.site-btn, .site-btn,
.gym-switch-btn { .gym-switch-btn {
will-change: transform; will-change: transform;
/* the face colour fades slowly so the change to near-black never "pops" */
transition: transform 600ms cubic-bezier(.3, .7, .4, 1), box-shadow 600ms cubic-bezier(.3, .7, .4, 1), 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); background-color 450ms ease, border-color 450ms ease, color 450ms ease;
} }
.site-btn::before, .site-btn::before,
.gym-switch-btn::before { .site-btn::after,
.gym-switch-btn::before,
.gym-switch-btn::after {
transition: transform 600ms cubic-bezier(.3, .7, .4, 1); transition: transform 600ms cubic-bezier(.3, .7, .4, 1);
} }
@@ -407,29 +431,29 @@ section[id] {
.site-btn:focus-visible, .site-btn:focus-visible,
.gym-switch-btn:hover, .gym-switch-btn:hover,
.gym-switch-btn:focus-visible { .gym-switch-btn:focus-visible {
transform: translateY(calc(var(--depth) * -1)); transform: translate(calc(var(--depth-x) * -1), calc(var(--depth) * -1));
box-shadow: 0 0 18px 2px rgba(var(--fitme-accent-rgb), .35); box-shadow: 0 0 18px 2px rgba(var(--fitme-accent-rgb), .35);
transition-duration: 250ms, 250ms, var(--fitme-transition), var(--fitme-transition); transition-duration: 250ms, 250ms, 450ms, 450ms, 450ms;
transition-timing-function: cubic-bezier(.3, .7, .4, 1.5); transition-timing-function: cubic-bezier(.3, .7, .4, 1.5), cubic-bezier(.3, .7, .4, 1.5), ease, ease, ease;
} }
.site-btn:hover::before, .site-btn:hover::before,
.site-btn:focus-visible::before, .site-btn:focus-visible::before,
.gym-switch-btn:hover::before, .gym-switch-btn:hover::before,
.gym-switch-btn:focus-visible::before { .gym-switch-btn:focus-visible::before { transform: scaleY(1); transition: transform 250ms cubic-bezier(.3, .7, .4, 1.5); }
transform: scaleY(1); .site-btn:hover::after,
transition: transform 250ms cubic-bezier(.3, .7, .4, 1.5); .site-btn:focus-visible::after,
} .gym-switch-btn:hover::after,
.gym-switch-btn:focus-visible::after { transform: scaleX(1); transition: transform 250ms cubic-bezier(.3, .7, .4, 1.5); }
.site-btn:active, .site-btn:active,
.gym-switch-btn:active { .gym-switch-btn:active {
transform: translateY(-1px); transform: translate(-1px, -1px);
transition-duration: 34ms; transition-duration: 34ms;
} }
.site-btn:active::before, .site-btn:active::before,
.gym-switch-btn:active::before { .gym-switch-btn:active::before { transform: scaleY(.2); transition-duration: 34ms; }
transform: scaleY(.2); .site-btn:active::after,
transition-duration: 34ms; .gym-switch-btn:active::after { transform: scaleX(.25); transition-duration: 34ms; }
}
} }
/* Hover: white text on an almost-black face keeping ~10% of the brand colour — /* Hover: white text on an almost-black face keeping ~10% of the brand colour —