Self-hosted, federated location sharing app and server that prioritizes user privacy and security
end-to-end-encryption
location-sharing
privacy
self-hosted
federated
1body {
2 font-family: system-ui, sans-serif;
3 background: #f9fafb;
4 display: flex;
5 align-items: center;
6 justify-content: center;
7 height: 100vh;
8 margin: 0;
9}
10
11p {
12 font-size: 0.9rem;
13 color: #6b7280;
14}
15
16.hint {
17 font-size: 0.75rem;
18}
19
20.container {
21 display: flex;
22}
23
24.container div {
25 flex: 1;
26 text-align: center;
27 margin: auto;
28}
29
30.contentHeader {
31 text-align: center;
32 border-bottom: 1px solid #e5e7eb;
33 padding-bottom: 10px;
34}
35
36.icon-btn {
37 border: none;
38 background: none;
39 cursor: pointer;
40 padding: 0.4rem;
41 font-size: 1rem;
42}
43
44.svg-icon {
45 width: 25px;
46 height: 25px;
47 margin: auto;
48}
49
50.app {
51 width: 100%;
52 background: #f9fafb;
53 min-height: 100vh;
54}
55
56header {
57 background: #fff;
58 border-bottom: 1px solid #e5e7eb;
59 padding: 0.75rem 1rem;
60 padding-top: 15%;
61 display: flex;
62 align-items: center;
63}
64
65.content {
66 padding: 1rem;
67 display: grid;
68 gap: 0.75rem;
69}
70
71.card {
72 background: white;
73 border: 1px solid #d1d5db;
74 border-radius: 8px;
75 padding: 1.5rem;
76}
77
78.row {
79 display: flex;
80 justify-content: space-between;
81 gap: 1rem;
82 align-items: center;
83}
84
85label {
86 display: block;
87 margin-top: 0.5rem;
88 margin-bottom: 0.25rem;
89 font-size: 0.9rem;
90 color: #374151;
91}
92
93input {
94 width: 100%;
95 box-sizing: border-box;
96 padding: 0.55rem 0.6rem;
97 border-radius: 8px;
98 border: 1px solid #d1d5db;
99 outline: none;
100}
101
102input:focus {
103 border-color: #3b82f6;
104}
105
106button.primary {
107 margin-top: 0.75rem;
108 width: 100%;
109 padding: 0.6rem 0.75rem;
110 border: none;
111 border: 1px solid #d1d5db;
112 border-radius: 8px;
113 background: #3b82f6;
114 color: white;
115 cursor: pointer;
116}
117
118button.primary:hover {
119 background: #2563eb;
120}
121
122button.secondary {
123 margin-top: 0.75rem;
124 width: 100%;
125 padding: 0.6rem 0.75rem;
126 border: 1px solid #d1d5db;
127 border-radius: 8px;
128 background: #ffffff;
129 color: #000000;
130 cursor: pointer;
131}
132
133button.secondary:hover {
134 background: #d7d9de;
135}
136
137.switch {
138 position: relative;
139 display: inline-block;
140 width: 46px;
141 height: 26px;
142}
143
144.switch input {
145 opacity: 0;
146 width: 0;
147 height: 0;
148}
149
150.slider {
151 position: absolute;
152 cursor: pointer;
153 top: 0;
154 left: 0;
155 right: 0;
156 bottom: 0;
157 background-color: #ccc;
158 -webkit-transition: 0.4s;
159 transition: 0.4s;
160 border-radius: 50px;
161}
162
163.slider:before {
164 position: absolute;
165 content: "";
166 height: 20px;
167 width: 20px;
168 left: 3px;
169 bottom: 3px;
170 background-color: white;
171 -webkit-transition: 0.4s;
172 transition: 0.4s;
173 border-radius: 50%;
174}
175
176input:checked + .slider {
177 background-color: #3b82f6;
178}
179
180input:focus + .slider {
181 box-shadow: 0 0 1px #3b82f6;
182}
183
184input:checked + .slider:before {
185 -webkit-transform: translateX(20px);
186 -ms-transform: translateX(20px);
187 transform: translateX(20px);
188}
189
190.status {
191 background: #fff;
192 border-bottom: 1px solid #f3f4f6;
193 padding: 0.75rem 1rem;
194 display: flex;
195 justify-content: space-between;
196 align-items: center;
197 font-size: 0.9rem;
198}
199
200.friends-header {
201 display: flex;
202 align-items: center;
203 gap: 0.5rem;
204 margin-bottom: 1rem;
205}
206
207.friend-card {
208 background: #fff;
209 border: 1px solid #e5e7eb;
210 border-radius: 8px;
211 padding: 1rem;
212 margin-bottom: 0.75rem;
213 display: flex;
214 justify-content: space-between;
215 align-items: center;
216}
217
218.friend-actions {
219 display: flex;
220 align-items: center;
221 gap: 0.1rem;
222}
223
224.friend-actions .view-btn {
225 cursor: pointer;
226 border-radius: 6px;
227 border: 1px solid #d1d5db;
228 background: #fff;
229 padding: 0.3rem 0.5rem;
230 font-size: 0.8rem;
231}
232
233.friend-actions .view-btn:hover {
234 background: #f3f4f6;
235}
236
237.friend-actions {
238 cursor: pointer;
239 font-size: 1.2rem;
240 color: #6b7280;
241 padding: 0 0.3rem;
242 user-select: none;
243}
244
245.friend-actions {
246 color: #111827;
247}
248
249.empty-state {
250 text-align: center;
251 padding: 3rem 1rem;
252 color: #6b7280;
253}
254
255.friend-actions button img {
256 width: 16px;
257 height: 16px;
258 vertical-align: middle;
259 margin-right: 4px;
260}
261
262.icon-circle {
263 width: 64px;
264 height: 64px;
265 background: #dbeafe;
266 border-radius: 50%;
267 display: flex;
268 align-items: center;
269 justify-content: center;
270 margin: 0 auto 1rem;
271}
272
273.icon-circle img {
274 width: 64px;
275 height: 64px;
276}
277
278button img {
279 width: 16px;
280 height: 16px;
281 margin: auto;
282}