Skip to content

feat(ui): polish visuals, motion and support across devices - #9

Merged
aMonteSl merged 1 commit into
feat/urjc-research-rolefrom
feat/visual-polish
Oct 5, 2026
Merged

aMonteSl merged 1 commit into
feat/urjc-research-rolefrom
feat/visual-polish

Conversation

@aMonteSl

@aMonteSl aMonteSl commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Stacked on #8. Merge #8 first; when its branch is deleted, GitHub retargets this PR to main.

Summary

An audit of every section at 390, 768, 1024, 1366, 1440 and 1920px, plus a code review of the design system and animations, led to the fixes below. The look stays the same: no redesign, only polish and bug fixes.

Typography and layout

  • Consistent typeface everywhere. The CSS asked for Inter but never loaded it, so each OS used its own font (Segoe UI / SF / Roboto). Inter is now self-hosted through next/font.
  • Hero:
    • On 1366×768 and 1024×768 laptops, Download CV / View projects / socials were below the fold. They now come before the long bio.
    • The bio is left-aligned on phones; 12 centred lines were hard to read.
    • Headings use text-balance.
  • Section headers share the max-w-6xl content column. At ≥1600px they no longer sit 32px left of their cards.
  • Featured project: the media aligns to the top of the card. It used to be vertically centred, which left an empty band above it.
  • Skill cards:
    • "View group" is pinned to the bottom.
    • A container-query header drops the level badge under the title on narrow cards, so "Bases de datos y Cloud" no longer breaks into three lines.
  • Journey: the "today" label no longer covers the next year's label.
  • Desktop sidebar: it now fits 1366×768. The language switcher used to be cut off.

Motion

  • Reduced-motion bug: the static HTML ships opacity:0, and components spread animate ? fadeInUp() : {}. Reduced-motion visitors could hydrate with no animation props, leaving elements stuck invisible. The fix is a global <MotionConfig reducedMotion="user"> with the motion props always passed.
  • Hero entrance is pure CSS. The first screen paints and animates before hydration (better LCP). The preload now targets the portrait actually rendered (hero-320, not hero-196).
  • Entrances:
    • Scroll-in entrances are softer (0.55s ease-out).
    • References, skills and projects get real staggers; the staggerChildren blocks that did nothing are gone.
    • Secondary projects no longer play two entrance animations, and the layout animation is gone.
  • Journey:
    • The timeline draws in when it scrolls into view. Before, it animated on page load, unseen.
    • The infinite pulses only run in view, on the horizontal layout, and without reduced motion.
    • The ongoing node breathes instead of blinking.
  • Hover:
    • No transition-all on framer-animated elements.
    • Non-clickable cards (references, certifications) no longer lift on hover.

Performance

  • Hero rotation: the hero's featured-project rotation re-rendered the whole Hero about 60 times a second, forever, even off-screen. The progress bar now runs on a MotionValue, and the rotation pauses off-screen and in hidden tabs.
  • Silk WebGL background:
    • Renders at dpr={1}, without MSAA, on the low-power GPU, at about 30fps (on-demand frameloop), with the same visual speed.
    • Its reduced-motion check is reactive.
    • The fallback is transparent, so the body gradient no longer "pops in" after mount.
  • Type shims: dropped the stale hand-written @react-three/fiber shims (src/types/fiber.d.ts, three-fiber.d.ts) that shadowed R3F 9's own types.

Devices

  • Notches and status bar:
    • New px-gutter utility: a 16/24/32px gutter that also clears landscape notches, needed because the viewport uses viewport-fit=cover.
    • Safe-area insets on the header (standalone/PWA status bar), the drawer and the floating menu button.
  • Floating menu button: below xl the home footer leaves room for it, so it no longer covers the end of the page.
  • Touch targets: 44px on footer links, the DOI chip and the header nav on touch screens at xl (iPad Pro landscape).
  • Text: tech tags go from 10 to 11px.
  • Global CSS:
    • Rules moved into @layer base, so utilities win. This fixes the double focus indicator (outline + ring) and the 2px corners on every focused pill and card.
    • About 150 lines of dead utilities removed.
  • Manifest: theme_color / background_color now match the site (#040304 instead of #403e3e).

Test plan

  • npm run check passes: lint, typecheck, translations, journey timeline.
  • npm run build passes.
    • The exported hero <h1> no longer ships inline opacity:0.
    • Inter woff2 files are emitted and the hero-320 preload is present.
  • Headless Edge screenshots of the static export at 390×844 (touch), 768×1024 (touch), 1366×768, 1440×900 and 1920×1080, every section:
    • no horizontal overflow on phones;
    • CTAs above the fold on laptops;
    • sidebar fits at 768px tall;
    • headers aligned at 1920.
  • Journey: the entrance plays once on scroll-in, nothing re-hides after a drill-down and back, and there are no hydration warnings.
  • On a real iPhone, check landscape (notch gutter) and "Add to Home Screen" (header clears the status bar).

🤖 Generated with Claude Code

Typography and layout
- Load Inter through next/font: the CSS asked for it but never loaded it,
  so every OS fell back to its own system font.
- Hero: CTAs before the long bio so they sit above the fold on 1366x768
  and 1024x768 laptops; the bio is left-aligned on phones; balanced headings.
- Section headers share the max-w-6xl content column (no 32px offset at
  >=1600px); featured project media aligns to the top of its card.
- Skill cards: "View group" pinned to the bottom, container-query header so
  narrow cards keep their titles on one or two lines.
- Journey: the "today" label no longer covers the next year's label.
- Sidebar fits 1366x768 screens (smaller portrait and rows when short).

Motion
- MotionConfig reducedMotion="user" app-wide and no more
  `animate ? fadeInUp() : {}` spreads, which left elements stuck at
  opacity 0 for reduced-motion visitors after hydration.
- Hero entrance is pure CSS, so the first screen paints before hydration;
  the preload now targets the portrait actually rendered (hero-320).
- Softer, longer scroll-in entrances; real staggers instead of dead
  staggerChildren blocks; no duplicate entrance on secondary projects.
- Journey timeline draws in when it scrolls into view; infinite pulses are
  gated (in view, horizontal layout, reduced motion); the ongoing node
  breathes instead of blinking.
- No `transition-all` on framer-animated elements; non-clickable cards no
  longer lift on hover.

Performance
- Hero featured rotation drives its progress bar with a MotionValue and
  pauses off-screen (it re-rendered the Hero every frame, forever).
- Silk background: dpr 1, no MSAA, low-power GPU, ~30fps on-demand loop,
  reactive reduced-motion check, transparent fallback (no gradient pop-in).
- Drop the stale hand-written @react-three/fiber type shims.

Devices
- Notch-aware page gutter (px-gutter) for viewport-fit=cover, safe-area
  insets on header, drawer and floating menu button.
- Footer clears the floating menu button below xl; 44px touch targets on
  footer links, DOI chip and tablet header nav; tech tags at 11px.
- Base CSS moved to @layer base: one focus ring per element instead of
  outline + ring with 2px corners; ~150 lines of dead utilities removed.
- Manifest theme/background colour matches the site (#040304).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aMonteSl
aMonteSl merged commit 422de05 into feat/urjc-research-role Oct 5, 2026
aMonteSl added a commit that referenced this pull request Oct 5, 2026
Typography and layout
- Load Inter through next/font: the CSS asked for it but never loaded it,
  so every OS fell back to its own system font.
- Hero: CTAs before the long bio so they sit above the fold on 1366x768
  and 1024x768 laptops; the bio is left-aligned on phones; balanced headings.
- Section headers share the max-w-6xl content column (no 32px offset at
  >=1600px); featured project media aligns to the top of its card.
- Skill cards: "View group" pinned to the bottom, container-query header so
  narrow cards keep their titles on one or two lines.
- Journey: the "today" label no longer covers the next year's label.
- Sidebar fits 1366x768 screens (smaller portrait and rows when short).

Motion
- MotionConfig reducedMotion="user" app-wide and no more
  `animate ? fadeInUp() : {}` spreads, which left elements stuck at
  opacity 0 for reduced-motion visitors after hydration.
- Hero entrance is pure CSS, so the first screen paints before hydration;
  the preload now targets the portrait actually rendered (hero-320).
- Softer, longer scroll-in entrances; real staggers instead of dead
  staggerChildren blocks; no duplicate entrance on secondary projects.
- Journey timeline draws in when it scrolls into view; infinite pulses are
  gated (in view, horizontal layout, reduced motion); the ongoing node
  breathes instead of blinking.
- No `transition-all` on framer-animated elements; non-clickable cards no
  longer lift on hover.

Performance
- Hero featured rotation drives its progress bar with a MotionValue and
  pauses off-screen (it re-rendered the Hero every frame, forever).
- Silk background: dpr 1, no MSAA, low-power GPU, ~30fps on-demand loop,
  reactive reduced-motion check, transparent fallback (no gradient pop-in).
- Drop the stale hand-written @react-three/fiber type shims.

Devices
- Notch-aware page gutter (px-gutter) for viewport-fit=cover, safe-area
  insets on header, drawer and floating menu button.
- Footer clears the floating menu button below xl; 44px touch targets on
  footer links, DOI chip and tablet header nav; tech tags at 11px.
- Base CSS moved to @layer base: one focus ring per element instead of
  outline + ring with 2px corners; ~150 lines of dead utilities removed.
- Manifest theme/background colour matches the site (#040304).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant