anentrypoint-design 0.0.237 → 0.0.239

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.
@@ -132,6 +132,11 @@ html, body {
132
132
  flex-direction: column;
133
133
  gap: 2px;
134
134
  pointer-events: auto;
135
+ /* Long app registries must scroll, not extend past the viewport. */
136
+ max-height: calc(100vh - var(--os-bar-h) - 16px);
137
+ max-height: calc(100dvh - var(--os-bar-h) - env(safe-area-inset-top, 0px) - 16px);
138
+ overflow-y: auto;
139
+ overscroll-behavior: contain;
135
140
  }
136
141
  .os-menu.open { display: flex; }
137
142
  .os-menu .os-btn {
@@ -181,7 +186,10 @@ html, body {
181
186
  text-overflow: ellipsis;
182
187
  text-transform: lowercase;
183
188
  }
189
+ .os-task { min-height: 28px; }
184
190
  .os-task:hover { background: var(--panel-hover, var(--os-bg-2)); color: var(--os-fg); }
191
+ /* Empty taskbar reads as an intentional strip, not a stray blurred bar. */
192
+ .os-task-empty { font-size: 11px; color: var(--os-fg-3); padding: 0 10px; font-family: var(--os-font); }
185
193
  .os-task.focused {
186
194
  background: var(--panel-select, var(--os-accent-soft));
187
195
  color: var(--os-fg);
@@ -258,7 +266,8 @@ html, body {
258
266
  .os-side-rail {
259
267
  position: fixed;
260
268
  left: 0; top: var(--os-bar-h); bottom: var(--os-bar-h);
261
- width: var(--os-rail-w);
269
+ padding-left: env(safe-area-inset-left, 0px);
270
+ width: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px));
262
271
  background: var(--os-bg-2);
263
272
  border: none;
264
273
  display: none;
@@ -323,12 +332,16 @@ html, body {
323
332
  .os-drawer-close .ic svg { width: 22px; height: 22px; fill: none; stroke: currentColor; }
324
333
  .os-drawer-grid {
325
334
  display: grid;
326
- grid-template-columns: repeat(3, 1fr);
335
+ grid-template-columns: repeat(auto-fill, minmax(clamp(92px, 24vw, 140px), 1fr));
327
336
  gap: var(--space-3, 16px);
328
337
  padding: var(--space-3, 16px);
329
338
  overflow-y: auto;
330
339
  flex: 1;
331
340
  align-content: start;
341
+ max-width: 720px;
342
+ margin: 0 auto;
343
+ width: 100%;
344
+ box-sizing: border-box;
332
345
  }
333
346
  .os-drawer-tile {
334
347
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-2, 8px);
@@ -352,7 +365,7 @@ html, body {
352
365
 
353
366
  .os-spacer { flex: 1 1 auto; }
354
367
  .os-tray { display: flex; align-items: center; gap: 6px; }
355
- .os-instances { display: flex; gap: 4px; margin-left: 8px; max-width: 280px; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; padding: 0 4px; }
368
+ .os-instances { display: flex; gap: 4px; margin-left: 8px; flex: 0 1 40vw; max-width: 40vw; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; padding: 0 4px; -webkit-mask-image: linear-gradient(to right, transparent, black 12px, black calc(100% - 12px), transparent); mask-image: linear-gradient(to right, transparent, black 12px, black calc(100% - 12px), transparent); }
356
369
  .os-instances::-webkit-scrollbar { height: 4px; }
357
370
  .os-instances .os-btn { flex: 0 0 auto; min-width: 36px; padding: 2px 8px; font-family: var(--os-mono); font-size: 11px; }
358
371
  .os-instances .os-btn.active { background: var(--panel-select, var(--os-accent-soft)); color: var(--os-fg); border-color: var(--panel-accent, var(--os-accent)); box-shadow: inset 0 0 0 1px var(--panel-accent, var(--os-accent)); }
@@ -392,11 +405,11 @@ html, body {
392
405
  }
393
406
  @media (max-width: 1023px) and (min-width: 768px) {
394
407
  .os-side-rail { display: flex; }
395
- .wm-root { left: var(--os-rail-w) !important; }
396
- .os-menubar { padding-left: calc(var(--os-rail-w) + var(--space-2, 8px)); }
397
- .os-taskbar { padding-left: calc(var(--os-rail-w) + var(--space-2, 8px)); }
408
+ .wm-root { left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px)) !important; }
409
+ .os-menubar { padding-left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px) + var(--space-2, 8px)); }
410
+ .os-taskbar { padding-left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px) + var(--space-2, 8px)); }
398
411
  .os-menubar .os-instances { display: flex; }
399
- .os-menu { left: calc(var(--os-rail-w) + var(--space-2, 8px)); }
412
+ .os-menu { left: calc(var(--os-rail-w) + env(safe-area-inset-left, 0px) + var(--space-2, 8px)); }
400
413
  }
401
414
 
402
415
  @media (max-width: 767px) {
@@ -404,14 +417,14 @@ html, body {
404
417
  body { overscroll-behavior: none; }
405
418
  .os-menubar [data-role="home"] { display: inline-flex; min-width: var(--os-tap); min-height: var(--os-tap); padding: 0 12px; }
406
419
  .os-menubar [data-role="home"] .ic svg { width: 22px; height: 22px; }
407
- .os-menubar { font-size: 14px; padding: 0 8px; padding-top: env(safe-area-inset-top, 0); height: calc(var(--os-bar-h) + env(safe-area-inset-top, 0)); }
420
+ .os-menubar { font-size: 14px; padding: env(safe-area-inset-top, 0) max(8px, env(safe-area-inset-right, 0px)) 0 max(8px, env(safe-area-inset-left, 0px)); height: calc(var(--os-bar-h) + env(safe-area-inset-top, 0)); }
408
421
  .os-menubar [data-role="apps"] { display: none; }
409
422
  .os-menubar .os-brand { font-size: 13px; margin-right: 6px; }
410
423
  .os-menubar [data-role="add"] { display: none; }
411
424
  .os-menubar .os-instances { display: none; }
412
425
  .os-clock { display: none; }
413
426
  .os-taskbar {
414
- padding: 6px 8px calc(6px + env(safe-area-inset-bottom, 0));
427
+ padding: 6px max(8px, env(safe-area-inset-right, 0px)) calc(6px + env(safe-area-inset-bottom, 0)) max(8px, env(safe-area-inset-left, 0px));
415
428
  gap: 6px;
416
429
  overflow-x: auto;
417
430
  overflow-y: hidden;
@@ -515,6 +528,19 @@ html, body {
515
528
  /* Bars overlay windows: .wm-root fills full viewport, menubar/taskbar paint on top.
516
529
  * Tilde key hides them via .bars-hidden on <html>. */
517
530
  .ds-247420 .wm-root { top: 0 !important; bottom: 0 !important; inset: 0 !important; }
531
+ /* With bars overlaying the wm-root, a maximized window's 34px titlebar would
532
+ * sit exactly under the 34px menubar (untappable) and its body under the
533
+ * taskbar; keep maximized windows between the bars on desktop/tablet. The
534
+ * mobile band re-asserts its own contract in the responsive layer below. */
535
+ @media (min-width: 768px) {
536
+ .ds-247420 .wm-win.wm-max {
537
+ top: var(--os-bar-h) !important;
538
+ height: calc(100% - (var(--os-bar-h) * 2)) !important;
539
+ }
540
+ }
541
+ /* Instance filtering hides off-instance windows via class, not inline style. */
542
+ .ds-247420 .wm-win.wm-inst-hidden,
543
+ .wm-win.wm-inst-hidden { display: none !important; }
518
544
  html.bars-hidden .os-menubar,
519
545
  html.bars-hidden .os-taskbar { display: none !important; }
520
546
  .ds-247420 .os-task { border-radius: var(--r-pill, 999px); }
@@ -813,7 +839,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
813
839
  .ds-247420 .cc-toggle { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: .4em; padding: .35em .7em; color: var(--fg, inherit); opacity: .75; }
814
840
  .ds-247420 .cc-toggle:hover { opacity: 1; }
815
841
  .ds-247420 .cc-toggle.cc-open { opacity: 1; font-weight: 600; }
816
- .ds-247420 .cc-body { padding: .5em .7em .7em; display: flex; flex-direction: column; gap: .5em; max-height: 42vh; overflow: auto; }
842
+ .ds-247420 .cc-body { padding: .5em .7em .7em; display: flex; flex-direction: column; gap: .5em; max-height: 42vh; max-height: 42dvh; overflow: auto; }
817
843
  .ds-247420 .cc-body[hidden] { display: none; }
818
844
  .ds-247420 .cc-row { display: flex; gap: .6em; flex-wrap: wrap; }
819
845
  .ds-247420 .cc-row > .cc-field { flex: 1 1 140px; min-width: 0; }
@@ -1482,7 +1508,7 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
1482
1508
  padding: max(12px, env(safe-area-inset-top, 0px)) max(12px, env(safe-area-inset-right, 0px))
1483
1509
  max(12px, env(safe-area-inset-bottom, 0px)) max(12px, env(safe-area-inset-left, 0px));
1484
1510
  }
1485
- .ds-247420 .tb-sess-modal { max-height: calc(100svh - 24px); display: flex; flex-direction: column; }
1511
+ .ds-247420 .tb-sess-modal { max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); display: flex; flex-direction: column; }
1486
1512
  .ds-247420 .tb-sess-modal-body { overflow-y: auto; min-height: 0; }
1487
1513
 
1488
1514
  /* --- browser-pane: the generic .app-pane 16px prose padding stranded the
@@ -15,6 +15,10 @@
15
15
  position: absolute;
16
16
  min-width: 200px;
17
17
  min-height: 120px;
18
+ /* Never exceed the .wm-root desktop area — a window sized on a large
19
+ monitor must stay recoverable when the viewport shrinks. */
20
+ max-width: 100%;
21
+ max-height: 100%;
18
22
  background: var(--os-bg-1);
19
23
  color: var(--os-fg);
20
24
  border: none;
@@ -35,6 +39,8 @@
35
39
  .wm-bar {
36
40
  display: flex;
37
41
  align-items: center;
42
+ min-height: 36px;
43
+ box-sizing: border-box;
38
44
  padding: 8px 12px;
39
45
  background: var(--os-bg-2);
40
46
  cursor: move;
@@ -70,6 +76,7 @@
70
76
  justify-content: center;
71
77
  border-radius: var(--os-radius-sm, var(--r-1, 6px));
72
78
  transition: background 100ms ease, color 100ms ease;
79
+ touch-action: manipulation;
73
80
  }
74
81
  .wm-btn:hover { background: var(--panel-hover, var(--os-bg-1)); color: var(--os-fg); }
75
82
 
@@ -135,7 +142,19 @@
135
142
  border-radius: 0;
136
143
  }
137
144
 
138
- @media (max-width: 767px) {
145
+ /* Touch: lift resize hit-zones and window buttons toward the 44px floor
146
+ (wm.css must be self-sufficient; theme.css only covers .ds-247420). */
147
+ @media (pointer: coarse) {
148
+ .wm-edge[data-dir='n'], .wm-edge[data-dir='s'] { height: 20px; }
149
+ .wm-edge[data-dir='e'], .wm-edge[data-dir='w'] { width: 20px; }
150
+ .wm-edge[data-dir='ne'], .wm-edge[data-dir='nw'], .wm-edge[data-dir='sw'] { width: 32px; height: 32px; }
151
+ .wm-resize { width: 32px; height: 32px; }
152
+ .wm-btn { min-width: 44px; min-height: 44px; }
153
+ }
154
+
155
+ /* Full-screen windows on phones AND short landscape phones — a width-only
156
+ query misses 812x375 landscape, which cannot host floating chrome. */
157
+ @media (max-width: 767px), ((max-height: 500px) and (orientation: landscape) and (pointer: coarse)) {
139
158
  .wm-win {
140
159
  left: 0 !important;
141
160
  top: 0 !important;
@@ -145,4 +164,5 @@
145
164
  border: none;
146
165
  }
147
166
  .wm-resize { display: none; }
167
+ .wm-edge { display: none; }
148
168
  }
package/src/kits/os/wm.js CHANGED
@@ -20,14 +20,34 @@ export function renderWindow(opts = {}) {
20
20
  callbacks = {},
21
21
  } = opts;
22
22
 
23
+ // Keep at least MIN px of the window horizontally inside the container and
24
+ // the titlebar (BAR px) vertically reachable, so a window can always be
25
+ // grabbed by pointer (persisted bounds from a larger viewport included).
26
+ const MIN_VISIBLE = 60;
27
+ const BAR_H = 36;
28
+ function clampBounds(b, p) {
29
+ const pw = p ? p.clientWidth : window.innerWidth;
30
+ const ph = p ? p.clientHeight : window.innerHeight;
31
+ const out = { ...b };
32
+ if (typeof out.w === 'number') out.w = Math.min(out.w, pw);
33
+ if (typeof out.h === 'number') out.h = Math.min(out.h, ph);
34
+ if (typeof out.x === 'number') {
35
+ const w = typeof out.w === 'number' ? out.w : MIN_VISIBLE;
36
+ out.x = Math.max(MIN_VISIBLE - w, Math.min(out.x, pw - MIN_VISIBLE));
37
+ }
38
+ if (typeof out.y === 'number') out.y = Math.max(0, Math.min(out.y, ph - BAR_H));
39
+ return out;
40
+ }
41
+
23
42
  const el = document.createElement('div');
24
43
  el.className = 'wm-win';
25
44
  el.dataset.kind = kind;
26
45
  if (instanceId) el.dataset.instanceId = instanceId;
27
- el.style.left = bounds.x + 'px';
28
- el.style.top = bounds.y + 'px';
29
- el.style.width = bounds.w + 'px';
30
- el.style.height = bounds.h + 'px';
46
+ const b0 = clampBounds(bounds, null);
47
+ el.style.left = b0.x + 'px';
48
+ el.style.top = b0.y + 'px';
49
+ el.style.width = b0.w + 'px';
50
+ el.style.height = b0.h + 'px';
31
51
 
32
52
  const bar = document.createElement('div');
33
53
  bar.className = 'wm-bar';
@@ -90,10 +110,14 @@ export function renderWindow(opts = {}) {
90
110
  setTitle(t) { titleEl.textContent = t; },
91
111
  setBody(b) { setBodyContent(bodyEl, b); },
92
112
  setBounds(b) {
93
- if (typeof b.x === 'number') el.style.left = b.x + 'px';
94
- if (typeof b.y === 'number') el.style.top = b.y + 'px';
95
- if (typeof b.w === 'number') el.style.width = b.w + 'px';
96
- if (typeof b.h === 'number') el.style.height = b.h + 'px';
113
+ const c = clampBounds({
114
+ ...b,
115
+ w: typeof b.w === 'number' ? b.w : el.offsetWidth,
116
+ }, el.offsetParent);
117
+ if (typeof c.x === 'number') el.style.left = c.x + 'px';
118
+ if (typeof c.y === 'number') el.style.top = c.y + 'px';
119
+ if (typeof b.w === 'number') el.style.width = c.w + 'px';
120
+ if (typeof b.h === 'number') el.style.height = c.h + 'px';
97
121
  },
98
122
  setFocused(v) { applyFocused(el, v); },
99
123
  setMaximized(v) { applyMaximized(el, v); },
@@ -12,8 +12,9 @@
12
12
  }
13
13
  .sp-hud-ammo {
14
14
  position: fixed;
15
- bottom: 50px;
16
- right: 20px;
15
+ /* Fixed chrome clears notch/home-indicator on cutout devices. */
16
+ bottom: calc(50px + env(safe-area-inset-bottom, 0px));
17
+ right: calc(20px + env(safe-area-inset-right, 0px));
17
18
  font-size: 24px;
18
19
  font-weight: bold;
19
20
  color: var(--fg);
@@ -22,7 +23,7 @@
22
23
  .sp-hud-ammo-reloading { color: var(--warn); }
23
24
  .sp-hud-health {
24
25
  position: fixed;
25
- bottom: 20px;
26
+ bottom: calc(20px + env(safe-area-inset-bottom, 0px));
26
27
  left: 50%;
27
28
  transform: translateX(-50%);
28
29
  width: 200px;
@@ -49,7 +50,7 @@
49
50
  .sp-hud-boost {
50
51
  position: fixed;
51
52
  top: 80px;
52
- right: 20px;
53
+ right: calc(20px + env(safe-area-inset-right, 0px));
53
54
  padding: 8px 16px;
54
55
  background: var(--accent);
55
56
  color: var(--accent-fg);
@@ -21,6 +21,11 @@
21
21
  border: 1px solid var(--bw-rule, var(--rule));
22
22
  border-radius: var(--r-2, 10px);
23
23
  color: var(--fg);
24
+ /* Short landscape phones: keep lower controls reachable inside the card. */
25
+ max-height: calc(100vh - 32px);
26
+ max-height: calc(100dvh - 32px);
27
+ overflow-y: auto;
28
+ overscroll-behavior: contain;
24
29
  }
25
30
  .sp-lobby-title {
26
31
  margin: 0;