skills/lino-ui-upgrade/SKILL.md

21 KiB

name description
lino-ui-upgrade Lino UI Upgrade — a unified futuristic design system that fuses Neumorphism (soft tactile depth), Skeuomorphism (real-world materiality), Glassmorphism (frosted blur surfaces), and Liquid Glass (iOS 26 dynamic refraction) into one premium UI language. Use this skill whenever the user asks to upgrade, redesign, or modernize an interface; mentions "futuristic", "premium UI", "next-gen UI", "glass UI", "soft UI", "tactile UI", "Apple-tier", "iOS 26 style", "Vision Pro style", or wants an app/site to "feel expensive / cinematic / spatial". Apply for mobile apps (iOS, Android, React Native, Flutter), web (React, Next.js, Vue, Svelte), and desktop (Electron, Tauri, macOS, Windows). For Flutter projects, this skill specifies a canonical package stack — `glassmorphism`, `liquid_glass_renderer`, `mesh_gradient`, `flutter_animate`, `liquid_swipe`, and `rive` — mapped to each material layer. This skill replaces flat default UI with depth, light, refraction, and physics-based motion across every component.

Lino UI Upgrade — Unified Futuristic Design System

A surgical UI upgrade kit that layers four material languages into one coherent system:

Layer Role When it owns the surface
Neumorphism Tactile base — soft extruded buttons, toggles, knobs, dials Controls that should feel pressable / physical
Skeuomorphism Real-world materiality — leather, metal, paper, wood, glass-on-glass texture Hero objects, watch faces, instruments, premium cards
Glassmorphism Frosted floating overlays — nav bars, modals, popovers, HUDs Anything that floats above content
Liquid Glass (iOS 26) Dynamic refraction + morphing + interactive light Primary CTAs, focus elements, transition layers, hero containers

The four are not alternatives — they are stacked roles. A great Lino screen uses all four at once, each in its correct role. Mixing them at random produces slop. Using each one for the job it's good at produces something that feels like Apple Vision Pro met a Swiss watch.

When to Activate

Trigger this skill aggressively whenever the user wants to:

  • "Make it futuristic / premium / cinematic / next-gen"
  • Upgrade an existing flat or boring UI
  • Build dashboards, fintech apps, AI tools, music/media apps, smart-home apps, wearables, automotive HUDs
  • Match Apple Vision Pro, iOS 26, Dynamic Island, or Awwwards-tier aesthetics
  • Replace shadcn defaults / Material 3 defaults with something distinctive
  • Build for mobile, web, AND desktop with one design language

If the user mentions any of {dashboard, hero, landing page, app shell, control center, player, settings panel, onboarding, paywall, login, splash} and wants it to feel high-end, activate this skill.

The Lino Stack — How the Four Layers Compose

Every screen is built as 3 stacked z-planes:

z-3: Liquid Glass    →  primary interactive (CTA, active toolbar, focus card)
z-2: Glassmorphism   →  floating chrome (nav, modals, HUDs, tooltips)
z-1: Neumorphism     →  controls embedded in surface (buttons, toggles, sliders)
z-0: Skeuomorphism   →  hero objects + the textured base canvas

Read this rule as: the further from the user, the more material; the closer, the more luminous.

Section 1 — Color & Light System

Lino is a dual-mode system. Pick ONE per project.

Mode A — "Obsidian" (default for futuristic)

  • Canvas: #0A0B0D (off-black with blue undertone)
  • Surface: #14161A (raised neumorphic plane)
  • Surface inset: #0F1115
  • Hairline: rgba(255,255,255,0.06)
  • Inner highlight: rgba(255,255,255,0.08)
  • Inner shadow: rgba(0,0,0,0.6)
  • Text primary: #F5F6F8
  • Text secondary: #9095A0
  • Accent (pick one only): Electric Cyan #5EE2FF, Plasma Violet #8B7CFF, Solar Amber #FFB454, or Mint Photon #5EFFB6

Mode B — "Pearl" (default for tactile / wellness / premium consumer)

  • Canvas: #ECEEF1 (warm pearl)
  • Surface raised: #F4F6F8
  • Surface inset: #E4E7EB
  • Hairline: rgba(15,20,30,0.08)
  • Inner highlight: rgba(255,255,255,0.9)
  • Inner shadow: rgba(150,160,180,0.35)
  • Text primary: #11151B
  • Text secondary: #5A6473
  • Accent: same options as Obsidian, used sparingly

