Chat chrome: one gutter, one radius scale, one even glass recipe
The header and composer were full-bleed bands (flush to the top/right/bottom viewport edges, composer corners off-screen) next to a rail that floats with a 12px margin. The new --layout-gutter (12px) spaces the rail, header, empty-state card and composer identically on every side; --radius-panel/-control/-chip (-pill) replace the ad-hoc radii across the shared classes, so every panel is rounded on all four corners and shared controls match in every theme. The desktop-only ::after hairlines and the left-corner-only radius are gone. Aero: the rail and the chat chrome (answers included) share one even recipe - the wallpaper extra-blurred into a hue-free wash (background-glass.webp) under a uniform ~50% white veil and a whisper of gloss. Measured within ~10 RGB units across the rail top->bottom and the card/composer left->right; the blue->green smear and the teal composer are gone. The composer's field is a clean even tile with no wallpaper gradient inside it. Chat fixes: send is a filled primary tile shaped exactly like attach (dimmed while the input is empty), suggestion/context chips use the shared .chip token (40/44px target, visible rim, full-contrast text, raw model id in the tooltip), the AI note reads at 12px --text-muted (.ai-disclaimer), the selected sidebar row carries the accent border + accent icon, the theme toggle is back in Aero (the moon flips to Dark; Settings brings Aero back), and the empty state is centered exactly between header and composer. Outside CSS: the wallpaper's top-left HUD-circle decoration (it peeked through the 12px gutters on wide windows) was healed out of background.webp and background-blur.webp; the orbs/bubbles ride one masked .ice-floats layer that fades them under the chrome bands and the rail strip, so none is sliced by a panel edge (still parked under reduced motion). Version 0.6.0, SW -> freezmo-v82. Tests: chat suite pins the new geometry (12px gutter, 24px corners, even wash on all four panels, send-vs-attach shape, chips/input radii); mobile pins the phone chrome and the Aero toggle; bubbles pins the floats layer + its reduced-motion opt-out.
This commit is contained in:
parent
8153fc8dae
commit
786d6cf1ae
21 changed files with 562 additions and 290 deletions
|
|
@ -75,6 +75,26 @@ async function orbAt(page, phase) {
|
|||
check("orbs: own duration per pass (30-70s, 5 distinct)", orbs.every((orb) => orb.duration >= 30 && orb.duration <= 70) && new Set(orbs.map((orb) => orb.duration)).size === 5, orbs.map((orb) => orb.duration).join(","));
|
||||
check("orbs: reduced opacity token applied", orbs.every((orb) => orb.opacity > 0.3 && orb.opacity < 0.45), String(orbs[0]?.opacity));
|
||||
|
||||
/* The floats layer: orbs + bubbles live in one masked wrapper that fades
|
||||
them out before the chrome bands, so none of them is sliced by a panel
|
||||
edge (see .ice-floats in globals.css). */
|
||||
const floats = await page.evaluate(() => {
|
||||
const layer = document.querySelector(".ice-floats");
|
||||
const style = layer ? getComputedStyle(layer) : null;
|
||||
return {
|
||||
children: layer ? layer.children.length : 0,
|
||||
orbs: document.querySelectorAll(".ice-floats .ice-orb").length,
|
||||
bubbles: document.querySelectorAll(".ice-floats .ice-bubble").length,
|
||||
mask: style ? style.maskImage || style.webkitMaskImage : "",
|
||||
};
|
||||
});
|
||||
check(
|
||||
"floats: orbs and bubbles ride one masked layer",
|
||||
floats.children === 23 && floats.orbs === 5 && floats.bubbles === 18,
|
||||
JSON.stringify(floats),
|
||||
);
|
||||
check("floats: the chrome bands fade the layer out", floats.mask.includes("gradient"), floats.mask.slice(0, 60));
|
||||
|
||||
const keyframes = await page.evaluate(() => {
|
||||
for (const sheet of document.styleSheets) {
|
||||
try {
|
||||
|
|
@ -153,8 +173,17 @@ async function orbAt(page, phase) {
|
|||
const orb = document.querySelector(".ice-orb-1");
|
||||
const style = getComputedStyle(orb);
|
||||
const rect = orb.getBoundingClientRect();
|
||||
return { animation: style.animationName, willChange: style.willChange, opacity: Number(style.opacity), top: rect.top, left: rect.left };
|
||||
const floats = getComputedStyle(document.querySelector(".ice-floats"));
|
||||
return {
|
||||
animation: style.animationName,
|
||||
willChange: style.willChange,
|
||||
opacity: Number(style.opacity),
|
||||
top: rect.top,
|
||||
left: rect.left,
|
||||
mask: floats.maskImage || floats.webkitMaskImage,
|
||||
};
|
||||
});
|
||||
check("reduced motion: the floats mask is off (parked orbs keep their spots)", state.mask === "none", state.mask);
|
||||
check("reduced motion: rise removed, layer released", state.animation === "none" && state.willChange === "auto", JSON.stringify(state));
|
||||
check("reduced motion: orb visible and faded in at a static spot", state.opacity > 0.08 && state.top > 0 && state.top < 900, JSON.stringify(state));
|
||||
await page.waitForTimeout(1100);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue