diff --git a/openless-all/app/scripts/windows-ui-config.test.mjs b/openless-all/app/scripts/windows-ui-config.test.mjs
index 873afdbb..4d9ddb61 100644
--- a/openless-all/app/scripts/windows-ui-config.test.mjs
+++ b/openless-all/app/scripts/windows-ui-config.test.mjs
@@ -55,7 +55,7 @@ if (!/function WindowsResizeHandles\(\)/.test(windowChromeTsx)) {
assertMatch(
windowChromeTsx,
- /const MAC_TITLEBAR_HEIGHT = 30;/,
+ /const MAC_TITLEBAR_HEIGHT = 28;/,
'macOS titlebar spacer should stay visually compact around the native traffic lights',
);
assertMatch(
@@ -108,7 +108,7 @@ if (!/export function getCapsuleHostMetrics\(\s*os: OS,\s*translationActive: boo
throw new Error('capsule layout should define explicit host metrics separate from the visible pill metrics');
}
-if (!/if \(os === 'win'\)\s*\{[\s\S]*?width: 220,[\s\S]*?height: translationActive \? 118 : 84,[\s\S]*?bottomInset: 12,[\s\S]*?badgeGap: 8[\s\S]*?\}/.test(capsuleLayoutTs)) {
+if (!/if \(os === 'win'\)\s*\{[\s\S]*?const horizontalInset = 12;[\s\S]*?const pill = getCapsulePillMetrics\(os\);[\s\S]*?width: pill\.width \+ horizontalInset \* 2,[\s\S]*?height: translationActive \? 118 : 84,[\s\S]*?horizontalInset,[\s\S]*?bottomInset: 12,[\s\S]*?badgeGap: 8,[\s\S]*?boxSizing: 'border-box',[\s\S]*?\}/.test(capsuleLayoutTs)) {
throw new Error('windows capsule host metrics should leave room for shadow and badge geometry');
}
@@ -116,19 +116,23 @@ if (!/const hostMetrics = getCapsuleHostMetrics\(os,\s*translation\);/.test(caps
throw new Error('capsule should derive host metrics from the shared layout contract');
}
-if (!/justifyContent:\s*os === 'win' \? 'flex-end' : 'center'/.test(capsuleTsx)) {
- throw new Error('windows capsule host should anchor the pill to the bottom instead of centering it inside the larger native host window');
+if (!/return\s*\(\s*
CapsuleWindowBounds {
#[cfg(target_os = "windows")]
{
+ const WINDOWS_CAPSULE_PILL_WIDTH: f64 = 196.0;
+ const WINDOWS_CAPSULE_SIDE_INSET: f64 = 12.0;
CapsuleWindowBounds {
- width: 220.0,
+ // Keep the existing Windows hitbox width, but express it as
+ // pill width (196) + symmetric 12px side insets for shadow room.
+ width: WINDOWS_CAPSULE_PILL_WIDTH + WINDOWS_CAPSULE_SIDE_INSET * 2.0,
height: if translation_active { 118.0 } else { 84.0 },
bottom_inset: 12.0,
}
diff --git a/openless-all/app/src/components/Capsule.tsx b/openless-all/app/src/components/Capsule.tsx
index 4c669598..6ee474a9 100644
--- a/openless-all/app/src/components/Capsule.tsx
+++ b/openless-all/app/src/components/Capsule.tsx
@@ -15,9 +15,14 @@ interface AudioBarsProps {
function AudioBars({ level }: AudioBarsProps) {
const envelope = [0.55, 0.85, 1.0, 0.85, 0.55];
- const base = 4;
- const max = 18;
+ const base = 2;
+ const max = 24;
const voice = Math.min(1, Math.max(0, level));
+ const silenceGate = 0.012;
+ const responseCeiling = 0.34;
+ const gatedVoice = Math.min(1, Math.max(0, (voice - silenceGate) / (responseCeiling - silenceGate)));
+ const easedVoice = gatedVoice * gatedVoice * (3 - 2 * gatedVoice);
+ const visualVoice = Math.pow(easedVoice, 0.42);
return (
@@ -110,6 +116,8 @@ interface CircleButtonProps {
function CircleButton({ variant, enabled, onClick }: CircleButtonProps) {
const { t } = useTranslation();
const isCancel = variant === 'cancel';
+ const os = detectOS();
+ const useBackdrop = os !== 'win' && isCancel;
return (