A liquid-glass UI pass: snake borders, noise, conic gradients
Rotating conic-gradient borders with @property, backdrop-filter glow cards, SVG feTurbulence noise, and the things we deliberately didn't do. The CSS behind why the dashboard feels different.

For the first few months, the FeedbackIQ UI was correct and forgettable — dark zinc, cyan accent, flat cards, rounded buttons. It worked. It looked like every other side-project dashboard on the internet. When a product’s differentiator is “this tool feels different than other feedback tools,” the UI has to carry part of that claim.
So we did a liquid-glass pass. The goal: keep the dark aesthetic, but make surfaces feel layered, luminous, and slightly alive — Apple’s 2025 visual language filtered through a dev-tool lens. Three ingredients carry most of the effect.
Snake borders with conic-gradient
The primary CTA (.btn-snake) has a cyan-blue gradient fill and a rotating conic-gradient border that runs like a snake of light around the button on hover. It’s done with zero JavaScript, using @property for a custom angle that CSS can animate:
@property --fiq-angle {
syntax: "<angle>";
initial-value: 0deg;
inherits: false;
}
@keyframes fiq-spin {
to { --fiq-angle: 360deg; }
}
.btn-snake::before {
content: "";
position: absolute;
inset: -2px;
padding: 2px;
border-radius: inherit;
background: conic-gradient(
from var(--fiq-angle),
transparent 0%,
rgba(34,211,238,0.9) 20%,
rgba(125,211,252,1) 30%,
rgba(34,211,238,0) 50%,
transparent 100%
);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;
transition: opacity 0.25s ease;
z-index: -1;
}
.btn-snake:hover::before {
opacity: 1;
animation: fiq-spin 2.4s linear infinite;
}The trick is the mask-composite pair: the outer conic gradient becomes only the border because the inner content box masks out everything else. The border then spins by animating --fiq-angle. Before @property existed this was a hack; now it’s essentially a one-liner.
Glow cards with backdrop-filter
Every content card on the marketing site is a .glow-card: a layered gradient inner, blurred backdrop, soft inner top highlight, and a hover state that subtly lifts and emits cyan glow. The CSS is ~20 lines and replaces every previous card style in the codebase:
.glow-card {
border: 1px solid rgba(255,255,255,0.06);
background:
linear-gradient(180deg, rgba(255,255,255,0.025), rgba(255,255,255,0) 40%),
rgba(24,24,27,0.55);
backdrop-filter: blur(18px) saturate(140%);
border-radius: 0.75rem;
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.04),
0 1px 2px rgba(0,0,0,0.3);
transition:
border-color 0.35s cubic-bezier(0.16,1,0.3,1),
box-shadow 0.35s cubic-bezier(0.16,1,0.3,1),
transform 0.35s cubic-bezier(0.16,1,0.3,1);
}
.glow-card:hover {
border-color: rgba(34,211,238,0.25);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.05),
0 20px 40px -20px rgba(34,211,238,0.25),
0 0 32px -8px rgba(34,211,238,0.12);
transform: translateY(-1px);
}Noise and grid textures
Pure flat dark backgrounds read as cheap. A small amount of stochastic noise and a faint grid makes them feel like a real surface. The noise is an inline SVG feTurbulence filter baked into a data-URI, applied at ~3% opacity on top of everything:
.noise-bg::before {
content: "";
position: fixed;
inset: 0;
z-index: 9999;
pointer-events: none;
opacity: 0.03;
background-image: url("data:image/svg+xml,%3Csvg ...%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
background-size: 128px 128px;
}The grid is two linear gradients at 72px tiling. It’s the visual-weight equivalent of adding one grain of salt to a dish — you can’t point at it, but you can feel its absence.
What we deliberately didn’t do
No animated gradients on page backgrounds. No particle fields. No cursor followers. No bespoke fonts. The visual language is confident precisely because it stops before it gets cute. When every surface has a flourish, no surface is special.
The perf cost
backdrop-filter is the one thing to watch — it can wreck paint times on mid-range Android if you stack too many blurred surfaces. We cap it at three visible at once, and the widget itself uses a flat blur (no saturate) because it’s rendering in a Shadow DOM on someone else’s marketing site where we don’t own the frame budget.
Next up: the SEO pass. Comparison pages, a technical blog (this one), llms.txt, structured data, and OG images generated by a Gemini 2.5 Flash Image prompt chain.
Try FeedbackIQ
Drop a widget on your site, ship PRs from feedback
Claude reads the report, writes the fix, opens the PR on your repo. Dedupe with pgvector so the backlog doesn’t drown in duplicates.
Start for free