Self-hosted, federated location sharing app and server that prioritizes user privacy and security
end-to-end-encryption location-sharing privacy self-hosted federated

Nevermind, this would have been better before there was an individual css file for each thing

kishka.cc 63a9cb6b a84b2ffd

verified
Changed files
-386
app
-386
app/src/privacypin.css
··· 1 - .container-sl { 2 - display: flex; 3 - justify-content: space-between; /* This will align the elements on opposite sides of the container */ 4 - } 5 - 6 - .element-al, 7 - .element-ar { 8 - flex: 1; /* Make the elements take up equal width */ 9 - } 10 - 11 - .element-al { 12 - text-align: left; 13 - } 14 - 15 - .element-ar { 16 - text-align: right; 17 - } 18 - 19 - body { 20 - font-family: sans-serif; 21 - background: #f9fafb; 22 - margin: 0; 23 - display: flex; 24 - justify-content: center; 25 - } 26 - 27 - .app { 28 - width: 100%; 29 - background: #f9fafb; 30 - } 31 - 32 - .svg-icon { 33 - width: 25px; 34 - height: 25px; 35 - margin: auto; 36 - } 37 - 38 - header { 39 - background: #fff; 40 - border-bottom: 1px solid #e5e7eb; 41 - padding: 0.75rem 1rem; 42 - display: flex; 43 - justify-content: space-between; 44 - } 45 - 46 - header h1 { 47 - font-size: 1rem; 48 - margin: 0; 49 - display: flex; 50 - align-items: center; 51 - } 52 - 53 - header .icon-btn { 54 - border: none; 55 - background: none; 56 - cursor: pointer; 57 - padding: 0.4rem; 58 - } 59 - 60 - .status { 61 - background: #fff; 62 - border-bottom: 1px solid #f3f4f6; 63 - padding: 0.75rem 1rem; 64 - display: flex; 65 - justify-content: space-between; 66 - align-items: center; 67 - font-size: 0.9rem; 68 - } 69 - 70 - .content { 71 - flex: 1; 72 - overflow-y: auto; 73 - padding: 1rem; 74 - } 75 - 76 - .friends-header { 77 - display: flex; 78 - align-items: center; 79 - gap: 0.5rem; 80 - margin-bottom: 1rem; 81 - } 82 - 83 - .friend-card { 84 - background: #fff; 85 - border: 1px solid #e5e7eb; 86 - border-radius: 8px; 87 - padding: 1rem; 88 - margin-bottom: 0.75rem; 89 - display: flex; 90 - justify-content: space-between; 91 - align-items: center; 92 - } 93 - 94 - .friend-actions { 95 - display: flex; 96 - align-items: center; 97 - gap: 0.1rem; 98 - } 99 - 100 - .friend-actions .view-btn { 101 - cursor: pointer; 102 - border-radius: 6px; 103 - border: 1px solid #d1d5db; 104 - background: #fff; 105 - padding: 0.3rem 0.5rem; 106 - font-size: 0.8rem; 107 - } 108 - 109 - .friend-actions .view-btn:hover { 110 - background: #f3f4f6; 111 - } 112 - 113 - .menu-icon { 114 - width: 16px; 115 - height: 16px; 116 - margin: 0; 117 - } 118 - 119 - .friend-actions { 120 - cursor: pointer; 121 - font-size: 1.2rem; 122 - color: #6b7280; 123 - padding: 0 0.3rem; 124 - user-select: none; 125 - } 126 - 127 - .friend-actions { 128 - color: #111827; 129 - } 130 - 131 - .empty-state { 132 - text-align: center; 133 - padding: 3rem 1rem; 134 - color: #6b7280; 135 - } 136 - 137 - .empty-state button { 138 - margin-top: 0.75rem; 139 - padding: 0.5rem 1rem; 140 - border: none; 141 - border-radius: 6px; 142 - background: #3b82f6; 143 - color: white; 144 - cursor: pointer; 145 - } 146 - 147 - .friend-actions button img { 148 - width: 16px; 149 - height: 16px; 150 - vertical-align: middle; 151 - margin-right: 4px; 152 - } 153 - 154 - body { 155 - font-family: system-ui, sans-serif; 156 - background: #f9fafb; 157 - display: flex; 158 - align-items: center; 159 - justify-content: center; 160 - height: 100vh; 161 - margin: 0; 162 - } 163 - 164 - .card { 165 - max-width: 90%; 166 - background: white; 167 - border: 1px solid #d1d5db; 168 - border-radius: 8px; 169 - padding: 1.5rem; 170 - box-sizing: border-box; 171 - } 172 - 173 - .header { 174 - text-align: center; 175 - margin-bottom: 1.5rem; 176 - } 177 - 178 - .icon-circle { 179 - width: 64px; 180 - height: 64px; 181 - background: #dbeafe; 182 - border-radius: 50%; 183 - display: flex; 184 - align-items: center; 185 - justify-content: center; 186 - margin: 0 auto 1rem; 187 - } 188 - 189 - .icon-circle img { 190 - width: 32px; 191 - height: 32px; 192 - } 193 - 194 - h1 { 195 - font-size: 1.5rem; 196 - } 197 - 198 - p { 199 - font-size: 0.9rem; 200 - color: #6b7280; 201 - } 202 - 203 - .actions { 204 - display: flex; 205 - flex-direction: column; 206 - gap: 1rem; 207 - } 208 - 209 - label { 210 - display: block; 211 - font-size: 0.85rem; 212 - font-weight: 600; 213 - margin-bottom: 0.25rem; 214 - } 215 - 216 - input { 217 - width: 100%; 218 - padding: 0.5rem 0.75rem; 219 - border: 1px solid #d1d5db; 220 - border-radius: 4px; 221 - font-size: 0.95rem; 222 - box-sizing: border-box; 223 - } 224 - 225 - input:focus { 226 - outline: none; 227 - border-color: #2563eb; 228 - } 229 - 230 - button { 231 - width: 100%; 232 - padding: 0.6rem; 233 - font-size: 0.95rem; 234 - border-radius: 4px; 235 - cursor: pointer; 236 - /*transition: background 0.2s ease;*/ 237 - display: flex; 238 - align-items: center; 239 - justify-content: center; 240 - } 241 - 242 - .btn-primary { 243 - background: #2563eb; 244 - color: white; 245 - border: none; 246 - } 247 - 248 - .btn-primary:hover { 249 - background: #1d4ed8; 250 - } 251 - 252 - .btn-secondary { 253 - background: white; 254 - gap: 0.5rem; 255 - border: 1px solid #d1d5db; 256 - } 257 - 258 - .btn-secondary:hover { 259 - background: #f3f4f6; 260 - } 261 - 262 - .btn-secondary img { 263 - width: 16px; 264 - height: 16px; 265 - } 266 - 267 - .hint { 268 - font-size: 0.75rem; 269 - } 270 - 271 - body { 272 - font-family: system-ui, sans-serif; 273 - background: #f9fafb; 274 - display: flex; 275 - align-items: center; 276 - justify-content: center; 277 - height: 100vh; 278 - margin: 0; 279 - } 280 - 281 - .card { 282 - max-width: 90%; 283 - background: white; 284 - border: 1px solid #d1d5db; 285 - border-radius: 8px; 286 - padding: 1.5rem; 287 - box-sizing: border-box; 288 - } 289 - 290 - .header { 291 - text-align: center; 292 - margin-bottom: 1.5rem; 293 - } 294 - 295 - .icon-circle { 296 - width: 64px; 297 - height: 64px; 298 - background: #dbeafe; 299 - border-radius: 50%; 300 - display: flex; 301 - align-items: center; 302 - justify-content: center; 303 - margin: 0 auto 1rem; 304 - } 305 - 306 - .icon-circle img { 307 - width: 48px; 308 - height: 48px; 309 - } 310 - 311 - h1 { 312 - font-size: 1.5rem; 313 - } 314 - 315 - p { 316 - font-size: 0.9rem; 317 - color: #6b7280; 318 - } 319 - 320 - .actions { 321 - display: flex; 322 - flex-direction: column; 323 - gap: 1rem; 324 - } 325 - 326 - label { 327 - display: block; 328 - font-size: 0.85rem; 329 - font-weight: 600; 330 - margin-bottom: 0.25rem; 331 - } 332 - 333 - input { 334 - width: 100%; 335 - padding: 0.5rem 0.75rem; 336 - border: 1px solid #d1d5db; 337 - border-radius: 4px; 338 - font-size: 0.95rem; 339 - box-sizing: border-box; 340 - } 341 - 342 - input:focus { 343 - outline: none; 344 - border-color: #2563eb; 345 - } 346 - 347 - button { 348 - width: 100%; 349 - padding: 0.6rem; 350 - font-size: 0.95rem; 351 - border-radius: 4px; 352 - cursor: pointer; 353 - /*transition: background 0.2s ease;*/ 354 - display: flex; 355 - align-items: center; 356 - justify-content: center; 357 - } 358 - 359 - .btn-primary { 360 - background: #2563eb; 361 - color: white; 362 - border: none; 363 - } 364 - 365 - .btn-primary:hover { 366 - background: #1d4ed8; 367 - } 368 - 369 - .btn-qr { 370 - background: white; 371 - gap: 0.5rem; 372 - border: 1px solid #d1d5db; 373 - } 374 - 375 - .btn-qr:hover { 376 - background: #f3f4f6; 377 - } 378 - 379 - .btn-qr img { 380 - width: 20px; 381 - height: 16px; 382 - } 383 - 384 - .hint { 385 - font-size: 0.75rem; 386 - }