Rewild Your Web
web
browser
dweb
1/* SPDX-License-Identifier: AGPL-3.0-or-later */
2
3/* Hide desktop-only elements */
4body.mobile-mode #sidebar {
5 display: none;
6}
7
8body.mobile-mode #header {
9 display: none;
10}
11
12/* Root becomes full-screen container for carousel */
13body.mobile-mode #root {
14 flex: 1;
15 display: block;
16 overflow: hidden;
17 position: relative;
18}
19
20/* Each webview container is full-screen, stacked */
21body.mobile-mode .mobile-webview-container {
22 position: absolute;
23 top: 0;
24 left: 0;
25 right: 0;
26 bottom: var(--keyboard-offset);
27 opacity: 0;
28 visibility: hidden;
29 transition:
30 opacity 0.3s ease,
31 visibility 0.3s ease,
32 bottom 0.3s ease;
33 z-index: var(--z-base);
34}
35
36body.mobile-mode .mobile-webview-container.active {
37 opacity: 1;
38 visibility: visible;
39 z-index: var(--z-base-active);
40}
41
42/* WebView fills container completely */
43body.mobile-mode .mobile-webview-container web-view {
44 width: 100%;
45 height: 100%;
46}
47
48/* Override WebView to hide title bar on mobile */
49body.mobile-mode web-view::part(bar) {
50 display: none;
51}
52
53/* Footer (keyboard) adjustments for mobile */
54body.mobile-mode #footer {
55 position: fixed;
56 bottom: 0;
57 left: 0;
58 right: 0;
59 z-index: var(--z-chrome);
60}
61
62/* Mobile action bar adjustments when keyboard is open */
63body.mobile-mode mobile-action-bar {
64 transition: bottom var(--transition-fast) ease;
65}
66
67body.mobile-mode.keyboard-open mobile-action-bar {
68 bottom: var(--keyboard-height);
69}
70
71/* ============================================================================
72 Peek Preview Styles
73 ============================================================================ */
74
75.mobile-peek-preview {
76 position: fixed;
77 top: 0;
78 width: 100%;
79 height: 100%;
80 background: var(--bg-menu);
81 z-index: var(--z-gesture);
82 display: flex;
83 flex-direction: column;
84 box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
85 opacity: 0;
86 visibility: hidden;
87}
88
89.mobile-peek-preview.visible {
90 opacity: 1;
91 visibility: visible;
92}
93
94/* Animate transform on release (commit or cancel) */
95.mobile-peek-preview.animating {
96 transition: transform var(--transition-fast);
97}
98
99.mobile-peek-preview.from-left {
100 left: 0;
101 transform: translateX(-100%);
102}
103
104.mobile-peek-preview.from-right {
105 right: 0;
106 left: auto;
107 transform: translateX(100%);
108}
109
110.peek-header {
111 display: flex;
112 align-items: center;
113 gap: var(--spacing-sm);
114 padding: var(--spacing-md);
115 background: var(--bg-header);
116}
117
118.peek-favicon {
119 width: 20px;
120 height: 20px;
121 object-fit: contain;
122 border-radius: 4px;
123}
124
125.peek-favicon[src=""] {
126 display: none;
127}
128
129.peek-title {
130 flex: 1;
131 font-size: 14px;
132 font-weight: 600;
133 color: var(--color-text-menu);
134 white-space: nowrap;
135 overflow: hidden;
136 text-overflow: ellipsis;
137}
138
139.peek-screenshot {
140 flex: 1;
141 width: 100%;
142 object-fit: cover;
143 object-position: top;
144}
145
146/* ============================================================================
147 Tab Count Indicator (shown during edge swipe)
148 ============================================================================ */
149
150.mobile-tab-indicator {
151 position: fixed;
152 bottom: 60px;
153 left: 50%;
154 transform: translateX(-50%);
155 display: flex;
156 gap: 6px;
157 padding: 8px 12px;
158 background: rgba(0, 0, 0, 0.6);
159 border-radius: 16px;
160 z-index: var(--z-gesture);
161 opacity: 0;
162 visibility: hidden;
163 transition:
164 opacity 0.2s ease,
165 visibility 0.2s ease;
166}
167
168.mobile-tab-indicator.visible {
169 opacity: 1;
170 visibility: visible;
171}
172
173.tab-dot {
174 width: 8px;
175 height: 8px;
176 border-radius: 50%;
177 background: rgba(255, 255, 255, 0.3);
178 transition:
179 background 0.2s ease,
180 transform 0.2s ease;
181}
182
183.tab-dot.active {
184 background: var(--color-focus-ring);
185 transform: scale(1.2);
186}
187
188/* ============================================================================
189 Transition Animations
190 ============================================================================ */
191
192/* Slide transition between webviews */
193@keyframes slideInFromLeft {
194 from {
195 transform: translateX(-100%);
196 }
197 to {
198 transform: translateX(0);
199 }
200}
201
202@keyframes slideInFromRight {
203 from {
204 transform: translateX(100%);
205 }
206 to {
207 transform: translateX(0);
208 }
209}
210
211@keyframes slideOutToLeft {
212 from {
213 transform: translateX(0);
214 }
215 to {
216 transform: translateX(-100%);
217 }
218}
219
220@keyframes slideOutToRight {
221 from {
222 transform: translateX(0);
223 }
224 to {
225 transform: translateX(100%);
226 }
227}
228
229body.mobile-mode .mobile-webview-container.slide-in-left {
230 animation: slideInFromLeft 0.3s ease forwards;
231}
232
233body.mobile-mode .mobile-webview-container.slide-in-right {
234 animation: slideInFromRight 0.3s ease forwards;
235}
236
237body.mobile-mode .mobile-webview-container.slide-out-left {
238 animation: slideOutToLeft 0.3s ease forwards;
239}
240
241body.mobile-mode .mobile-webview-container.slide-out-right {
242 animation: slideOutToRight 0.3s ease forwards;
243}
244
245/* ============================================================================
246 Edge Zone Visual Feedback (subtle)
247 ============================================================================ */
248
249.edge-feedback {
250 position: fixed;
251 z-index: var(--z-gesture);
252 pointer-events: none;
253 opacity: 0;
254 transition: opacity 0.15s ease;
255}
256
257.edge-feedback.active {
258 opacity: 1;
259}
260
261.edge-feedback.left {
262 left: 0;
263 top: 0;
264 width: 4px;
265 height: 100%;
266 background: linear-gradient(to right, var(--color-focus-ring), transparent);
267}
268
269.edge-feedback.right {
270 right: 0;
271 top: 0;
272 width: 4px;
273 height: 100%;
274 background: linear-gradient(to left, var(--color-focus-ring), transparent);
275}
276
277.edge-feedback.bottom {
278 bottom: 0;
279 left: 0;
280 width: 100%;
281 height: 4px;
282 background: linear-gradient(to top, var(--color-focus-ring), transparent);
283}
284
285.edge-feedback.top {
286 top: 0;
287 left: 0;
288 width: 100%;
289 height: 4px;
290 background: linear-gradient(to bottom, var(--color-focus-ring), transparent);
291}
292
293.gesture-edge-overlay {
294 position: fixed;
295 z-index: calc(var(--z-gesture) + 1);
296 touch-action: none;
297 pointer-events: auto;
298 background: transparent;
299 /* rgba(77, 215, 220, 0.49); */
300}
301
302/* Expand edge overlay to full screen during active gesture,
303 above the peek preview so we keep receiving touch events */
304.gesture-edge-overlay.fullscreen-overlay {
305 left: 0 !important;
306 top: 0 !important;
307 right: auto !important;
308 bottom: auto !important;
309 width: 100% !important;
310 height: 100% !important;
311}