anentrypoint-design 0.0.42 → 0.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anentrypoint-design",
3
- "version": "0.0.42",
3
+ "version": "0.0.43",
4
4
  "description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
5
5
  "type": "module",
6
6
  "main": "./dist/247420.js",
@@ -12,6 +12,18 @@
12
12
  },
13
13
  "./app": "./dist/247420.app.js",
14
14
  "./css": "./dist/247420.css",
15
+ "./desktop": {
16
+ "import": "./src/desktop/index.js",
17
+ "default": "./src/desktop/index.js"
18
+ },
19
+ "./desktop/theme.css": "./src/desktop/theme.css",
20
+ "./desktop/icons.js": "./src/desktop/icons.js",
21
+ "./desktop/shell.js": "./src/desktop/shell.js",
22
+ "./page-html": {
23
+ "import": "./src/page-html.js",
24
+ "default": "./src/page-html.js"
25
+ },
26
+ "./src/page-html.js": "./src/page-html.js",
15
27
  "./package.json": "./package.json"
16
28
  },
17
29
  "files": [
@@ -0,0 +1,11 @@
1
+ export const icons = {
2
+ terminal: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M7 9l3 3-3 3M13 15h4"/></svg>',
3
+ browser: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a14 14 0 010 18M12 3a14 14 0 000 18"/></svg>',
4
+ canvas: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="14" rx="2"/><path d="M3 17l6-5 4 3 5-4 3 2"/></svg>',
5
+ files: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6a2 2 0 012-2h4l2 2h8a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2z"/></svg>',
6
+ monitor: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12l4-8 4 14 4-10 4 8 2-3"/></svg>',
7
+ validator: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12l4 4L19 6"/></svg>',
8
+ about: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 8v.01M11 12h1v5h1"/></svg>',
9
+ apps: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>',
10
+ plus: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>',
11
+ };
@@ -0,0 +1,3 @@
1
+ export { icons } from './icons.js';
2
+ export { createDesktopShell } from './shell.js';
3
+ export const themeUrl = new URL('./theme.css', import.meta.url).href;
@@ -0,0 +1,180 @@
1
+ import { icons } from './icons.js';
2
+
3
+ const THEME_CSS_URL = new URL('./theme.css', import.meta.url).href;
4
+
5
+ function ensureCss() {
6
+ if (document.querySelector('link[data-os-theme]')) return;
7
+ const l = document.createElement('link');
8
+ l.rel = 'stylesheet';
9
+ l.href = THEME_CSS_URL;
10
+ l.dataset.osTheme = '1';
11
+ document.head.appendChild(l);
12
+ }
13
+
14
+ function ic(svg) {
15
+ const s = document.createElement('span');
16
+ s.className = 'ic';
17
+ s.innerHTML = svg;
18
+ return s;
19
+ }
20
+
21
+ function makeBtn(svg, label, role) {
22
+ const b = document.createElement('button');
23
+ b.className = 'os-btn';
24
+ if (role) b.dataset.role = role;
25
+ if (svg) b.append(ic(svg));
26
+ if (label) b.append(Object.assign(document.createElement('span'), { textContent: label }));
27
+ return b;
28
+ }
29
+
30
+ export function createDesktopShell({ root = document.body, wm, registry, brand = 'desktop', themeUrl, onNewInstance, autoBoot = false } = {}) {
31
+ if (!wm) throw new Error('createDesktopShell: wm is required');
32
+ if (!registry) throw new Error('createDesktopShell: registry is required');
33
+ if (themeUrl) {
34
+ if (!document.querySelector('link[data-os-theme]')) {
35
+ const l = document.createElement('link');
36
+ l.rel = 'stylesheet';
37
+ l.href = themeUrl;
38
+ l.dataset.osTheme = '1';
39
+ document.head.appendChild(l);
40
+ }
41
+ } else {
42
+ ensureCss();
43
+ }
44
+
45
+ const osRoot = document.createElement('div');
46
+ osRoot.className = 'os-root';
47
+ osRoot.style.cssText = 'position:fixed;inset:0;display:flex;flex-direction:column;pointer-events:none;z-index:8000';
48
+ root.appendChild(osRoot);
49
+
50
+ const menubar = document.createElement('div');
51
+ menubar.className = 'os-menubar';
52
+
53
+ const brandEl = document.createElement('span');
54
+ brandEl.className = 'os-brand';
55
+ brandEl.textContent = brand;
56
+
57
+ const appsBtn = makeBtn(icons.apps, 'apps', 'apps');
58
+ const newInstBtn = onNewInstance ? makeBtn(icons.plus, 'instance', 'add') : null;
59
+
60
+ const instSwitch = document.createElement('div');
61
+ instSwitch.className = 'os-instances';
62
+ instSwitch.style.cssText = 'display:flex;gap:6px;margin-left:8px';
63
+
64
+ const spacer = document.createElement('div');
65
+ spacer.style.cssText = 'flex:1';
66
+
67
+ const tray = document.createElement('div');
68
+ tray.style.cssText = 'display:flex;align-items:center;gap:6px';
69
+ const clock = document.createElement('span');
70
+ clock.className = 'os-clock';
71
+ tray.appendChild(clock);
72
+
73
+ menubar.append(brandEl, appsBtn);
74
+ if (newInstBtn) menubar.append(newInstBtn);
75
+ menubar.append(instSwitch, spacer, tray);
76
+
77
+ const appsMenu = document.createElement('div');
78
+ appsMenu.className = 'os-menu';
79
+ appsMenu.style.cssText = 'position:absolute;display:none;flex-direction:column;pointer-events:auto';
80
+
81
+ const sideRail = document.createElement('div');
82
+ sideRail.className = 'os-side-rail';
83
+
84
+ const sheet = document.createElement('div');
85
+ sheet.className = 'os-mobile-sheet';
86
+ const sheetHandle = document.createElement('div');
87
+ sheetHandle.className = 'os-mobile-handle';
88
+ const sheetGrid = document.createElement('div');
89
+ sheetGrid.className = 'os-mobile-grid';
90
+ sheet.append(sheetHandle, sheetGrid);
91
+ sheet.addEventListener('click', e => {
92
+ if (e.target === sheet || e.target === sheetHandle) sheet.classList.toggle('open');
93
+ });
94
+
95
+ const apps = typeof registry.list === 'function' ? registry.list() : [...registry.values()];
96
+
97
+ for (const app of apps) {
98
+ const iconSvg = app.icon || icons[app.id] || '';
99
+ const menuBtn = makeBtn(iconSvg, app.name);
100
+ menuBtn.addEventListener('click', () => { appsMenu.style.display = 'none'; openApp(app.id); });
101
+ appsMenu.appendChild(menuBtn);
102
+
103
+ const railBtn = document.createElement('button');
104
+ railBtn.className = 'os-rail-btn';
105
+ railBtn.title = app.name;
106
+ railBtn.append(ic(iconSvg));
107
+ railBtn.addEventListener('click', () => openApp(app.id));
108
+ sideRail.appendChild(railBtn);
109
+
110
+ const tile = document.createElement('button');
111
+ tile.className = 'os-mobile-tile';
112
+ tile.append(ic(iconSvg), Object.assign(document.createElement('span'), { className: 'lbl', textContent: app.name }));
113
+ tile.addEventListener('click', () => { sheet.classList.remove('open'); openApp(app.id); });
114
+ sheetGrid.appendChild(tile);
115
+ }
116
+
117
+ const taskbar = document.createElement('div');
118
+ taskbar.className = 'os-taskbar';
119
+ taskbar.style.cssText = 'margin-top:auto;display:flex;align-items:center;gap:6px;flex-wrap:wrap';
120
+
121
+ osRoot.append(menubar, appsMenu, taskbar);
122
+ document.body.appendChild(sideRail);
123
+ document.body.appendChild(sheet);
124
+
125
+ appsBtn.addEventListener('click', e => {
126
+ e.stopPropagation();
127
+ appsMenu.style.display = appsMenu.style.display === 'flex' ? 'none' : 'flex';
128
+ });
129
+ document.addEventListener('click', e => {
130
+ if (!appsMenu.contains(e.target) && !appsBtn.contains(e.target)) appsMenu.style.display = 'none';
131
+ });
132
+
133
+ function tickClock() { clock.textContent = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); }
134
+ tickClock();
135
+ const clockTimer = setInterval(tickClock, 30000);
136
+
137
+ let activeContext = null;
138
+ function setContext(ctx) { activeContext = ctx; }
139
+
140
+ function refreshTaskbar() {
141
+ taskbar.innerHTML = '';
142
+ for (const w of wm.list()) {
143
+ const t = document.createElement('button');
144
+ t.className = 'os-task' + (w.focused ? ' focused' : '');
145
+ t.textContent = w.title;
146
+ t.addEventListener('click', () => wm.focus(w.id));
147
+ taskbar.appendChild(t);
148
+ }
149
+ }
150
+
151
+ function openApp(appId) {
152
+ const app = (typeof registry.get === 'function') ? registry.get(appId) : registry[appId];
153
+ if (!app) throw new Error('unknown app: ' + appId);
154
+ const ctx = { ...(activeContext || {}), registry, openApp, wm };
155
+ const result = app.factory(ctx);
156
+ const finish = (r) => {
157
+ const sz = app.defaultSize || { w: 520, h: 360 };
158
+ const titlePrefix = (activeContext && activeContext.titlePrefix) ? activeContext.titlePrefix + ' · ' : '';
159
+ const win = wm.open({ title: titlePrefix + app.name, body: r.node, kind: appId, width: sz.w, height: sz.h, x: 100 + (wm.count * 28) % 240, y: 80 + (wm.count * 22) % 180 });
160
+ win._app = { id: appId, dispose: r.dispose };
161
+ refreshTaskbar();
162
+ return win;
163
+ };
164
+ return (result && typeof result.then === 'function') ? result.then(finish) : finish(result);
165
+ }
166
+
167
+ if (newInstBtn) newInstBtn.addEventListener('click', () => onNewInstance && onNewInstance({ instSwitch, setContext, openApp }));
168
+
169
+ const taskTimer = setInterval(refreshTaskbar, 500);
170
+
171
+ const api = {
172
+ wm, registry, openApp, setContext, refreshTaskbar,
173
+ toggleSheet() { sheet.classList.toggle('open'); },
174
+ elements: { osRoot, menubar, taskbar, appsMenu, sideRail, sheet, instSwitch },
175
+ dispose() { clearInterval(clockTimer); clearInterval(taskTimer); osRoot.remove(); sideRail.remove(); sheet.remove(); },
176
+ };
177
+
178
+ if (autoBoot && typeof autoBoot === 'string') openApp(autoBoot);
179
+ return api;
180
+ }
@@ -0,0 +1,297 @@
1
+ :root {
2
+ --os-accent: #3FA93A;
3
+ --os-accent-2: #79e872;
4
+ --os-accent-soft: rgba(63, 169, 58, 0.16);
5
+ --os-bg-0: #0b0d10;
6
+ --os-bg-1: #14181d;
7
+ --os-bg-2: #1a1f26;
8
+ --os-bg-3: #222831;
9
+ --os-fg: #e7ecf2;
10
+ --os-fg-2: #93a0ad;
11
+ --os-fg-3: #5a6571;
12
+ --os-red: #d04444;
13
+ --os-amber: #c0a02f;
14
+ --os-green: #3FA93A;
15
+ --os-radius: 6px;
16
+ --os-radius-sm: 4px;
17
+ --os-bar-h: 40px;
18
+ --os-bar-h-mobile: 48px;
19
+ --os-rail-w: 64px;
20
+ --os-tap: 44px;
21
+ --os-font: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
22
+ --os-mono: "SF Mono", ui-monospace, "JetBrains Mono", Menlo, Consolas, monospace;
23
+ }
24
+
25
+ html, body {
26
+ background: var(--os-bg-0);
27
+ color: var(--os-fg);
28
+ font-family: var(--os-font);
29
+ -webkit-font-smoothing: antialiased;
30
+ text-rendering: optimizeLegibility;
31
+ }
32
+
33
+ .os-menubar, .os-taskbar {
34
+ background: var(--os-bg-1);
35
+ border: none;
36
+ color: var(--os-fg);
37
+ font: 13px var(--os-font);
38
+ height: var(--os-bar-h);
39
+ padding: 0 12px;
40
+ gap: 6px;
41
+ box-shadow: none;
42
+ }
43
+ .os-menubar { border-bottom: 1px solid var(--os-bg-3); }
44
+ .os-taskbar { border-top: 1px solid var(--os-bg-3); }
45
+
46
+ .os-brand {
47
+ color: var(--os-fg);
48
+ font-weight: 600;
49
+ letter-spacing: 0.01em;
50
+ margin-right: 14px;
51
+ display: inline-flex;
52
+ align-items: center;
53
+ gap: 8px;
54
+ }
55
+ .os-brand::before {
56
+ content: '';
57
+ display: inline-block;
58
+ width: 8px; height: 8px;
59
+ border-radius: 50%;
60
+ background: var(--os-accent);
61
+ }
62
+
63
+ .os-btn {
64
+ background: transparent;
65
+ color: var(--os-fg);
66
+ border: none;
67
+ padding: 6px 12px;
68
+ cursor: pointer;
69
+ font: inherit;
70
+ border-radius: var(--os-radius-sm);
71
+ transition: background 100ms ease, color 100ms ease;
72
+ display: inline-flex;
73
+ align-items: center;
74
+ gap: 6px;
75
+ outline: none;
76
+ }
77
+ .os-btn:hover { background: var(--os-bg-2); color: var(--os-accent-2); }
78
+ .os-btn.active, .os-btn[aria-pressed="true"] { background: var(--os-accent-soft); color: var(--os-accent-2); }
79
+ .os-btn:focus-visible { background: var(--os-bg-2); }
80
+ .os-btn .ic { color: var(--os-accent); display: inline-flex; width: 16px; height: 16px; }
81
+ .os-btn .ic svg { width: 16px; height: 16px; display: block; fill: none; stroke: currentColor; }
82
+
83
+ .os-menu {
84
+ background: var(--os-bg-1);
85
+ border: 1px solid var(--os-bg-3);
86
+ border-radius: var(--os-radius);
87
+ box-shadow: none;
88
+ padding: 6px;
89
+ min-width: 220px;
90
+ top: calc(var(--os-bar-h) + 4px);
91
+ left: 8px;
92
+ z-index: 9500;
93
+ }
94
+ .os-menu .os-btn {
95
+ width: 100%;
96
+ text-align: left;
97
+ border-radius: var(--os-radius-sm);
98
+ padding: 8px 10px;
99
+ color: var(--os-fg);
100
+ justify-content: flex-start;
101
+ }
102
+ .os-menu .os-btn:hover { background: var(--os-bg-2); color: var(--os-accent-2); }
103
+
104
+ .os-clock {
105
+ color: var(--os-fg-2);
106
+ font-variant-numeric: tabular-nums;
107
+ padding: 0 10px;
108
+ font-size: 12px;
109
+ }
110
+
111
+ .os-task {
112
+ border: none;
113
+ background: var(--os-bg-2);
114
+ color: var(--os-fg);
115
+ border-radius: var(--os-radius-sm);
116
+ padding: 6px 10px;
117
+ font-size: 12px;
118
+ transition: background 100ms ease, color 100ms ease;
119
+ max-width: 200px;
120
+ cursor: pointer;
121
+ outline: none;
122
+ }
123
+ .os-task:hover { background: var(--os-bg-3); }
124
+ .os-task.focused {
125
+ background: var(--os-accent-soft);
126
+ color: var(--os-accent-2);
127
+ }
128
+
129
+ .wm-win {
130
+ background: var(--os-bg-1) !important;
131
+ border: 1px solid var(--os-bg-3) !important;
132
+ border-radius: var(--os-radius) !important;
133
+ box-shadow: none !important;
134
+ overflow: hidden;
135
+ }
136
+ .wm-win.wm-focused {
137
+ border-color: var(--os-accent) !important;
138
+ box-shadow: none !important;
139
+ }
140
+
141
+ .wm-bar {
142
+ background: var(--os-bg-2) !important;
143
+ border-bottom: 1px solid var(--os-bg-3) !important;
144
+ padding: 8px 12px !important;
145
+ gap: 10px !important;
146
+ }
147
+ .wm-title {
148
+ font: 12px var(--os-font) !important;
149
+ color: var(--os-fg-2) !important;
150
+ letter-spacing: 0.02em;
151
+ text-align: center;
152
+ }
153
+ .wm-btns { gap: 6px !important; order: -1; }
154
+ .wm-btn {
155
+ width: 12px !important;
156
+ height: 12px !important;
157
+ border-radius: 50% !important;
158
+ border: none !important;
159
+ padding: 0 !important;
160
+ cursor: pointer;
161
+ font-size: 0 !important;
162
+ transition: opacity 100ms ease;
163
+ }
164
+ .wm-btn:hover { opacity: 0.75; }
165
+ .wm-btns .wm-btn:nth-child(1) { background: var(--os-amber) !important; }
166
+ .wm-btns .wm-btn:nth-child(2) { background: var(--os-green) !important; }
167
+ .wm-btns .wm-btn:nth-child(3) { background: var(--os-red) !important; }
168
+
169
+ .wm-resize {
170
+ background: var(--os-bg-3) !important;
171
+ width: 14px !important;
172
+ height: 14px !important;
173
+ clip-path: polygon(100% 0, 100% 100%, 0 100%);
174
+ }
175
+ .wm-body { background: var(--os-bg-1) !important; }
176
+
177
+ .os-side-rail {
178
+ position: fixed;
179
+ left: 0; top: 0; bottom: 0;
180
+ width: var(--os-rail-w);
181
+ background: var(--os-bg-1);
182
+ border-right: 1px solid var(--os-bg-3);
183
+ display: none;
184
+ flex-direction: column;
185
+ align-items: center;
186
+ padding: 12px 0;
187
+ gap: 6px;
188
+ z-index: 9100;
189
+ pointer-events: auto;
190
+ }
191
+ .os-rail-btn {
192
+ width: 48px; height: 48px;
193
+ border-radius: var(--os-radius-sm);
194
+ background: transparent;
195
+ border: none;
196
+ color: var(--os-fg);
197
+ cursor: pointer;
198
+ display: flex; align-items: center; justify-content: center;
199
+ transition: background 100ms ease;
200
+ padding: 0;
201
+ outline: none;
202
+ }
203
+ .os-rail-btn:hover { background: var(--os-bg-2); }
204
+ .os-rail-btn:active { background: var(--os-bg-3); }
205
+ .os-rail-btn .ic { color: var(--os-accent); display: inline-flex; }
206
+ .os-rail-btn .ic svg { width: 22px; height: 22px; fill: none; stroke: currentColor; }
207
+
208
+ .os-mobile-sheet {
209
+ position: fixed;
210
+ left: 0; right: 0; bottom: 0;
211
+ background: var(--os-bg-1);
212
+ border-top: 1px solid var(--os-bg-3);
213
+ border-radius: 14px 14px 0 0;
214
+ padding: 8px 12px env(safe-area-inset-bottom, 12px);
215
+ transform: translateY(calc(100% - 56px));
216
+ transition: transform 220ms cubic-bezier(0.22, 0.8, 0.34, 1.0);
217
+ z-index: 9700;
218
+ pointer-events: auto;
219
+ display: none;
220
+ flex-direction: column;
221
+ gap: 8px;
222
+ max-height: 70vh;
223
+ box-shadow: none;
224
+ }
225
+ .os-mobile-sheet.open { transform: translateY(0); }
226
+ .os-mobile-handle {
227
+ width: 44px; height: 4px;
228
+ border-radius: 999px;
229
+ background: var(--os-bg-3);
230
+ margin: 6px auto 4px;
231
+ }
232
+ .os-mobile-grid {
233
+ display: grid;
234
+ grid-template-columns: repeat(4, 1fr);
235
+ gap: 8px;
236
+ overflow-y: auto;
237
+ padding: 6px 4px 12px;
238
+ }
239
+ .os-mobile-tile {
240
+ display: flex; flex-direction: column; align-items: center; gap: 6px;
241
+ padding: 12px 6px;
242
+ border-radius: var(--os-radius);
243
+ background: var(--os-bg-2);
244
+ border: none;
245
+ color: var(--os-fg);
246
+ font: 11px var(--os-font);
247
+ min-height: var(--os-tap);
248
+ cursor: pointer;
249
+ transition: background 100ms ease;
250
+ outline: none;
251
+ }
252
+ .os-mobile-tile:active { background: var(--os-accent-soft); }
253
+ .os-mobile-tile .ic { color: var(--os-accent); display: inline-flex; width: 28px; height: 28px; }
254
+ .os-mobile-tile .ic svg { width: 28px; height: 28px; fill: none; stroke: currentColor; }
255
+ .os-mobile-tile .lbl { color: var(--os-fg-2); }
256
+
257
+ .app-pane { padding: 14px; font: 13px var(--os-font); color: var(--os-fg); line-height: 1.55; overflow: auto; height: 100%; box-sizing: border-box; }
258
+ .app-pane h2 { margin: 0 0 10px 0; color: var(--os-fg); font-size: 16px; font-weight: 600; }
259
+ .app-pane p { margin: 0 0 10px 0; color: var(--os-fg-2); }
260
+ .app-pane ul { padding-left: 18px; margin: 6px 0 12px; color: var(--os-fg-2); }
261
+ .app-pane li { padding: 2px 0; }
262
+ .app-pane code { font: 12px var(--os-mono); background: var(--os-bg-2); padding: 1px 5px; border-radius: 3px; color: var(--os-fg); }
263
+ .app-pane a { color: var(--os-accent); text-decoration: none; }
264
+ .app-pane a:hover { color: var(--os-accent-2); }
265
+ .app-pane .meta { color: var(--os-fg-3); font-size: 12px; }
266
+ .app-pane.mono { font: 12px var(--os-mono); padding: 10px; }
267
+ .app-pane.mono .row { padding: 4px 6px; cursor: pointer; border-radius: 3px; }
268
+ .app-pane.mono .row:hover { background: var(--os-bg-2); }
269
+ .app-pane.mono .head { color: var(--os-accent); margin-bottom: 8px; padding-bottom: 4px; border-bottom: 1px solid var(--os-bg-3); font-weight: 600; }
270
+ .app-pane.mono pre { background: var(--os-bg-2); padding: 8px; margin: 8px 0 0 0; max-height: 200px; overflow: auto; white-space: pre-wrap; font: 11px var(--os-mono); border-radius: 3px; color: var(--os-fg); border: none; }
271
+ .app-canvas { width: 100%; height: 100%; background: var(--os-bg-0); }
272
+ .app-frame { width: 100%; height: 100%; border: 0; background: var(--os-bg-0); }
273
+ @media (max-width: 1023px) and (min-width: 768px) {
274
+ .os-side-rail { display: flex; }
275
+ .wm-root { left: var(--os-rail-w) !important; }
276
+ .os-menubar { padding-left: calc(var(--os-rail-w) + 8px); }
277
+ .os-taskbar { padding-left: calc(var(--os-rail-w) + 8px); }
278
+ .os-menubar .os-instances { display: flex; }
279
+ .os-menu { left: calc(var(--os-rail-w) + 8px); }
280
+ }
281
+
282
+ @media (max-width: 767px) {
283
+ :root { --os-bar-h: var(--os-bar-h-mobile); }
284
+ .os-mobile-sheet { display: flex; }
285
+ .os-menubar { font-size: 14px; padding: 0 8px; }
286
+ .os-menubar .os-btn { min-height: var(--os-tap); padding: 8px 10px; }
287
+ .os-menubar [data-role="apps"] { display: none; }
288
+ .os-menubar [data-role="add"] { min-width: var(--os-tap); }
289
+ .os-menubar .os-instances { gap: 4px; }
290
+ .os-clock { display: none; }
291
+ .os-taskbar { padding: 4px 8px 64px; gap: 4px; overflow-x: auto; flex-wrap: nowrap; }
292
+ .os-task { flex: 0 0 auto; min-height: 36px; max-width: 140px; padding: 8px 10px; }
293
+ .wm-win { border-radius: 0 !important; }
294
+ .wm-bar { padding: 10px 12px !important; }
295
+ .wm-btn { width: 16px !important; height: 16px !important; }
296
+ .os-menu { left: 8px; right: 8px; min-width: 0; }
297
+ }