diff --git a/client/src/components/BottomNav.tsx b/client/src/components/BottomNav.tsx
index 36d5333..d5b57e2 100644
--- a/client/src/components/BottomNav.tsx
+++ b/client/src/components/BottomNav.tsx
@@ -22,6 +22,7 @@ import {
} from "lucide-react";
import { Link, useLocation } from "wouter";
import { useMemo } from "react";
+import { appShellColumnClass, appShellGutterClass } from "@/lib/appShell";
type BottomNavLocale = NonNullable<(typeof localeZh)["bottomNav"]>;
@@ -56,16 +57,19 @@ export default function BottomNav() {
return (
);
}
diff --git a/client/src/components/DesktopAIShell.tsx b/client/src/components/DesktopAIShell.tsx
index 4aa7805..94c9def 100644
--- a/client/src/components/DesktopAIShell.tsx
+++ b/client/src/components/DesktopAIShell.tsx
@@ -92,7 +92,9 @@ export default function DesktopAIShell({ children }: { children: ReactNode }) {
"min-w-0",
showSplit
? "h-full min-h-0 overflow-y-auto overflow-x-hidden"
- : "min-h-dvh max-h-dvh overflow-x-hidden overflow-y-auto overscroll-y-contain [touch-action:pan-y]",
+ : isLgUp
+ ? "min-h-dvh overflow-x-hidden"
+ : "min-h-dvh max-h-dvh overflow-x-hidden overflow-y-auto overscroll-y-contain [touch-action:pan-y]",
)}
style={
showSplit
diff --git a/client/src/index.css b/client/src/index.css
index 5d0869b..d35637f 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -116,12 +116,25 @@
* {
@apply border-border outline-ring/50;
}
+ html,
+ body,
+ #root {
+ min-height: 100%;
+ }
+
body {
@apply bg-background text-foreground;
font-family: -apple-system, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', sans-serif;
-webkit-font-smoothing: antialiased;
background-color: #000000;
}
+
+ /* Desktop / ultrawide: page scrolls on window; shell stays centered */
+ @media (min-width: 1024px) {
+ html {
+ overflow-x: hidden;
+ }
+ }
button:not(:disabled),
[role="button"]:not([aria-disabled="true"]),
[type="button"]:not(:disabled),
diff --git a/client/src/lib/appShell.ts b/client/src/lib/appShell.ts
new file mode 100644
index 0000000..26d4c67
--- /dev/null
+++ b/client/src/lib/appShell.ts
@@ -0,0 +1,8 @@
+/** Centered phone-style shell width (desktop / ultrawide). */
+export const APP_SHELL_MAX_PX = 1180;
+
+/** Inner column inside horizontal gutters — use with a flex/grid centering parent. */
+export const appShellColumnClass =
+ "w-full min-w-0 max-w-[min(1180px,100%)]";
+
+export const appShellGutterClass = "px-4 sm:px-6";
diff --git a/client/src/locales/data-en.json b/client/src/locales/data-en.json
index c26691e..c12bd38 100644
--- a/client/src/locales/data-en.json
+++ b/client/src/locales/data-en.json
@@ -546,19 +546,7 @@
},
{
"index": 2,
- "label": "Chinese"
- },
- {
- "index": 3,
- "label": "German"
- },
- {
- "index": 4,
- "label": "Spanish"
- },
- {
- "index": 5,
- "label": "French"
+ "label": "Simplified Chinese"
}
]
},
diff --git a/client/src/locales/data-zh-HK.json b/client/src/locales/data-zh-HK.json
index 52aced7..9990bde 100644
--- a/client/src/locales/data-zh-HK.json
+++ b/client/src/locales/data-zh-HK.json
@@ -384,10 +384,7 @@
"options": [
{ "index": 0, "label": "英語" },
{ "index": 1, "label": "中文(繁體)" },
- { "index": 2, "label": "中文(簡體)" },
- { "index": 3, "label": "德語" },
- { "index": 4, "label": "西語" },
- { "index": 5, "label": "法語" }
+ { "index": 2, "label": "中文(簡體)" }
]
},
"Automatic": {
diff --git a/client/src/locales/data-zh.json b/client/src/locales/data-zh.json
index 04c680c..b743b77 100644
--- a/client/src/locales/data-zh.json
+++ b/client/src/locales/data-zh.json
@@ -385,10 +385,7 @@
"options": [
{ "index": 0, "label": "英语" },
{ "index": 1, "label": "中文(繁体)" },
- { "index": 2, "label": "中文(简体)" },
- { "index": 3, "label": "德语" },
- { "index": 4, "label": "西班牙语" },
- { "index": 5, "label": "法语" }
+ { "index": 2, "label": "中文(简体)" }
]
},
"Automatic": {
diff --git a/client/src/pages/SelectPage.tsx b/client/src/pages/SelectPage.tsx
index 88c0a4f..1449479 100644
--- a/client/src/pages/SelectPage.tsx
+++ b/client/src/pages/SelectPage.tsx
@@ -13,8 +13,12 @@
import { useLocation } from "wouter";
import { ChevronLeft, Check } from "lucide-react";
import { useDevice } from "@/contexts/DeviceContext";
+import { cn } from "@/lib/utils";
import { useEffect, useState } from "react";
+const iisModeImageUrl = (index: number) =>
+ `${import.meta.env.BASE_URL}IIS/iis_app${index + 1}.png`;
+
/* ── Key → API field mapping ── */
const KEY_TO_SETTING: Record
= {
effect_value: "effect_value",
@@ -118,26 +122,68 @@ export default function SelectPage() {
-
- {options.map((opt, idx) => {
- const isSelected = idx === selectedIdx;
- return (
-
- );
- })}
-
+ {key === "IISMode" ? (
+
+ {options.map((opt, idx) => {
+ const isSelected = idx === selectedIdx;
+ return (
+
+ );
+ })}
+
+ ) : (
+
+ {options.map((opt, idx) => {
+ const isSelected = idx === selectedIdx;
+ return (
+
+ );
+ })}
+
+ )}