Banned colors

Pure #000, pure #FFF for surfaces, AI purple/blue gradients, more than one accent per screen, neon outer glows, oversaturated default Tailwind palette.

Section 2 — Neumorphism Layer (the tactile base)

Use for: buttons, toggles, sliders, knobs, segmented controls, search inputs, dial widgets, settings rows.

The dual-shadow formula

Every neumorphic element gets two shadows simultaneously — one light from top-left, one dark from bottom-right.

/* Obsidian mode — raised */
.neu-raised {
  background: #14161A;
  border-radius: 20px;
  box-shadow:
    -6px -6px 14px rgba(255,255,255,0.04),
     6px  6px 14px rgba(0,0,0,0.55);
}

/* Obsidian mode — inset (pressed / active) */
.neu-inset {
  background: #14161A;
  border-radius: 20px;
  box-shadow:
    inset -4px -4px 10px rgba(255,255,255,0.04),
    inset  4px  4px 10px rgba(0,0,0,0.55);
}

/* Pearl mode — raised */
.neu-raised-pearl {
  background: #ECEEF1;
  box-shadow:
    -6px -6px 14px rgba(255,255,255,0.9),
     6px  6px 14px rgba(150,160,180,0.35);
}

Rules

  • Light source is always top-left at 315°. Never rotate it across components — inconsistent lighting destroys the illusion.
  • Background of the neumorphic element must equal the parent surface color. Different colors break the "extruded from the surface" effect.
  • Press state = swap raised → inset. Animate over 120ms with cubic-bezier(0.32, 0.72, 0, 1).
  • Never put a neumorphic element on a glass / blurred background. It needs an opaque parent.
  • Border-radius must be at least 16px — neumorphism collapses at sharp corners.

Tailwind variant

<button className="
  bg-[#14161A] rounded-2xl px-6 py-4 text-white/90
  shadow-[-6px_-6px_14px_rgba(255,255,255,0.04),6px_6px_14px_rgba(0,0,0,0.55)]
  active:shadow-[inset_-4px_-4px_10px_rgba(255,255,255,0.04),inset_4px_4px_10px_rgba(0,0,0,0.55)]
  transition-all duration-150 ease-[cubic-bezier(0.32,0.72,0,1)]
">
  Press me
</button>

Section 3 — Skeuomorphism Layer (the hero materials)

Use sparingly — one skeuomorphic hero per screen, max. Use for: watch faces, music players' vinyl, camera shutters, instrument dials, premium card mockups, the "physical" thing your app is replacing.

The four real materials Lino supports

Brushed metal — subtle horizontal noise + soft gradient + 1px inner highlight at the top edge.

background:
  linear-gradient(180deg, #2A2D33 0%, #1B1D21 100%),
  url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="2"><rect width="200" height="1" fill="rgba(255,255,255,0.04)"/></svg>');
background-blend-mode: overlay;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.12), 0 20px 40px rgba(0,0,0,0.4);

Glass-over-glass (skeuo crystal) — a real-world lens cap effect using backdrop-filter: blur() + a radial highlight on top.

position: relative;
background: rgba(255,255,255,0.04);
backdrop-filter: blur(20px) saturate(140%);
border: 1px solid rgba(255,255,255,0.12);
border-radius: 28px;
&::before {
  content: '';
  position: absolute; inset: 0;
  background: radial-gradient(120% 80% at 30% 0%, rgba(255,255,255,0.18), transparent 60%);
  border-radius: inherit; pointer-events: none;
}

Soft leather / paper — fine grain noise + warm tone + inset shadow at edges. Use SVG noise, not images.

Polished ceramic — for wellness/health apps. Smooth radial gradient + diffuse soft shadow + zero hairlines.

Rules

  • Skeuomorphic objects must cast a real shadow on the canvas below. Always include a soft drop shadow (40-60px blur, 30% opacity, offset Y +20).
  • Add a single specular highlight at the top — this is what makes it read as a physical object.
  • Never apply skeuomorphism to chrome (nav, buttons in toolbars). It belongs on content.
  • One material per screen. Brushed metal + leather + glass-over-glass on the same view = costume party.

Section 4 — Glassmorphism Layer (the floating chrome)

Use for: top navs, side panels that overlay content, modals, popovers, tooltips, command palettes, floating action menus, HUDs over media.

The four glass strengths

// Whisper — barely visible, for ambient HUDs
<div className="bg-white/5 backdrop-blur-sm border border-white/8 rounded-2xl" />

// Standard — nav bars, toolbars
<div className="bg-white/8 backdrop-blur-md saturate-150 border border-white/12 rounded-2xl" />

// Strong — modals, command palettes
<div className="bg-black/35 backdrop-blur-xl saturate-150 border border-white/15 rounded-3xl" />

// Crystal — splash overlays, hero scrims
<div className="bg-white/12 backdrop-blur-2xl saturate-180 border border-white/20 rounded-[2rem]
                shadow-[inset_0_1px_0_rgba(255,255,255,0.18),0_20px_60px_rgba(0,0,0,0.4)]" />

Rules — these are the difference between premium glass and slop

  • Always pair backdrop-blur with saturate(140-180%). Without saturation boost, blurred content looks washed out and dead.
  • Always include the inner top highlight: inset 0 1px 0 rgba(255,255,255,0.15). This is the edge refraction. Skipping it makes the glass look flat.
  • Never put glass on a flat solid background — it needs busy content behind it (image, gradient, scrolling list) or there's nothing to refract.
  • Never apply backdrop-blur to scrolling containers — only to fixed/sticky elements. Causes catastrophic mobile FPS drop.
  • Border must use rgba(255,255,255, X) — never solid gray. The whole point is light passing through the edge.

Glass over hero image — the canonical Lino nav

<nav className="fixed top-4 inset-x-4 z-50 mx-auto max-w-5xl
                bg-white/8 backdrop-blur-xl saturate-150
                border border-white/12 rounded-full
                shadow-[inset_0_1px_0_rgba(255,255,255,0.18),0_8px_32px_rgba(0,0,0,0.3)]
                px-6 py-3 flex items-center justify-between">
  ...
</nav>

Section 5 — Liquid Glass Layer (the interactive light)

This is the top-of-stack material — primary CTAs, focus elements, the active tab in a tab bar, the morphing element during a transition. It's glassmorphism + reactive light + spring physics.

What makes Liquid Glass different from Glassmorphism

Glassmorphism Liquid Glass
Static blur Dynamic refraction that reacts to cursor / touch
Fixed shape Morphs between shapes during state changes
Single layer Has inner gloss + edge refraction + ambient color pickup
backdrop-blur backdrop-blur + displacement + radial highlight that follows pointer

Native iOS 26 (use when available)

Button("Continue") { /* */ }
    .buttonStyle(.glassProminent)
    .glassEffect(.regular.tint(.cyan).interactive(), in: .capsule)

Web / React equivalent

function LiquidGlassButton({ children }: { children: React.ReactNode }) {
  const ref = useRef<HTMLButtonElement>(null);
  // pointer position drives a CSS variable for the radial highlight
  const onMove = (e: React.PointerEvent) => {
    const r = ref.current!.getBoundingClientRect();
    ref.current!.style.setProperty('--mx', `${e.clientX - r.left}px`);
    ref.current!.style.setProperty('--my', `${e.clientY - r.top}px`);
  };
  return (
    <button
      ref={ref}
      onPointerMove={onMove}
      className="
        relative isolate overflow-hidden
        px-7 py-3.5 rounded-full
        bg-white/10 backdrop-blur-xl saturate-180
        border border-white/20
        text-white font-medium
        shadow-[inset_0_1px_0_rgba(255,255,255,0.25),inset_0_-1px_0_rgba(0,0,0,0.3),0_8px_32px_rgba(0,0,0,0.3)]
        transition-transform duration-300 ease-[cubic-bezier(0.32,0.72,0,1)]
        active:scale-[0.97]
        before:content-[''] before:absolute before:inset-0 before:rounded-full
        before:bg-[radial-gradient(120px_circle_at_var(--mx)_var(--my),rgba(255,255,255,0.25),transparent_60%)]
        before:pointer-events-none before:transition-opacity
      "
    >
      <span className="relative z-10">{children}</span>
    </button>
  );
}

Morphing — the signature move

When a Liquid Glass element changes role (button → expanded panel, tab → hero card), it must morph, not swap. Use Framer Motion's layoutId on web, matchedGeometryEffect on iOS.

<motion.div layoutId="primary-cta" className="liquid-glass-pill">
  {expanded ? <FullPanel /> : <CompactButton />}
</motion.div>

Spring physics only: { type: "spring", stiffness: 220, damping: 26 }. Never linear.

Section 6 — Composition Rules (How to actually build a screen)

A canonical Lino screen, top to bottom:

  1. Canvas — Obsidian or Pearl. Optionally a slow-drifting radial gradient blob (opacity: 0.04, animation: 30s drift infinite) to give the glass something to refract.
  2. Hero zone — one Skeuomorphic object (the watch face, the album art, the device mockup), casting a real shadow.
  3. Content cards — Neumorphic raised surfaces, holding text and small controls.
  4. Floating chrome — Glassmorphic nav (top), glass tab bar (bottom on mobile), glass side rail (desktop).
  5. Primary action — Liquid Glass CTA, single per screen.

Asymmetric Bento layout (default)

┌─────────────────────────────────────┐
│  [Skeuo Hero — col-span-2 row-2]    │
│                                      │
├──────────────┬──────────────────────┤
│ [Neu Card]   │ [Neu Card]           │
│              │                      │
└──────────────┴──────────────────────┘
       [Liquid Glass CTA — fixed]
[Glass Nav — fixed top]

Spacing

8px base. Section padding py-24 minimum on desktop, py-12 mobile. Card internal padding p-8 desktop, p-5 mobile.

Typography

Display: Geist, Satoshi, or SF Pro Display (iOS). Tight tracking -0.025em, weights 500-700. Body: same family, 400, line-height 1.6, max-width 65ch. Mono (for numbers in dashboards): Geist Mono or SF Mono. Banned: Inter, generic system serifs, Roboto.

Section 7 — Motion Choreography

Every Lino interaction obeys spring physics. Linear easing is banned.

Interaction Spring config Duration
Press feedback stiffness: 400, damping: 30 120ms
Hover lift stiffness: 250, damping: 25 200ms
Glass morph stiffness: 220, damping: 26 400ms
Page enter stiffness: 100, damping: 20 + 80ms stagger 600ms
Modal in stiffness: 180, damping: 22 350ms

Hardware rule: animate only transform and opacity. Never width, height, top, left. Backdrop-filter is GPU-expensive — apply only to fixed elements, never scroll-bound.

Perpetual micro-loops — every active dashboard tile gets one infinite subtle animation: pulse on a status dot, shimmer on a skeleton, slow drift on a background blob. Never on more than 3 elements per viewport.

Section 8 — Platform Adaptation

Mobile (iOS / Android / React Native / Flutter)

  • Bottom tab bar: Glassmorphism strong, safe-area-inset-bottom padding.
  • Primary CTA: Liquid Glass, full-width with 16px side margin, min-h: 56px for thumb.
  • Cards: Neumorphism, border-radius: 24px.
  • Hero: Skeuomorphism (album art, watch face).
  • Touch targets: 44x44 min. Press state = neu inset transition.
  • Use min-height: 100dvh, never 100vh (iOS Safari jump).

Web (React / Next / Vue / Svelte)

  • Top nav: floating Glass pill, detached from edge with mt-4 mx-auto.
  • Dashboard cards: Neumorphic Bento grid (asymmetric, never 3 equal columns).
  • Modals: Glass strong with backdrop scrim bg-black/40.
  • CTA: Liquid Glass with cursor-tracking highlight.
  • Responsive: collapse all multi-col to single col under 768px. w-full px-4.

Desktop (Electron / Tauri / macOS / Windows native)

  • Window chrome: Glass standard with traffic lights / window controls.
  • Sidebar: Neumorphism inset rail, 72px wide collapsed / 240px expanded.
  • Content area: Skeuomorphic surface (paper, leather) for document apps; Obsidian canvas for tools.
  • Command palette (Cmd-K): Glass crystal, centered, with Liquid Glass selected row.
  • Use platform vibrancy APIs when available (NSVisualEffectView on macOS, Mica on Windows 11) instead of CSS backdrop-filter.

Section 9 — Accessibility (non-negotiable)

  • Reduced motion: respect prefers-reduced-motion: reduce. Disable morphing, perpetual loops, parallax. Keep press feedback.
  • Reduced transparency: respect prefers-reduced-transparency. Replace glass surfaces with opaque equivalents using the surface token.
  • Contrast: text on glass must hit 4.5:1. If the background is unpredictable (image), add a subtle bg-black/40 scrim under the glass.
  • Focus rings: visible 2px ring in accent color, 2px offset. Liquid Glass elements get a ring + subtle outer glow on focus-visible.
  • Hit area: 44x44 mobile, 32x32 desktop minimum.
  • Test with screen reader: glass / skeuo decorative effects must be aria-hidden.

Section 10 — Anti-Patterns (auto-fail)

  • Mixing 3+ materials at the same z-level (e.g. neumorphism + skeuomorphism on the same button)
  • Glass on a flat solid background (nothing to refract)
  • Backdrop-blur on scrolling containers (kills mobile FPS)
  • Pure #000 or #FFF surfaces
  • More than one accent color per screen
  • More than one Skeuomorphic hero per screen
  • More than one Liquid Glass primary CTA per screen
  • Linear easing
  • Animating width/height/top/left
  • Inconsistent neumorphic light direction (always top-left at 315°)
  • Glass without saturate() companion
  • Glass without inner top highlight
  • Neumorphism on a glass parent
  • Emojis as icons (use Phosphor Light, SF Symbols, or Radix Icons)
  • Inter font in any premium context
  • AI purple/blue gradients
  • Generic shadcn defaults left untuned

Section 11 — Pre-Flight Checklist

Before shipping any Lino screen:

  • One canvas mode (Obsidian or Pearl), not both
  • One accent color
  • At most one Skeuomorphic hero
  • At most one Liquid Glass primary CTA
  • All glass surfaces include saturate() + inner top highlight
  • Neumorphic elements share parent surface color, light from 315°
  • All transitions use spring physics (not linear / ease-in-out)
  • Backdrop-blur only on fixed/sticky elements
  • Layout collapses to single column under 768px
  • min-h-[100dvh] not h-screen
  • prefers-reduced-motion and prefers-reduced-transparency honored
  • Focus rings visible on all interactive elements
  • Touch targets ≥ 44x44 on mobile
  • No banned fonts, colors, or motion patterns
  • Real device test on a mid-tier Android (glass FPS check)

Section 12 — Quick-Start Recipes

Recipe: Futuristic mobile app shell (React Native / Expo)

  1. Canvas: Obsidian.
  2. Top status bar: transparent, safe-area-inset-top.
  3. Hero card: Skeuomorphic (brushed metal background) holding the day's primary content.
  4. Two Bento Neumorphic cards below.
  5. Bottom tab bar: Glass standard, fixed, blur-xl + saturate-150.
  6. Active tab indicator: Liquid Glass pill that morphs between tabs via layoutId.

Recipe: Premium SaaS dashboard (Next.js + Tailwind)

  1. Canvas: Obsidian with one drifting radial blob in the accent color (opacity-[0.05]).
  2. Top nav: floating Glass pill, full-width minus 32px margin, rounded-full.
  3. Sidebar: Neumorphic inset rail.
  4. Main grid: 5-card Bento (1 large + 4 small), each Neumorphic raised.
  5. Primary CTA in header: Liquid Glass with cursor-tracking highlight.
  6. Modals (Cmd-K): Glass crystal, Liquid Glass on selected row.

Recipe: Music / media app (cross-platform)

  1. Canvas: Obsidian.
  2. Hero: Skeuomorphic vinyl / album art with real cast shadow, slowly rotating during playback.
  3. Player controls: Neumorphic raised circular buttons (play/pause swaps raised ↔ inset).
  4. Now-playing bar: Glass standard, fixed bottom.
  5. Lyrics overlay: Glass crystal full-screen sheet.
  6. Next-track button: Liquid Glass that morphs into expanded queue.

Recipe: Smart-home / IoT control panel (desktop / tablet)

  1. Canvas: Pearl (warmer, more residential).
  2. Hero: Skeuomorphic thermostat dial (polished ceramic) with real shadow.
  3. Room cards: Neumorphic raised, one per room.
  4. Top bar: Glass whisper.
  5. Scene activator: Liquid Glass capsule, morphs to show active scene.

Final principle

Lino UI is not maximalism. It's disciplined material stacking. Every layer earns its place by doing one job the others can't. When in doubt, remove a layer rather than add one. A screen with only Neumorphism + Glass can still be a Lino screen. A screen with all four piled on top of each other is a costume.

The goal is the feeling of holding a piece of impossibly well-engineered hardware that happens to be made of light.