relmio 0.3.0 → 0.4.0
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/CHANGELOG.md +51 -0
- package/README.md +126 -36
- package/docs/architecture.md +57 -0
- package/docs/images/examples/gpt-56-model-selector.png +0 -0
- package/docs/images/examples/n8n-openai-credential-connected.png +0 -0
- package/docs/images/examples/telegram-model-results.png +0 -0
- package/docs/images/examples/telegram-n8n-workflow-execution.png +0 -0
- package/docs/images/setup/00-install-methods.png +0 -0
- package/docs/images/setup/01-local-sign-in-ready.png +0 -0
- package/docs/images/setup/02-vps-identity-confirmed.png +0 -0
- package/docs/images/setup/03-n8n-detected.png +0 -0
- package/docs/images/setup/04-install-plan.png +0 -0
- package/docs/images/setup/05-bridge-ready.png +0 -0
- package/docs/local-endpoints-spec.md +370 -0
- package/docs/local-endpoints.md +374 -0
- package/docs/npm-publish.md +121 -201
- package/docs/security.md +92 -3
- package/package.json +2 -2
- package/src/domain/local-endpoints.js +460 -0
- package/src/gateway/openai.js +834 -0
- package/src/infrastructure/local-process.js +375 -0
- package/src/services/codex-login.js +711 -0
- package/src/services/local-installer.js +1120 -0
- package/src/ui/app.js +4 -0
- package/src/ui/index.html +119 -108
- package/src/ui/local.css +262 -0
- package/src/ui/local.html +442 -0
- package/src/ui/local.js +550 -0
- package/src/ui/styles.css +577 -278
- package/src/web/server.js +247 -12
package/src/ui/app.js
CHANGED
|
@@ -13,6 +13,10 @@ const state = {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
const element = (id) => document.getElementById(id);
|
|
16
|
+
const localEndpointLink = element("local-endpoint-link");
|
|
17
|
+
if (token) {
|
|
18
|
+
localEndpointLink.href = `/local?session=${encodeURIComponent(token)}`;
|
|
19
|
+
}
|
|
16
20
|
const messageToast = element("global-message");
|
|
17
21
|
const message = element("global-message-text");
|
|
18
22
|
const errorBox = element("global-error");
|
package/src/ui/index.html
CHANGED
|
@@ -55,108 +55,108 @@
|
|
|
55
55
|
</div>
|
|
56
56
|
</header>
|
|
57
57
|
|
|
58
|
-
<
|
|
59
|
-
<aside
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
58
|
+
<main id="main-content" class="shell" tabindex="-1">
|
|
59
|
+
<aside class="rail" aria-label="Setup progress and safety">
|
|
60
|
+
<section class="intro" aria-labelledby="page-title">
|
|
61
|
+
<h1 id="page-title">Connect n8n without changing n8n</h1>
|
|
62
|
+
<p class="lede">
|
|
63
|
+
This wizard installs one separate Docker sidecar. Your existing n8n
|
|
64
|
+
image, Compose file, container, and workflows stay untouched.
|
|
65
|
+
</p>
|
|
66
|
+
</section>
|
|
67
|
+
|
|
68
|
+
<nav class="steps" aria-label="Setup progress">
|
|
69
|
+
<ol>
|
|
70
|
+
<li data-step-marker="1" aria-current="step">
|
|
71
|
+
<span>1</span><em>Sign in</em>
|
|
72
|
+
</li>
|
|
73
|
+
<li data-step-marker="2"><span>2</span><em>VPS</em></li>
|
|
74
|
+
<li data-step-marker="3"><span>3</span><em>n8n</em></li>
|
|
75
|
+
<li data-step-marker="4"><span>4</span><em>Review</em></li>
|
|
76
|
+
<li data-step-marker="5"><span>5</span><em>Done</em></li>
|
|
77
|
+
</ol>
|
|
78
|
+
</nav>
|
|
79
|
+
|
|
80
|
+
<div class="toast-stack" aria-label="Wizard notifications">
|
|
81
|
+
<aside
|
|
82
|
+
id="global-safety"
|
|
83
|
+
class="toast safety-note"
|
|
84
|
+
aria-label="Safety guarantee"
|
|
85
|
+
>
|
|
86
|
+
<strong>Sidecar-only guarantee</strong>
|
|
87
|
+
<span>
|
|
88
|
+
No n8n restart. No n8n rebuild. No public port. You approve the
|
|
89
|
+
exact plan before anything is written.
|
|
90
|
+
</span>
|
|
91
|
+
<button
|
|
92
|
+
class="toast-close"
|
|
93
|
+
type="button"
|
|
94
|
+
data-dismiss-toast="global-safety"
|
|
95
|
+
aria-label="Dismiss safety guarantee"
|
|
96
|
+
>
|
|
97
|
+
<span aria-hidden="true">×</span>
|
|
98
|
+
</button>
|
|
99
|
+
</aside>
|
|
98
100
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
101
|
+
<aside
|
|
102
|
+
id="global-backup"
|
|
103
|
+
class="toast safety-note backup-note"
|
|
104
|
+
aria-label="Backup reminder"
|
|
105
|
+
>
|
|
106
|
+
<strong>Back up first</strong>
|
|
107
|
+
<span>
|
|
108
|
+
Export your n8n workflows before connecting. This wizard uses
|
|
109
|
+
sidecar-only commands, but it still writes to your VPS.
|
|
110
|
+
</span>
|
|
111
|
+
<button
|
|
112
|
+
class="toast-close"
|
|
113
|
+
type="button"
|
|
114
|
+
data-dismiss-toast="global-backup"
|
|
115
|
+
aria-label="Dismiss backup reminder"
|
|
116
|
+
>
|
|
117
|
+
<span aria-hidden="true">×</span>
|
|
118
|
+
</button>
|
|
119
|
+
</aside>
|
|
115
120
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
</div>
|
|
133
|
-
</div>
|
|
134
|
-
|
|
135
|
-
<main id="main-content" class="shell">
|
|
136
|
-
<section class="intro" aria-labelledby="page-title">
|
|
137
|
-
<p class="eyebrow">Guided VPS setup</p>
|
|
138
|
-
<h1 id="page-title">Connect n8n without changing n8n</h1>
|
|
139
|
-
<p class="lede">
|
|
140
|
-
This wizard installs one separate Docker sidecar. Your existing n8n
|
|
141
|
-
image, Compose file, container, and workflows stay untouched.
|
|
142
|
-
</p>
|
|
143
|
-
</section>
|
|
121
|
+
<div
|
|
122
|
+
id="global-message"
|
|
123
|
+
class="toast message"
|
|
124
|
+
role="status"
|
|
125
|
+
aria-live="polite"
|
|
126
|
+
>
|
|
127
|
+
<span id="global-message-text">Checking your local sign-in…</span>
|
|
128
|
+
<button
|
|
129
|
+
class="toast-close"
|
|
130
|
+
type="button"
|
|
131
|
+
data-dismiss-toast="global-message"
|
|
132
|
+
aria-label="Dismiss status message"
|
|
133
|
+
>
|
|
134
|
+
<span aria-hidden="true">×</span>
|
|
135
|
+
</button>
|
|
136
|
+
</div>
|
|
144
137
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
138
|
+
<div
|
|
139
|
+
id="global-error"
|
|
140
|
+
class="toast error"
|
|
141
|
+
role="alert"
|
|
142
|
+
tabindex="-1"
|
|
143
|
+
hidden
|
|
144
|
+
>
|
|
145
|
+
<span id="global-error-text"></span>
|
|
146
|
+
<button
|
|
147
|
+
class="toast-close"
|
|
148
|
+
type="button"
|
|
149
|
+
data-dismiss-toast="global-error"
|
|
150
|
+
aria-label="Dismiss error"
|
|
151
|
+
>
|
|
152
|
+
<span aria-hidden="true">×</span>
|
|
153
|
+
</button>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</aside>
|
|
156
157
|
|
|
157
158
|
<section class="panel" data-step="1" aria-labelledby="signin-title">
|
|
158
159
|
<div class="panel-heading">
|
|
159
|
-
<span class="step-kicker">Step 1 of 5</span>
|
|
160
160
|
<h2 id="signin-title" tabindex="-1">Use your local ChatGPT sign-in</h2>
|
|
161
161
|
<p>
|
|
162
162
|
The OAuth credential stays on this computer until you approve its
|
|
@@ -177,6 +177,19 @@
|
|
|
177
177
|
</div>
|
|
178
178
|
</div>
|
|
179
179
|
|
|
180
|
+
<aside class="final-note" aria-labelledby="local-endpoint-title">
|
|
181
|
+
<h3 id="local-endpoint-title">Need an endpoint on this computer?</h3>
|
|
182
|
+
<p>
|
|
183
|
+
Install a loopback-only OpenAI API endpoint with a Platform key, or
|
|
184
|
+
the experimental official Codex App Server with ChatGPT sign-in.
|
|
185
|
+
</p>
|
|
186
|
+
<div class="actions">
|
|
187
|
+
<a id="local-endpoint-link" class="button secondary">
|
|
188
|
+
Set up a local endpoint
|
|
189
|
+
</a>
|
|
190
|
+
</div>
|
|
191
|
+
</aside>
|
|
192
|
+
|
|
180
193
|
<div class="actions">
|
|
181
194
|
<button id="login-button" class="button secondary" type="button">
|
|
182
195
|
Sign in with ChatGPT
|
|
@@ -198,7 +211,6 @@
|
|
|
198
211
|
|
|
199
212
|
<section class="panel" data-step="2" aria-labelledby="vps-title" hidden>
|
|
200
213
|
<div class="panel-heading">
|
|
201
|
-
<span class="step-kicker">Step 2 of 5</span>
|
|
202
214
|
<h2 id="vps-title" tabindex="-1">Connect to your VPS</h2>
|
|
203
215
|
<p>
|
|
204
216
|
Copy the address exactly from Hostinger. Your password is used only
|
|
@@ -294,7 +306,6 @@
|
|
|
294
306
|
|
|
295
307
|
<section class="panel" data-step="3" aria-labelledby="n8n-title" hidden>
|
|
296
308
|
<div class="panel-heading">
|
|
297
|
-
<span class="step-kicker">Step 3 of 5</span>
|
|
298
309
|
<h2 id="n8n-title" tabindex="-1">Choose the detected n8n</h2>
|
|
299
310
|
<p>
|
|
300
311
|
Discovery uses read-only Docker commands. It does not execute
|
|
@@ -332,7 +343,6 @@
|
|
|
332
343
|
|
|
333
344
|
<section class="panel" data-step="4" aria-labelledby="review-title" hidden>
|
|
334
345
|
<div class="panel-heading">
|
|
335
|
-
<span class="step-kicker">Step 4 of 5</span>
|
|
336
346
|
<h2 id="review-title" tabindex="-1">Review before installing</h2>
|
|
337
347
|
<p>No existing n8n files or containers will be changed.</p>
|
|
338
348
|
</div>
|
|
@@ -381,14 +391,15 @@
|
|
|
381
391
|
</section>
|
|
382
392
|
|
|
383
393
|
<section class="panel success-panel" data-step="5" aria-labelledby="done-title" hidden>
|
|
384
|
-
<div class="success-
|
|
385
|
-
|
|
386
|
-
<
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
394
|
+
<div class="success-heading">
|
|
395
|
+
<div class="success-mark" aria-hidden="true">✓</div>
|
|
396
|
+
<div class="panel-heading">
|
|
397
|
+
<h2 id="done-title" tabindex="-1">The private bridge is ready</h2>
|
|
398
|
+
<p>
|
|
399
|
+
Copy the OpenAI credential values first, then use one of the node
|
|
400
|
+
recipes below.
|
|
401
|
+
</p>
|
|
402
|
+
</div>
|
|
392
403
|
</div>
|
|
393
404
|
|
|
394
405
|
<h3>1. OpenAI credential</h3>
|
|
@@ -435,7 +446,7 @@
|
|
|
435
446
|
|
|
436
447
|
<button
|
|
437
448
|
id="copy-settings"
|
|
438
|
-
class="button
|
|
449
|
+
class="button primary"
|
|
439
450
|
type="button"
|
|
440
451
|
data-copy-group="credential"
|
|
441
452
|
data-copy-label="OpenAI credential settings"
|
package/src/ui/local.css
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
.local-wizard .shell {
|
|
2
|
+
width: min(100% - 2.5rem, 78rem);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.local-wizard .panel {
|
|
6
|
+
scroll-behavior: smooth;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.local-wizard .status-row {
|
|
10
|
+
margin-bottom: 1rem;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.local-wizard .safety-note {
|
|
14
|
+
grid-template-columns: 1.75rem minmax(0, 1fr);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.local-wizard .safety-note > span {
|
|
18
|
+
grid-column: 2;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.target-picker {
|
|
22
|
+
display: grid;
|
|
23
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
24
|
+
gap: 0.75rem;
|
|
25
|
+
min-width: 0;
|
|
26
|
+
margin: 0 0 1rem;
|
|
27
|
+
padding: 0;
|
|
28
|
+
border: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.target-picker legend {
|
|
32
|
+
width: 100%;
|
|
33
|
+
margin-bottom: 0.5rem;
|
|
34
|
+
font-weight: 800;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.target-card {
|
|
38
|
+
position: relative;
|
|
39
|
+
display: grid;
|
|
40
|
+
grid-template-columns: 1.25rem minmax(0, 1fr);
|
|
41
|
+
gap: 0.75rem;
|
|
42
|
+
min-width: 0;
|
|
43
|
+
padding: 1rem;
|
|
44
|
+
border: 1px solid var(--border-strong);
|
|
45
|
+
border-radius: var(--radius);
|
|
46
|
+
background: var(--surface-muted);
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
transition:
|
|
49
|
+
border-color 180ms var(--ease),
|
|
50
|
+
background 180ms var(--ease),
|
|
51
|
+
box-shadow 180ms var(--ease),
|
|
52
|
+
transform 180ms var(--ease);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.target-card:hover {
|
|
56
|
+
border-color: var(--accent);
|
|
57
|
+
transform: translateY(-1px);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.target-card:has(input:checked) {
|
|
61
|
+
border-color: var(--accent);
|
|
62
|
+
background: var(--accent-soft);
|
|
63
|
+
box-shadow: 0 0 0 3px rgb(19 124 116 / 12%);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.target-card:has(input:focus-visible) {
|
|
67
|
+
outline: 3px solid #f2a94a;
|
|
68
|
+
outline-offset: 2px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.target-card input {
|
|
72
|
+
width: 1.125rem;
|
|
73
|
+
height: 1.125rem;
|
|
74
|
+
margin: 0.2rem 0 0;
|
|
75
|
+
accent-color: var(--accent);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.target-card-copy {
|
|
79
|
+
display: grid;
|
|
80
|
+
gap: 0.35rem;
|
|
81
|
+
color: var(--text-muted);
|
|
82
|
+
font-size: 0.875rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.target-card-copy strong {
|
|
86
|
+
color: var(--text);
|
|
87
|
+
font-size: 1rem;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.target-card-copy .target-meta {
|
|
91
|
+
color: var(--accent-deep);
|
|
92
|
+
font-size: 0.75rem;
|
|
93
|
+
font-weight: 800;
|
|
94
|
+
letter-spacing: 0.02em;
|
|
95
|
+
text-transform: uppercase;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.warning-card:has(input:checked) {
|
|
99
|
+
border-color: var(--warning-border);
|
|
100
|
+
background: var(--warning-soft);
|
|
101
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--warning) 13%, transparent);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.warning-card .target-meta {
|
|
105
|
+
color: var(--warning);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.local-fields {
|
|
109
|
+
grid-template-columns: minmax(8rem, 0.55fr) minmax(0, 1.45fr);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.field textarea {
|
|
113
|
+
width: 100%;
|
|
114
|
+
min-height: 5.75rem;
|
|
115
|
+
padding: 0.625rem 0.875rem;
|
|
116
|
+
resize: vertical;
|
|
117
|
+
border: 1px solid var(--border-strong);
|
|
118
|
+
border-radius: var(--radius-sm);
|
|
119
|
+
color: var(--text);
|
|
120
|
+
background: var(--surface);
|
|
121
|
+
font: 0.875rem/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
122
|
+
transition:
|
|
123
|
+
border-color 200ms var(--ease),
|
|
124
|
+
box-shadow 200ms var(--ease);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.field textarea:hover {
|
|
128
|
+
border-color: var(--accent);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.field textarea:focus {
|
|
132
|
+
border-color: var(--accent);
|
|
133
|
+
outline: 0;
|
|
134
|
+
box-shadow: 0 0 0 4px rgb(19 124 116 / 13%);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.policy-note,
|
|
138
|
+
.high-trust-warning,
|
|
139
|
+
.one-time-note,
|
|
140
|
+
.codex-login {
|
|
141
|
+
margin-top: 1rem;
|
|
142
|
+
padding: 0.875rem 1rem;
|
|
143
|
+
border: 1px solid var(--accent-border);
|
|
144
|
+
border-radius: var(--radius);
|
|
145
|
+
background: var(--accent-soft);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.policy-note p,
|
|
149
|
+
.high-trust-warning p,
|
|
150
|
+
.one-time-note p,
|
|
151
|
+
.codex-login p {
|
|
152
|
+
margin: 0.35rem 0 0;
|
|
153
|
+
color: var(--text-muted);
|
|
154
|
+
font-size: 0.875rem;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.high-trust-warning {
|
|
158
|
+
border-color: var(--warning-border);
|
|
159
|
+
background: var(--warning-soft);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.high-trust-warning strong,
|
|
163
|
+
.high-trust-warning p {
|
|
164
|
+
color: var(--warning);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.one-time-note {
|
|
168
|
+
margin: 0 0 1rem;
|
|
169
|
+
border-color: var(--warning-border);
|
|
170
|
+
background: var(--warning-soft);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.one-time-note strong,
|
|
174
|
+
.one-time-note p {
|
|
175
|
+
color: var(--warning);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.local-review-grid {
|
|
179
|
+
margin-top: 1rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.review-details dd {
|
|
183
|
+
overflow-wrap: anywhere;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.review-details div {
|
|
187
|
+
grid-template-columns: 9.5rem minmax(0, 1fr);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.codex-login {
|
|
191
|
+
border-color: var(--warning-border);
|
|
192
|
+
background: var(--warning-soft);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.codex-login h3 {
|
|
196
|
+
margin-bottom: 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.codex-login > .button {
|
|
200
|
+
margin-top: 0.875rem;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.device-code-result {
|
|
204
|
+
margin-top: 1rem;
|
|
205
|
+
padding-top: 1rem;
|
|
206
|
+
border-top: 1px solid var(--warning-border);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.device-code-row {
|
|
210
|
+
display: flex;
|
|
211
|
+
flex-wrap: wrap;
|
|
212
|
+
align-items: center;
|
|
213
|
+
gap: 0.625rem;
|
|
214
|
+
margin: 0.75rem 0;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.device-code-row code {
|
|
218
|
+
padding: 0.65rem 0.875rem;
|
|
219
|
+
border: 1px solid var(--warning-border);
|
|
220
|
+
background: var(--surface);
|
|
221
|
+
font-size: 1.125rem;
|
|
222
|
+
font-weight: 800;
|
|
223
|
+
letter-spacing: 0.08em;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.device-code-status {
|
|
227
|
+
font-weight: 700;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.local-wizard a.button {
|
|
231
|
+
text-decoration: none;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@media (max-width: 60rem),
|
|
235
|
+
(min-width: 961px) and (max-height: 768px) {
|
|
236
|
+
.local-wizard .steps ol {
|
|
237
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@media (max-width: 48rem) {
|
|
242
|
+
.target-picker,
|
|
243
|
+
.local-fields,
|
|
244
|
+
.local-review-grid {
|
|
245
|
+
grid-template-columns: minmax(0, 1fr);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.review-details div {
|
|
249
|
+
grid-template-columns: minmax(0, 1fr);
|
|
250
|
+
gap: 0.2rem;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@media (prefers-reduced-motion: reduce) {
|
|
255
|
+
.local-wizard *,
|
|
256
|
+
.local-wizard *::before,
|
|
257
|
+
.local-wizard *::after {
|
|
258
|
+
scroll-behavior: auto !important;
|
|
259
|
+
transition-duration: 0.01ms !important;
|
|
260
|
+
animation-duration: 0.01ms !important;
|
|
261
|
+
}
|
|
262
|
+
}
|