| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
| |
Root.svelte already gated the fly transition on
\$settings.displayDisableAnimations, but the View Transition path
added in 7e2495bd ran unconditionally. The setting appeared broken
because the slide kept firing via the browser API.
Adds the same check to onNavigate via get(settings) (the callback is
not in reactive context, so a synchronous store read is the right
shape). When the setting is on, both transition paths bypass and
navigation snaps as expected.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Wires SvelteKit's onNavigate hook into document.startViewTransition,
with a callback that bypasses cleanly when the API is unavailable or
the user prefers reduced motion.
Direction is computed from navigation.from/to.pathname using the same
navigationOrder logic as the existing fly slide (forward through the
ordered routes, backward otherwise; entering /user is +1, leaving
-1). Sign is written to --vt-direction on :root before the transition
fires.
::view-transition-old(root) and -new(root) get explicit slide
keyframes that read --vt-direction as a sign multiplier on
translateX(200px), replacing the browser default crossfade with a
direction-aware page-flip that matches the prior feel.
.header carries view-transition-name: app-header so it is pulled out
of the root snapshot and treated as a shared element. Since the
header lives outside the {#key data.url} block and is the same DOM
element on both sides, its morph is a visual no-op: only the body
slides past it instead of the whole viewport.
Svelte's existing fly transition in Root.svelte still runs hidden
beneath the snapshot for browsers without View Transitions support,
acting as a graceful fallback.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Two unrelated modernisations:
- Adds &display=swap to the Roboto and Overpass Google Fonts URLs
imported by Wrapped's stylesheet. Avoids the invisible-text flash
during font load on the Wrapped page; DM Sans already had this.
- Adds content-visibility: auto to each child of .badges (the grid
on the badge wall page). Browser skips layout and paint for off
-screen badges until they scroll into view. contain-intrinsic-size
auto 8rem reserves placeholder space so the scrollbar stays stable.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A document-level click delegate intercepts <summary> clicks and
animates the parent <details> height instead of relying on the
browser's instant snap.
Initial attempt used the CSS pseudo-element approach
(::details-content + interpolate-size: allow-keywords). Both features
have shipped at different times across browsers (Safari < 18.2 has
neither, Safari 18.2 to 25 only has the pseudo) and degrade in
distinct broken ways. JS via WAAPI works in every browser that has
shipped Web Animations.
Closed height is computed from the summary's offsetHeight plus the
details element's vertical padding and border (read from
getComputedStyle), so the animation end-state matches the natural
collapsed height regardless of per-element padding tweaks
(details-unstyled, card variants, etc). Earlier draft animated to
summary.offsetHeight only, which undershot by 2 * padding and caused
the element to clip text before snapping back to its resting height.
Respects prefers-reduced-motion (bypass to native toggle). Uses a
WeakMap so rapid toggles cancel the in-flight animation cleanly.
Duration 240ms / cubic-bezier(0.22,1,0.36,1) matches the panel-class
motion token used elsewhere.
|
| |
|
|
|
|
|
| |
When the menu is open and the user scrolls, they have signalled they
want to interact with content rather than the menu. Closes
isMenuOpen on any scroll event alongside the existing
isHeaderVisible recalculation in the same handler.
|
| |
|
|
|
|
|
|
|
|
| |
Dropdown items add border-radius: 8px on hover. The pre-485f1b11
:global(a) transition: all rule used to animate the corner rounding;
the narrowed list excluded it. Adds a scoped transition on
.dropdown-content a that mirrors the global anchor list plus
border-radius, so the corner rounding eases in over 150ms instead of
snapping. CommandPalette dropdown sets border-radius in base state so
is unaffected.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Commit 485f1b11 narrowed :global(a) transition to color/opacity/
text-decoration-color, intentionally excluding background. That
swallowed background-color animation across every anchor, including
the dropdown items (Schedule, Profile) whose :hover toggles
background-color from base01.
Adds background-color to the narrowed list. The original intent of
excluding background-image / shorthand background transitions still
holds; only background-color was a real loss.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
A surface audit of commit 963d6356 (which narrowed the universal *
transition rule) identified two genuine regressions: .button-badge
and .badge-info, both <span> chip styles in src/styles/badge.css.
Their :hover changes background-color, which the global * rule used
to animate but the narrowed :where() list did not catch.
Adds them to the :where() list. All other state-change surfaces
audited either still match the existing selectors (anchors, buttons,
form controls, cards, ARIA roles) or have their own explicit
transition rule (covers, tool cards, badge wall, previews).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds src/styles/_breakpoints.scss with five canonical tokens
(\$bp-sm 600, \$bp-md 800, \$bp-lg 1024, \$bp-xl 1280, \$bp-2xl 1600)
and migrates all 15 @media (max-width: ...) occurrences across 9 files.
Configures vite.config.ts with scss loadPaths so any file can
@use "breakpoints" without relative paths.
Conservative rounding-up where existing values were near-duplicates:
500 and 512 collapse to 600, 768 collapses to 800, 1000 collapses to
1024. Slightly more viewports get the smaller-layout treatment in
those bands, which is usually beneficial on cramped widths.
Converts 7 Svelte files from <style> to <style lang="scss"> to access
the SCSS tokens. SCSS is a CSS superset, so existing rules stay valid.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The existing --base0011 glass tint is #ffffff80 / #0c0c0c80 (50%
alpha), which is unusually transparent for floating UI. The desktop
header and the mobile hamburger sit over scrolling content, so the
content bleeds through and reads as distracting.
Introduces --base0011-strong at #ffffffcc / #0c0c0ccc (80% alpha) for
floating chrome. The backdrop blur still has enough content to soften,
but the surface now reads as grounded rather than barely-present.
Applied to: desktop .header background, mobile toggle background and
hover, mobile open panel background. Other glass cards (CommandPalette
dropdown, Dropdown component content, tooltips, hover covers) keep the
softer --base0011 since they sit over relatively static surfaces and
the see-through effect there is not distracting.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Adds 0.24s between --duration-fast (0.15s) and --duration-slow (0.4s)
for animations that live in the touch-UI floor: panels, sheets,
drawers, modals. 150ms reads as crisp on desktop but undershoots the
200-300ms range touch UI conventions prescribe (finger occludes the
target during the tap, deliberation pace is slower, and high-DPI
displays compress small translateY into less perceptible motion).
Applies the new token to the mobile hamburger panel open/close
transition and to the bar-morph that fires on the same tap, so the
bars and the panel finish arriving together.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Three changes to the mobile floating header:
- Restore the desktop scroll-driven hide/show on the corner button by
dropping the transform:none override. Override the translate distance
under 800px so the toggle (44px tall at top:1.25rem) and its 5px
outline ring fully clear the viewport: translateY(calc(-100% - 2rem))
instead of -150%, which had been leaving 3px of ring poking through.
- Replace display:none / display:flex on the open panel (uneanimatable)
with always-rendered panel that flips opacity, transform, visibility,
and pointer-events. Uses --duration-fast / --ease-out-quart so the
motion vocabulary matches the rest of the project. transform-origin
is top right so the scale grows from the toggle position.
- Move per-item styling out of the .menu-open qualifier so items keep
their block layout even while the panel is faded out, avoiding a
layout reflow at the moment menu-open flips.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Two related touch fixes:
- Dropdown :hover rule was sticky on touch devices after a tap, keeping
the menu visible even when the click toggle set open to false. Gate
the hover rule behind @media (hover: hover) so only true pointer
devices use the hover path; touch uses the click-driven open class.
- Hamburger menu had no outside-click close. Added a window click
handler that closes isMenuOpen when the target is outside .header.
Clicks on the toggle and on nav items stay inside .header, so opening
and item navigation are unaffected.
|
| |
|
|
|
|
|
| |
100vh on mobile Safari/Chrome locks to the largest viewport (URL bar
collapsed), so the hero overflows by the bar's height when the page
loads with the bar visible, then shrinks when the user scrolls. 100dvh
tracks the dynamic viewport and avoids the jump.
|
| |
|
|
| |
This reverts commit b429cf8d3b566a6ec665cd4f2ec34f55c3138179.
|
| |
|
|
|
|
|
|
| |
Result rows are <a>, not <button>, so the global input.css coarse
-pointer height bump did not cascade. Adds a scoped pointer:coarse
block that lifts vertical padding from 0.5em to 0.875em (~46px tall
at the palette's 1.05em base) and trims row margin so the taller
rows do not double-space.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Below 800px the inline header overflows the viewport. Strips card chrome
from .header itself and floats it position:fixed at top:1.25rem/right
:1.25rem so it does not consume a horizontal band. The 44x44 toggle
button carries the desktop banner's exact card recipe (--base0011 glass,
shadow-card-emphasized + 5px --base02 ring, blur, 8px radius), and the
open panel mirrors it as a separately-positioned card below.
Menu closes on route navigation and Escape. Header stays visible while
the menu is open so a scroll-driven hide does not chop the open sheet
mid-interaction. Profile-avatar anchor and the bullet separator are
hidden in the mobile menu (avatar is redundant alongside the Profile
dropdown; separator reads as line noise vertically).
|
| |
|
|
|
|
|
|
| |
Inputs, buttons, and selects baseline at 32px (2em), well below WCAG
2.5.5's 44x44 minimum. Adds a coarse-pointer media block that lifts
the standard height to 2.75rem, neutralises aggressive 0.75 scale on
.smaller-button / .button-square (transforms shrink hit-test rects),
and grows the checkbox from 1.15em to 1.5rem.
|
| |
|
|
|
|
|
|
| |
Add explicit .header-item:focus { outline: none } and
.header-item:focus-visible rules in +layout.svelte so the navbar
matches the dropdown menu's teal rounded ring on keyboard focus and
stops leaking the browser default blue square ring on mouse click.
Same pattern as the Dropdown component's scoped focus-visible rule.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
Introduce --shadow-card, --shadow-card-emphasized, --shadow-cta,
--scrim, --scrim-soft, and --scrim-banner. Migrate 14 inline
literals (card.css, input.css, Notification, MediaRoulette, the
two Landing CTA buttons, the popup overlay, the palette and
roulette scrims, three identity banners, the user profile cover
art shadow) onto the tokens, with light/dark adaptation handled
by the existing prefers-color-scheme blocks instead of duplicated
inline. Two single-use Landing demo-focus values stay inline.
|
| |
|
|
|
|
|
|
|
|
|
| |
Strip backdrop-filter: blur(4px) from the base .card so the ~50
in-flow surfaces (landing panels, schedule rows, tool cards, user
profile cards, badge wall, etc.) stop paying for a blur they don't
need. Introduce .card-glass for the surfaces that actually float over
other content: the sticky page header, header nav dropdowns, command
palette, title-attribute tooltips, LinkedTooltip, and HoverCover.
Popup, MediaRoulette, and Notification keep their existing
parent-overlay or solid-background treatments.
|
| |
|
|
|
|
|
|
|
| |
Replace generic alt="Avatar" / alt="Character" with empty alts on
images that visually duplicate a name already present as adjacent text
(Wrapped activity avatar, Hololive stream icon, three Birthdays
covers); screen readers stop announcing "Avatar" / "Character" twice.
Also swap the em dash in the landing subheadline for a comma per the
project copy rule.
|
| |
|
|
|
|
|
|
|
| |
Replace the * { transition: color/bg/border/shadow } rule with a
:where() list of the surfaces that actually receive state changes
(anchors, buttons, form controls, cards, details/summary, role=button,
role=menuitem, role=option). Every element no longer pays the
transition (especially box-shadow, the costly one) on theme switch or
parent re-paint.
|
| |
|
|
|
|
|
|
|
| |
Add loading=lazy and decoding=async to the 16 <img> elements that
weren't already deferring across Tools/Wrapped, Events, EasterEvent,
Hololive, and the rate-limited fallback. Also drop the
backdrop-filter: blur(160px) the dropdown items were paying on every
hover; the background-color change already gives sufficient feedback,
and the parent card's own blur stays.
|
| |
|
|
|
|
|
|
| |
Wrap the palette in role=dialog with aria-modal, mark the overlay
aria-hidden, and turn the search input into a labeled combobox driving
a listbox of role=option results via aria-activedescendant. Trap Tab on
the input, preventDefault on Escape, and restore focus to the
previously-focused element when the palette closes.
|
| |
|
|
|
| |
The scoped :focus-visible rule on dropdown menu items no longer needs
its own border-radius now that the global rule sets it.
|
| |
|
|
|
|
| |
Add border-radius: 4px to the global :focus-visible rule so the ring
looks consistent on bare anchors and header items, not just on
elements that already carry their own radius.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Wire Enter/Space/ArrowDown/ArrowUp/Escape on the toggle and
ArrowDown/ArrowUp/Home/End/Escape on each item so the Schedule and
Profile menus are reachable without a mouse. Add aria-haspopup,
aria-expanded, aria-controls, and role=menu/menuitem; give each
instance a unique toggle/menu id so the two header dropdowns no longer
collide. Close the menu on item activation so preventDefault items
(e.g. Log Out) don't leave it hanging open. Focus moves via
`await tick()` so :focus-visible matches reliably, with a scoped
fallback outline tuned to var(--base0D) for the menu items.
|
| |
|
|
|
|
|
| |
Add a global reduced-motion media query that collapses animation and
transition durations and disables smooth scroll. Skip Lenis init when
the same preference is set so the JS-driven smooth scroll falls back to
the browser default, which the spec already honours.
|
| |
|
|
|
|
|
| |
Replace `a:focus { outline: none }` with `:focus { outline: none }` +
`:focus-visible { outline: 2px solid var(--base0D); outline-offset: 2px }`
so keyboard users see focus on every interactive element while mouse
clicks stay clean.
|
| |
|
|
| |
Add --ease-out-quart, --ease-in-out-quart, --duration-fast, --duration-slow in motion.css and migrate the global anchor, header, and theme-switch transitions to use them. Establishes a shared motion vocabulary for future polish.
|
| |
|
|
| |
Replace transform 0.3s ease with 0.4s cubic-bezier(0.22, 1, 0.36, 1) so the header settles instead of snapping, pairing with Lenis-smoothed scroll.
|
| |
|
|
| |
Replace transition: all with explicit color, opacity, and text-decoration-color so unrelated property changes (transform, background) do not get incidentally tweened.
|
| |
|
|
| |
Bump Root fly duration/delay from 100ms to 180ms so the built-in opacity fade is perceptible and the slide reads against Lenis-smoothed scroll.
|
| |
|
|
| |
Lenis disables native CSS smooth scroll, so window.scrollTo({behavior:"smooth"}) jumps instantly. Expose the Lenis instance via a store and scroll through it, falling back to native when unavailable.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
| |
Adds 13 reactive quick toggles (24h time, animations, blur adult, cover
modes, hover cover, schedule list, reverse sort, data saver, notifications,
language, title format cycle, outbound link target cycle), three sync
actions (push/pull/disable), and login/logout entries gated on auth state.
Names reflect current state so the palette doubles as a status surface.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The tooltip was appended to body with no top/left, so its static-flow position
extended body.scrollWidth/scrollHeight during measurement. Fix by setting
initial top/left to -9999px so the node never lands in the flow.
Previously this slid the tooltip in from off-screen because the top/left 0.3s
transition was already live. Now the transition starts as opacity-only at
creation time; after the first updateTooltipPosition snaps into place, a
requestAnimationFrame re-enables the top/left easing so subsequent mousemove
updates keep the original smooth glide and 100ms debounce behavior.
LinkedTooltip's measurement div is parked the same way plus visibility:hidden,
since it exists only to read offsetWidth for the Svelte-rendered tooltip.
|
| |
|
|
| |
This reverts commit 28860bb88da4c08e3ba383adc9c23ae3689310b6.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Body grew on hover because the absolutely-positioned tooltip was appended to
document.body without top/left, so its static-flow position extended
body.scrollWidth/scrollHeight during layout measurement.
Switch both the use:tooltip directive and LinkedTooltip's measurement div to
position:fixed, which is relative to the viewport and does not contribute to
the body's scroll area. The directive now also uses clientX/clientY (dropping
the scrollY offset for the pin branch), removes the 100ms mousemove debounce,
and drops the top/left transition so the tooltip tracks the cursor without
feeling laggy or sliding in from the page top.
|
| |
|
|
| |
This reverts commit 6865cae76cb88aa78d7c297c637557468fdce8fc.
|
| |
|
|
|
|
| |
sliding"
This reverts commit 6e780fdb76155669a72692c64fd51c0da2c932d2.
|
| |
|
|
|
|
|
| |
The opacity+top+left transition combined with the off-screen parking caused
tooltips to animate from -9999px into place ("pops down from the top") and
lagged cursor tracking in the non-pinned variant used by birthdays. Keep only
the opacity fade; position updates snap.
|