@sensorario/sg-components 0.0.100 → 0.0.102

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.
@@ -0,0 +1,10 @@
1
+ import './AppAccessGate.css';
2
+ export declare const DEFAULT_HEIMDALL_URL = "https://api.simonegentili.com/heimdall";
3
+ interface AppAccessGateProps {
4
+ /** Logged-in user's JWT. Without it there's nothing to check: the app's own login flow applies. */
5
+ token: string | null;
6
+ /** Base URL of the Heimdall API (`/access`, `/access-requests`). */
7
+ heimdallUrl?: string;
8
+ }
9
+ export declare const AppAccessGate: ({ token, heimdallUrl }: AppAccessGateProps) => import("react/jsx-runtime").JSX.Element | null;
10
+ export default AppAccessGate;
@@ -0,0 +1,8 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import AppAccessGate from './AppAccessGate';
3
+ declare const meta: Meta<typeof AppAccessGate>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AppAccessGate>;
6
+ export declare const NotGranted: Story;
7
+ export declare const Pending: Story;
8
+ export declare const Rejected: Story;
@@ -9,6 +9,8 @@ interface AppLauncherProps {
9
9
  appsUrl?: string;
10
10
  /** Accessible name of the grid button - this library has no i18n of its own. */
11
11
  label?: string;
12
+ /** Logged-in user's JWT: the API then lists only the apps this user may use. */
13
+ token?: string | null;
12
14
  }
13
- export declare const AppLauncher: ({ appsUrl, label }: AppLauncherProps) => import("react/jsx-runtime").JSX.Element;
15
+ export declare const AppLauncher: ({ appsUrl, label, token }: AppLauncherProps) => import("react/jsx-runtime").JSX.Element;
14
16
  export default AppLauncher;
@@ -17,6 +17,8 @@ interface QuadratoHeaderProps {
17
17
  onUserAuthenticated?: (isAuthenticated: boolean, username: string | null) => void;
18
18
  /** Endpoint of the app launcher menu. Default: the Heimdall-managed list on api.simonegentili.com. */
19
19
  appsUrl?: string;
20
+ /** Base URL of the Heimdall API, used to check whether the logged-in user may use this app. */
21
+ heimdallUrl?: string;
20
22
  }
21
23
  export interface QuadratoHeaderHandle {
22
24
  /** Forces the login modal open, e.g. when a consumer action requires auth first. */
package/dist/index.d.ts CHANGED
@@ -16,3 +16,4 @@ export * from './components/ColorPicker/ColorPicker';
16
16
  export * from './components/FontPicker/FontPicker';
17
17
  export * from './components/Toggle/Toggle';
18
18
  export * from './components/AppLauncher/AppLauncher';
19
+ export * from './components/AppAccessGate/AppAccessGate';
package/dist/index.es.js CHANGED
@@ -347,51 +347,117 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
347
347
  onNavigate: e,
348
348
  title: "Simone Gentili - senior web developer, tech author and chess enthusiast",
349
349
  homePageKey: "home"
350
- }), C = "https://api.simonegentili.com/heimdall/launcher", w = ({ appsUrl: e = C, label: t = "App" }) => {
351
- let [r, i] = o(!1), [s, u] = o(null), [f, p] = o(!1), m = a(null);
350
+ }), C = "https://api.simonegentili.com/heimdall", w = (e) => e.endsWith("/") ? e : `${e}/`, T = (e) => {
351
+ let t = w(window.location.origin + window.location.pathname);
352
+ return e.filter((e) => t.startsWith(w(e.url))).sort((e, t) => t.url.length - e.url.length)[0] ?? null;
353
+ }, E = ({ token: e, heimdallUrl: t = C }) => {
354
+ let [r, i] = o(null), [a, u] = o(!1), [d, p] = o(!1);
355
+ n(() => {
356
+ e && fetch(`${t}/access`, { headers: { Authorization: `Bearer ${e}` } }).then((e) => e.ok ? e.json() : Promise.reject(e.status)).then((t) => i({
357
+ token: e,
358
+ app: T(t.apps)
359
+ })).catch(() => i({
360
+ token: e,
361
+ app: null
362
+ }));
363
+ }, [e, t]);
364
+ let m = r?.token === e ? r.app : null;
365
+ return !e || m === null || m.access === "open" || m.access === "approved" ? null : /* @__PURE__ */ c("div", {
366
+ className: "sg-access-gate",
367
+ role: "dialog",
368
+ "aria-modal": "true",
369
+ "aria-labelledby": "sg-access-gate-title",
370
+ children: /* @__PURE__ */ l("div", {
371
+ className: "sg-access-gate-card",
372
+ children: [/* @__PURE__ */ l("h2", {
373
+ id: "sg-access-gate-title",
374
+ children: ["Non hai accesso a ", m.name]
375
+ }), m.access === "pending" ? /* @__PURE__ */ c("p", { children: "La tua richiesta è in attesa di approvazione." }) : /* @__PURE__ */ l(s, { children: [
376
+ /* @__PURE__ */ c("p", { children: m.access === "rejected" ? "La tua richiesta di accesso è stata rifiutata. Puoi inviarne una nuova." : "Per usare questa app devi chiedere l’accesso a un amministratore." }),
377
+ d && /* @__PURE__ */ c("p", {
378
+ className: "sg-access-gate-error",
379
+ children: "Invio non riuscito, riprova."
380
+ }),
381
+ /* @__PURE__ */ c(f, {
382
+ label: a ? "Invio…" : "Richiedi accesso",
383
+ disabled: a,
384
+ onClick: async () => {
385
+ u(!0), p(!1);
386
+ try {
387
+ let n = await fetch(`${t}/access-requests`, {
388
+ method: "POST",
389
+ headers: {
390
+ Authorization: `Bearer ${e}`,
391
+ "Content-Type": "application/json"
392
+ },
393
+ body: JSON.stringify({ app: m.slug })
394
+ });
395
+ n.ok || n.status === 409 ? i({
396
+ token: e,
397
+ app: {
398
+ ...m,
399
+ access: "pending"
400
+ }
401
+ }) : p(!0);
402
+ } catch {
403
+ p(!0);
404
+ } finally {
405
+ u(!1);
406
+ }
407
+ }
408
+ })
409
+ ] })]
410
+ })
411
+ });
412
+ }, D = "https://api.simonegentili.com/heimdall/launcher", O = ({ appsUrl: e = D, label: t = "App", token: r = null }) => {
413
+ let [i, s] = o(!1), [u, f] = o(null), p = u?.token === r ? u.apps : null, [m, h] = o(!1), g = a(null);
352
414
  return n(() => {
353
- !r || s !== null || fetch(e).then((e) => e.ok ? e.json() : Promise.reject(e.status)).then((e) => u(e.apps)).catch(() => p(!0));
415
+ !i || p !== null || fetch(e, r ? { headers: { Authorization: `Bearer ${r}` } } : void 0).then((e) => e.ok ? e.json() : Promise.reject(e.status)).then((e) => f({
416
+ token: r,
417
+ apps: e.apps
418
+ })).catch(() => h(!0));
354
419
  }, [
355
- r,
356
- s,
357
- e
420
+ i,
421
+ p,
422
+ e,
423
+ r
358
424
  ]), n(() => {
359
- if (!r) return;
425
+ if (!i) return;
360
426
  let e = (e) => {
361
- m.current?.contains(e.target) || i(!1);
427
+ g.current?.contains(e.target) || s(!1);
362
428
  }, t = (e) => {
363
- e.key === "Escape" && i(!1);
429
+ e.key === "Escape" && s(!1);
364
430
  };
365
431
  return document.addEventListener("pointerdown", e), document.addEventListener("keydown", t), () => {
366
432
  document.removeEventListener("pointerdown", e), document.removeEventListener("keydown", t);
367
433
  };
368
- }, [r]), /* @__PURE__ */ l("div", {
434
+ }, [i]), /* @__PURE__ */ l("div", {
369
435
  className: "sg-app-launcher",
370
- ref: m,
436
+ ref: g,
371
437
  children: [/* @__PURE__ */ c("button", {
372
438
  type: "button",
373
439
  className: "sg-app-launcher-toggle",
374
440
  "aria-label": t,
375
441
  title: t,
376
- "aria-expanded": r,
442
+ "aria-expanded": i,
377
443
  onClick: () => {
378
- r || p(!1), i(!r);
444
+ i || h(!1), s(!i);
379
445
  },
380
446
  children: /* @__PURE__ */ c(d, {
381
447
  name: "grid",
382
448
  size: 22
383
449
  })
384
- }), r && /* @__PURE__ */ c("div", {
450
+ }), i && /* @__PURE__ */ c("div", {
385
451
  className: "sg-app-launcher-panel",
386
- children: f ? /* @__PURE__ */ c("p", {
452
+ children: m ? /* @__PURE__ */ c("p", {
387
453
  className: "sg-app-launcher-message",
388
454
  children: "Impossibile caricare le app."
389
- }) : s === null ? /* @__PURE__ */ c("p", {
455
+ }) : p === null ? /* @__PURE__ */ c("p", {
390
456
  className: "sg-app-launcher-message",
391
457
  children: "Caricamento…"
392
458
  }) : /* @__PURE__ */ c("ul", {
393
459
  className: "sg-app-launcher-grid",
394
- children: s.map((e) => /* @__PURE__ */ c("li", { children: /* @__PURE__ */ l("a", {
460
+ children: p.map((e) => /* @__PURE__ */ c("li", { children: /* @__PURE__ */ l("a", {
395
461
  href: e.url,
396
462
  className: new URL(e.url).origin === window.location.origin ? "sg-app-launcher-app current" : "sg-app-launcher-app",
397
463
  children: [/* @__PURE__ */ c("span", {
@@ -406,28 +472,22 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
406
472
  })
407
473
  })]
408
474
  });
409
- }, T = ({ isLoggedIn: e, handleLogin: t, handleLogout: n }) => /* @__PURE__ */ c(s, { children: e ? /* @__PURE__ */ c("button", {
475
+ }, k = ({ isLoggedIn: e, handleLogin: t, handleLogout: n }) => /* @__PURE__ */ c(s, { children: e ? /* @__PURE__ */ c("button", {
410
476
  onClick: n,
411
- style: {
412
- fontSize: "0.9rem",
413
- padding: "0.4rem 1rem"
414
- },
477
+ className: "sg-authenticator-button",
415
478
  children: "logout"
416
479
  }) : /* @__PURE__ */ c("button", {
417
480
  onClick: t,
418
- style: {
419
- fontSize: "0.9rem",
420
- padding: "0.4rem 1rem"
421
- },
481
+ className: "sg-authenticator-button",
422
482
  children: "Login"
423
- }) }), E = 220, D = ({ open: t, onClose: r, title: i, icon: a, children: s, buttons: u, footer: d, closeLabel: p = "Close", className: m }) => {
483
+ }) }), A = 220, j = ({ open: t, onClose: r, title: i, icon: a, children: s, buttons: u, footer: d, closeLabel: p = "Close", className: m }) => {
424
484
  let [h, g] = o(!1), [_, v] = o({
425
485
  x: 0,
426
486
  y: 0
427
487
  }), y = e.useRef(null), [b, x] = o(!1), S = (e) => {
428
488
  h || (g(!0), setTimeout(() => {
429
489
  g(!1), e();
430
- }, E));
490
+ }, A));
431
491
  };
432
492
  n(() => {
433
493
  if (!t) return;
@@ -449,7 +509,7 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
449
509
  offsetY: _.y
450
510
  }, x(!0), e.currentTarget.setPointerCapture(e.pointerId));
451
511
  }
452
- function D(e) {
512
+ function E(e) {
453
513
  if (!y.current) return;
454
514
  let { pointerX: t, pointerY: n, offsetX: r, offsetY: i } = y.current;
455
515
  v({
@@ -457,7 +517,7 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
457
517
  y: i + (e.clientY - n)
458
518
  });
459
519
  }
460
- function O() {
520
+ function D() {
461
521
  y.current = null, x(!1);
462
522
  }
463
523
  return /* @__PURE__ */ c("div", {
@@ -474,9 +534,9 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
474
534
  /* @__PURE__ */ l("div", {
475
535
  className: `modal-header${b ? " modal-header-dragging" : ""}`,
476
536
  onPointerDown: T,
477
- onPointerMove: D,
478
- onPointerUp: O,
479
- onPointerCancel: O,
537
+ onPointerMove: E,
538
+ onPointerUp: D,
539
+ onPointerCancel: D,
480
540
  children: [
481
541
  a && /* @__PURE__ */ c("span", {
482
542
  className: "modal-icon",
@@ -515,7 +575,7 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
515
575
  ]
516
576
  })
517
577
  });
518
- }, O = ({ label: e, invalid: t, className: n, id: i, ...a }) => {
578
+ }, M = ({ label: e, invalid: t, className: n, id: i, ...a }) => {
519
579
  let o = r(), s = i ?? o;
520
580
  return /* @__PURE__ */ l("div", {
521
581
  className: "input-wrapper",
@@ -533,7 +593,7 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
533
593
  ...a
534
594
  })]
535
595
  });
536
- }, k = ({ label: e, className: t, id: n, ...i }) => {
596
+ }, N = ({ label: e, className: t, id: n, ...i }) => {
537
597
  let a = r(), o = n ?? a;
538
598
  return /* @__PURE__ */ l("div", {
539
599
  className: "input-wrapper",
@@ -548,9 +608,9 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
548
608
  ...i
549
609
  })]
550
610
  });
551
- }, A = ({ open: e, onClose: t, onLogin: n }) => {
611
+ }, P = ({ open: e, onClose: t, onLogin: n }) => {
552
612
  let [r, i] = o(""), [a, s] = o("");
553
- return /* @__PURE__ */ c(D, {
613
+ return /* @__PURE__ */ c(j, {
554
614
  open: e,
555
615
  onClose: t,
556
616
  title: "Login",
@@ -559,13 +619,13 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
559
619
  e.preventDefault(), n(r, a);
560
620
  },
561
621
  children: [
562
- /* @__PURE__ */ c(O, {
622
+ /* @__PURE__ */ c(M, {
563
623
  label: "Username",
564
624
  value: r,
565
625
  onChange: (e) => i(e.target.value),
566
626
  autoFocus: !0
567
627
  }),
568
- /* @__PURE__ */ c(k, {
628
+ /* @__PURE__ */ c(N, {
569
629
  label: "Password",
570
630
  value: a,
571
631
  onChange: (e) => s(e.target.value)
@@ -578,57 +638,67 @@ var v = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
578
638
  ]
579
639
  })
580
640
  });
581
- }, j = "simonegentili.com-access-token", M = (e) => document.cookie.split("; ").some((t) => t.startsWith(`${e}=`) && t.slice(e.length + 1).length > 0), N = (e) => {
641
+ }, F = "simonegentili.com-access-token", I = (e) => document.cookie.split("; ").some((t) => t.startsWith(`${e}=`) && t.slice(e.length + 1).length > 0), L = (e) => {
582
642
  let t = document.cookie.split("; ").find((t) => t.startsWith(`${e}=`));
583
643
  return t ? t.slice(e.length + 1) : null;
584
- }, P = (e, t) => {
644
+ }, R = (e, t) => {
585
645
  try {
586
646
  return JSON.parse(atob(e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/")))[t] ?? null;
587
647
  } catch {
588
648
  return null;
589
649
  }
590
- }, F = t(({ title: e = "Quadrato", homePageKey: t = "home", onNavigate: r, cookieName: a = j, username: u = null, usernameJwtField: d = "sub", onLogin: f, onLogout: p, onUserAuthenticated: m, appsUrl: h }, g) => {
591
- let [_, v] = o(() => M(a)), [y, b] = o(!1);
592
- i(g, () => ({ openLoginModal: () => b(!0) }));
593
- let S = u ?? (_ ? P(N(a) ?? "", d) : null);
650
+ }, z = t(({ title: e = "Quadrato", homePageKey: t = "home", onNavigate: r, cookieName: a = F, username: u = null, usernameJwtField: d = "sub", onLogin: f, onLogout: p, onUserAuthenticated: m, appsUrl: h, heimdallUrl: g }, _) => {
651
+ let [v, y] = o(() => I(a)), [b, S] = o(!1);
652
+ i(_, () => ({ openLoginModal: () => S(!0) }));
653
+ let C = v ? L(a) : null, w = u ?? (C ? R(C, d) : null);
594
654
  return n(() => {
595
- m?.(_, _ ? S : null);
596
- }, []), /* @__PURE__ */ l(s, { children: [/* @__PURE__ */ l(x, {
597
- onNavigate: r,
598
- title: e,
599
- homePageKey: t,
600
- className: "quadrato-header",
601
- children: [/* @__PURE__ */ c(w, { appsUrl: h }), /* @__PURE__ */ l("div", {
602
- className: "quadrato-header-auth",
603
- children: [_ && S && /* @__PURE__ */ c("span", {
604
- className: "quadrato-header-username",
605
- children: S
606
- }), /* @__PURE__ */ c(T, {
607
- isLoggedIn: _,
608
- handleLogin: () => b(!0),
609
- handleLogout: () => {
610
- p?.();
611
- let e = M(a);
612
- v(e), m?.(e, null);
613
- }
655
+ m?.(v, v ? w : null);
656
+ }, []), /* @__PURE__ */ l(s, { children: [
657
+ /* @__PURE__ */ l(x, {
658
+ onNavigate: r,
659
+ title: e,
660
+ homePageKey: t,
661
+ className: "quadrato-header",
662
+ children: [/* @__PURE__ */ c(O, {
663
+ appsUrl: h,
664
+ token: C
665
+ }), /* @__PURE__ */ l("div", {
666
+ className: "quadrato-header-auth",
667
+ children: [v && w && /* @__PURE__ */ c("span", {
668
+ className: "quadrato-header-username",
669
+ children: w
670
+ }), /* @__PURE__ */ c(k, {
671
+ isLoggedIn: v,
672
+ handleLogin: () => S(!0),
673
+ handleLogout: () => {
674
+ p?.();
675
+ let e = I(a);
676
+ y(e), m?.(e, null);
677
+ }
678
+ })]
614
679
  })]
615
- })]
616
- }), /* @__PURE__ */ c(A, {
617
- open: y,
618
- onClose: () => b(!1),
619
- onLogin: async (e, t) => {
620
- await f(e, t);
621
- let n = M(a);
622
- v(n), b(!1), m?.(n, n ? u ?? e : null);
623
- }
624
- })] });
680
+ }),
681
+ /* @__PURE__ */ c(E, {
682
+ token: C,
683
+ heimdallUrl: g
684
+ }),
685
+ /* @__PURE__ */ c(P, {
686
+ open: b,
687
+ onClose: () => S(!1),
688
+ onLogin: async (e, t) => {
689
+ await f(e, t);
690
+ let n = I(a);
691
+ y(n), S(!1), m?.(n, n ? u ?? e : null);
692
+ }
693
+ })
694
+ ] });
625
695
  });
626
- F.displayName = "QuadratoHeader";
696
+ z.displayName = "QuadratoHeader";
627
697
  //#endregion
628
698
  //#region src/components/SetPasswordModal/SetPasswordModal.tsx
629
- var I = ({ open: e, onClose: t, onSubmit: n }) => {
699
+ var B = ({ open: e, onClose: t, onSubmit: n }) => {
630
700
  let [r, i] = o(""), [a, s] = o(""), [u, d] = o("");
631
- return /* @__PURE__ */ c(D, {
701
+ return /* @__PURE__ */ c(j, {
632
702
  open: e,
633
703
  onClose: t,
634
704
  title: "Imposta una nuova password",
@@ -646,13 +716,13 @@ var I = ({ open: e, onClose: t, onSubmit: n }) => {
646
716
  d(""), n(r);
647
717
  },
648
718
  children: [
649
- /* @__PURE__ */ c(k, {
719
+ /* @__PURE__ */ c(N, {
650
720
  label: "Nuova password",
651
721
  value: r,
652
722
  onChange: (e) => i(e.target.value),
653
723
  autoFocus: !0
654
724
  }),
655
- /* @__PURE__ */ c(k, {
725
+ /* @__PURE__ */ c(N, {
656
726
  label: "Conferma password",
657
727
  value: a,
658
728
  onChange: (e) => s(e.target.value)
@@ -669,7 +739,7 @@ var I = ({ open: e, onClose: t, onSubmit: n }) => {
669
739
  ]
670
740
  })
671
741
  });
672
- }, L = ({ value: e, onChange: t, swatches: r }) => {
742
+ }, V = ({ value: e, onChange: t, swatches: r }) => {
673
743
  let [i, s] = o(!1), u = a(null);
674
744
  return n(() => {
675
745
  if (!i) return;
@@ -718,7 +788,7 @@ var I = ({ open: e, onClose: t, onSubmit: n }) => {
718
788
  })]
719
789
  })]
720
790
  });
721
- }, R = (e) => e.split(",")[0].replace(/'/g, ""), z = ({ value: e, onChange: t, options: r }) => {
791
+ }, H = (e) => e.split(",")[0].replace(/'/g, ""), U = ({ value: e, onChange: t, options: r }) => {
722
792
  let [i, s] = o(!1), u = a(null);
723
793
  return n(() => {
724
794
  if (!i) return;
@@ -740,7 +810,7 @@ var I = ({ open: e, onClose: t, onSubmit: n }) => {
740
810
  style: { fontFamily: e },
741
811
  children: [/* @__PURE__ */ c("span", {
742
812
  className: "sg-font-picker-toggle-label",
743
- children: R(e)
813
+ children: H(e)
744
814
  }), /* @__PURE__ */ c("span", {
745
815
  className: "sg-font-picker-toggle-caret",
746
816
  children: i ? "▲" : "▼"
@@ -754,11 +824,11 @@ var I = ({ open: e, onClose: t, onSubmit: n }) => {
754
824
  t(n), s(!1);
755
825
  },
756
826
  style: { fontFamily: n },
757
- children: R(n)
827
+ children: H(n)
758
828
  }) }, n))
759
829
  })]
760
830
  });
761
- }, B = ({ checked: e, onChange: t, label: n }) => /* @__PURE__ */ l("label", {
831
+ }, W = ({ checked: e, onChange: t, label: n }) => /* @__PURE__ */ l("label", {
762
832
  className: "sg-toggle",
763
833
  children: [
764
834
  /* @__PURE__ */ c("input", {
@@ -778,4 +848,4 @@ var I = ({ open: e, onClose: t, onSubmit: n }) => {
778
848
  ]
779
849
  });
780
850
  //#endregion
781
- export { w as AppLauncher, T as Authenticator, f as Button, L as ColorPicker, v as CookieConsent, C as DEFAULT_APPS_URL, z as FontPicker, p as Footer, x as Header, d as Icon, O as Input, D as Modal, k as PasswordInput, F as QuadratoHeader, b as SGFooter, S as SGHeader, I as SetPasswordModal, B as Toggle };
851
+ export { E as AppAccessGate, O as AppLauncher, k as Authenticator, f as Button, V as ColorPicker, v as CookieConsent, D as DEFAULT_APPS_URL, C as DEFAULT_HEIMDALL_URL, U as FontPicker, p as Footer, x as Header, d as Icon, M as Input, j as Modal, N as PasswordInput, z as QuadratoHeader, b as SGFooter, S as SGHeader, B as SetPasswordModal, W as Toggle };
@@ -1,2 +1,2 @@
1
- .custom-button{border-radius:var(--button-radius);background:var(--button-bg);color:var(--button-color);cursor:pointer;font-size:var(--primary-font);font-weight:600;font-family:var(--font-family);box-shadow:var(--button-shadow);transition:background .15s var(--button-ease-standard), transform var(--button-ease-bounce) .2s;border:none;padding:8px 20px}.custom-button:hover:not(:disabled){background:var(--button-bg-hover);transform:translateY(-1px)}.custom-button:active:not(:disabled){transform:scale(.97)}.custom-button:disabled{opacity:.6;cursor:default}.custom-button-with-icon{align-items:center;gap:8px;display:inline-flex}.custom-button-label-visually-hidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.sg-icon{vertical-align:middle;flex-shrink:0;display:inline-block}.footer{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;justify-content:space-between;align-items:center;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.footer a{color:#1ea7fd;text-decoration:none}.footer a:hover{text-decoration:underline}.cookie-consent{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;z-index:1000;box-sizing:border-box;flex-wrap:wrap;justify-content:center;align-items:center;gap:16px;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.cookie-consent-text{flex:320px;margin:0}.cookie-consent a{color:#1ea7fd;text-decoration:none}.cookie-consent a:hover{text-decoration:underline}.cookie-consent-accept{flex:none}.logo-text{font-size:var(--font-size-h1);font-family:var(--font-family);margin:0;font-weight:400}.header{z-index:100;width:100%;font-size:var(--font-size);background-color:#fff;border-bottom:1px solid #e1e5e9;position:sticky;top:0;box-shadow:0 2px 4px #0000001a}.header-container{justify-content:flex-start;align-items:center;max-width:1200px;margin:0 auto;padding:16px;display:flex}.header-actions{align-items:center;gap:12px;margin-left:auto;display:flex}.logo{cursor:pointer;color:#333;font-size:24px;font-weight:700;transition:color .2s}.logo:hover{color:#007acc}.logo-full{display:inline}.logo-short{display:none}@media (width<=768px){.header-container{padding:12px 16px}.logo{font-size:var(--font-size)}.logo-full{display:none}.logo-short{display:inline}}@media (width<=480px){.header-container{padding:8px 12px}.logo{font-size:var(--font-size)}}.sg-app-launcher{font-family:var(--font-family);position:relative}.sg-app-launcher-toggle{width:40px;height:40px;color:var(--ink-muted);cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;padding:0;display:inline-flex}.sg-app-launcher-toggle:hover,.sg-app-launcher-toggle[aria-expanded=true]{background:var(--primary-hover-bg)}.sg-app-launcher-panel{z-index:1000;box-sizing:border-box;border:1px solid var(--primary-border);border-radius:calc(var(--radius) * 3);background:var(--modal-bg);width:320px;max-width:calc(100vw - 24px);max-height:70vh;box-shadow:var(--shadow-2);padding:12px;position:absolute;top:calc(100% + 8px);right:0;overflow-y:auto}.sg-app-launcher-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;margin:0;padding:0;list-style:none;display:grid}.sg-app-launcher-app{border-radius:var(--radius);color:inherit;flex-direction:column;align-items:center;gap:6px;padding:12px 4px;text-decoration:none;display:flex}.sg-app-launcher-app:hover,.sg-app-launcher-app:focus-visible{background:var(--primary-hover-bg)}.sg-app-launcher-app.current{background:var(--accent-soft)}.sg-app-launcher-tile{border-radius:var(--radius);background:var(--accent);color:#fff;justify-content:center;align-items:center;width:40px;height:40px;font-size:18px;font-weight:600;display:flex}.sg-app-launcher-name{text-overflow:ellipsis;white-space:nowrap;max-width:100%;font-size:13px;overflow:hidden}.sg-app-launcher-message{color:var(--ink-muted);margin:0;padding:8px;font-size:13px}.modal-overlay{background:var(--modal-overlay);z-index:1000;justify-content:center;align-items:center;width:100vw;height:100vh;animation:.25s ease-out sg-modal-overlay-fade-in;display:flex;position:fixed;top:0;left:0}.modal-overlay.modal-overlay-closing{animation:.22s ease-in forwards sg-modal-overlay-fade-out}.modal-content{--drag-x:0px;--drag-y:0px;background:var(--modal-bg);border-radius:var(--primary-radius);font-size:var(--primary-font);min-width:320px;max-width:calc(100vw - 40px);max-height:90vh;transform:translate(var(--drag-x), var(--drag-y));flex-direction:column;animation:.3s ease-out sg-modal-slide-in;display:flex;overflow:hidden;box-shadow:0 2px 16px #00000026}.modal-content.modal-content-closing{animation:.22s ease-in forwards sg-modal-slide-out}@keyframes sg-modal-overlay-fade-in{0%{opacity:0}to{opacity:1}}@keyframes sg-modal-overlay-fade-out{0%{opacity:1}to{opacity:0}}@keyframes sg-modal-slide-in{0%{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}to{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}}@keyframes sg-modal-slide-out{0%{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}to{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}}.modal-header{background:var(--primary-bg);border-top-left-radius:var(--primary-radius);border-top-right-radius:var(--primary-radius);cursor:grab;touch-action:none;flex:none;align-items:center;gap:8px;padding:16px;display:flex}.modal-header-dragging{cursor:grabbing;-webkit-user-select:none;user-select:none}.modal-icon{color:var(--modal-title-color);display:inline-flex}.modal-title{color:var(--modal-title-color);font-family:var(--font-family);font-size:var(--primary-font);flex:1;margin:0}.modal-close{cursor:pointer;color:var(--modal-title-color);background:0 0;border:none;padding:4px 8px;font-size:20px;line-height:1}.modal-close:disabled{cursor:default;opacity:.6}.modal-children{font-family:var(--font-family);padding:16px;overflow-y:auto}.modal-footer{border-top:1px solid var(--primary-border);flex-wrap:wrap;flex:none;justify-content:flex-end;gap:8px;padding:12px 16px;display:flex}.input-label{font-weight:500;font-family:var(--font-family);font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field--invalid{background-color:#ffe5e5;border-color:#c00}.input-wrapper{margin-bottom:16px}.input-label{font-weight:500;font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field{box-sizing:border-box;border-radius:var(--radius);width:100%;font-size:var(--primary-font);border-style:solid;border-width:1px;padding:8px}.login-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.header.quadrato-header{z-index:999}.quadrato-header-auth{align-items:center;gap:12px;display:flex}.quadrato-header-username{font-size:var(--font-size);color:#333}form{font-family:var(--font-family)}.set-password-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.set-password-modal-error{color:#d32f2f;font-size:var(--primary-font);margin:0}.sg-color-picker{font-family:var(--font-family);position:relative}.sg-color-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-family:inherit;font-size:13px;display:flex}.sg-color-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-color-picker-swatch{border:1px solid #00000026;border-radius:4px;flex:none;width:18px;height:18px}.sg-color-picker-popover{z-index:30;background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);box-shadow:var(--shadow-1);width:170px;padding:10px;position:absolute;top:calc(100% + 4px);left:0}.sg-color-picker-grid{grid-template-columns:repeat(6,1fr);gap:6px;display:grid}.sg-color-picker-swatch-button{cursor:pointer;border:1px solid #00000026;border-radius:4px;width:20px;height:20px;padding:0}.sg-color-picker-swatch-button.active{border:2px solid var(--accent)}.sg-color-picker-custom{border-top:1px solid var(--input-border);color:var(--ink-muted);cursor:pointer;justify-content:space-between;align-items:center;gap:8px;margin-top:8px;padding-top:8px;font-size:11px;display:flex}.sg-color-picker-custom input[type=color]{cursor:pointer;border:none;width:26px;height:20px;padding:0}.sg-font-picker{font-family:var(--font-family);position:relative}.sg-font-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.sg-font-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-font-picker-toggle-caret{opacity:.5;flex:none;font-size:10px}.sg-font-picker-list{background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);max-height:260px;box-shadow:var(--shadow-1);z-index:30;margin:0;padding:4px 0;list-style:none;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto}.sg-font-picker-option{text-align:left;width:100%;color:inherit;cursor:pointer;background:0 0;border:none;padding:8px 10px;font-size:15px;display:block}.sg-font-picker-option.active{background:var(--accent-soft)}:root{--unit:3px;--primary-bg:#f5f5f5;--primary-border:#ccc;--radius:calc(var(--unit) * 2);--primary-radius:var(--radius);--primary-font:var(--font-size);--primary-hover-bg:#e0e0e0;--modal-bg:#fff;--modal-overlay:#0000004d;--modal-title-color:#222;--input-bg:#fff;--input-border:#ccc;--input-radius:var(--radius);--input-font:1rem;--font-size:14px;--font-family:Arial, sans-serif;--font-size-h1:calc(var(--font-size) * 1.5);--button-bg:#6f9cf7;--button-bg-hover:#5480e6;--button-color:#fff;--button-radius:999px;--button-shadow:0 1px 2px #5480e61f, 0 1px 3px #5480e61a;--button-ease-standard:cubic-bezier(.4, 0, .2, 1);--button-ease-bounce:cubic-bezier(.34, 1.56, .64, 1);--accent:#3d5fc4;--accent-strong:#2e4aa0;--accent-soft:#e2e7f8;--ink-muted:#647089;--shadow-1:0 1px 2px #0f172a14, 0 1px 3px #0f172a0f;--shadow-2:0 4px 12px #0f172a1f}.theme-dark{--primary-bg:#222;--primary-border:#444;--primary-font:1rem;--font-family:"Inter", Arial, sans-serif;--primary-hover-bg:#333;--modal-bg:#222;--modal-title-color:#fff;--input-bg:#333;--input-border:#555;--input-font:1rem;--button-bg:#6f9cf7;--button-bg-hover:#86aefc;--button-color:#fff;--accent:#6f9cf7;--accent-strong:#86aefc;--accent-soft:#6f9cf72e;--ink-muted:#9aa3b5;--shadow-1:0 1px 2px #0000004d, 0 1px 3px #0000003d;--shadow-2:0 4px 12px #0006}.sg-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family);align-items:center;gap:6px;display:flex}.sg-toggle-input{opacity:0;width:1px;height:1px;position:absolute}.sg-toggle-track{background:var(--input-border);border-radius:999px;flex:none;width:34px;height:20px;transition:background .15s cubic-bezier(.4,0,.2,1);position:relative}.sg-toggle-input:checked+.sg-toggle-track{background:var(--accent)}.sg-toggle-thumb{background:var(--input-bg);width:16px;height:16px;box-shadow:var(--shadow-1);border-radius:50%;transition:left .15s cubic-bezier(.4,0,.2,1);position:absolute;top:2px;left:2px}.sg-toggle-input:checked+.sg-toggle-track .sg-toggle-thumb{left:16px}.sg-toggle-input:focus-visible+.sg-toggle-track{outline:2px solid var(--accent-strong);outline-offset:2px}.sg-toggle-label{color:var(--ink-muted);white-space:nowrap;font-size:13px}
1
+ .custom-button{border-radius:var(--button-radius);background:var(--button-bg);color:var(--button-color);cursor:pointer;font-size:var(--primary-font);font-weight:600;font-family:var(--font-family);box-shadow:var(--button-shadow);transition:background .15s var(--button-ease-standard), transform var(--button-ease-bounce) .2s;border:none;padding:8px 20px}.custom-button:hover:not(:disabled){background:var(--button-bg-hover);transform:translateY(-1px)}.custom-button:active:not(:disabled){transform:scale(.97)}.custom-button:disabled{opacity:.6;cursor:default}.custom-button-with-icon{align-items:center;gap:8px;display:inline-flex}.custom-button-label-visually-hidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.sg-icon{vertical-align:middle;flex-shrink:0;display:inline-block}.footer{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;justify-content:space-between;align-items:center;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.footer a{color:#1ea7fd;text-decoration:none}.footer a:hover{text-decoration:underline}.cookie-consent{background-color:var(--primary-bg);border-top:1px solid var(--primary-border);font-family:var(--font-family);color:#555;z-index:1000;box-sizing:border-box;flex-wrap:wrap;justify-content:center;align-items:center;gap:16px;width:100%;padding:16px 32px;font-size:14px;display:flex;position:fixed;bottom:0;left:0}.cookie-consent-text{flex:320px;margin:0}.cookie-consent a{color:#1ea7fd;text-decoration:none}.cookie-consent a:hover{text-decoration:underline}.cookie-consent-accept{flex:none}.logo-text{font-size:var(--font-size-h1);font-family:var(--font-family);margin:0;font-weight:400}.header{z-index:100;width:100%;font-size:var(--font-size);background-color:#fff;border-bottom:1px solid #e1e5e9;position:sticky;top:0;box-shadow:0 2px 4px #0000001a}.header-container{justify-content:flex-start;align-items:center;max-width:1200px;margin:0 auto;padding:16px;display:flex}.header-actions{align-items:center;gap:12px;margin-left:auto;display:flex}.logo{cursor:pointer;color:#333;font-size:24px;font-weight:700;transition:color .2s}.logo:hover{color:#007acc}.logo-full{display:inline}.logo-short{display:none}@media (width<=768px){.header-container{padding:12px 16px}.logo{font-size:var(--font-size)}.logo-full{display:none}.logo-short{display:inline}}@media (width<=480px){.header-container{padding:8px 12px}.logo{font-size:var(--font-size)}}.sg-access-gate{z-index:998;box-sizing:border-box;background:var(--primary-bg);font-family:var(--font-family);justify-content:center;align-items:center;padding:16px;display:flex;position:fixed;inset:0}.sg-access-gate-card{border:1px solid var(--primary-border);border-radius:calc(var(--radius) * 3);background:var(--modal-bg);max-width:420px;box-shadow:var(--shadow-2);text-align:center;padding:24px}.sg-access-gate-card h2{font-size:var(--font-size-h1);color:var(--modal-title-color);margin:0 0 12px}.sg-access-gate-card p{color:var(--ink-muted);margin:0 0 16px}.sg-access-gate-card .sg-access-gate-error{color:#c0392b}.sg-app-launcher{font-family:var(--font-family);position:relative}.sg-app-launcher-toggle{width:40px;height:40px;color:var(--ink-muted);cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;padding:0;display:inline-flex}.sg-app-launcher-toggle:hover,.sg-app-launcher-toggle[aria-expanded=true]{background:var(--primary-hover-bg)}.sg-app-launcher-panel{z-index:1000;box-sizing:border-box;border:1px solid var(--primary-border);border-radius:calc(var(--radius) * 3);background:var(--modal-bg);width:320px;max-width:calc(100vw - 24px);max-height:70vh;box-shadow:var(--shadow-2);padding:12px;position:absolute;top:calc(100% + 8px);right:0;overflow-y:auto}.sg-app-launcher-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;margin:0;padding:0;list-style:none;display:grid}.sg-app-launcher-app{border-radius:var(--radius);color:inherit;flex-direction:column;align-items:center;gap:6px;padding:12px 4px;text-decoration:none;display:flex}.sg-app-launcher-app:hover,.sg-app-launcher-app:focus-visible{background:var(--primary-hover-bg)}.sg-app-launcher-app.current{background:var(--accent-soft)}.sg-app-launcher-tile{border-radius:var(--radius);background:var(--accent);color:#fff;justify-content:center;align-items:center;width:40px;height:40px;font-size:18px;font-weight:600;display:flex}.sg-app-launcher-name{text-overflow:ellipsis;white-space:nowrap;max-width:100%;font-size:13px;overflow:hidden}.sg-app-launcher-message{color:var(--ink-muted);margin:0;padding:8px;font-size:13px}.sg-authenticator-button{font-size:.9rem;font-family:var(--font-family);border:1px solid var(--primary-border);border-radius:var(--radius);background:var(--primary-bg);color:#333;cursor:pointer;padding:.4rem 1rem;transition:background .15s,border-color .15s}.sg-authenticator-button:hover{background:var(--primary-hover-bg);border-color:var(--ink-muted)}.modal-overlay{background:var(--modal-overlay);z-index:1000;justify-content:center;align-items:center;width:100vw;height:100vh;animation:.25s ease-out sg-modal-overlay-fade-in;display:flex;position:fixed;top:0;left:0}.modal-overlay.modal-overlay-closing{animation:.22s ease-in forwards sg-modal-overlay-fade-out}.modal-content{--drag-x:0px;--drag-y:0px;background:var(--modal-bg);border-radius:var(--primary-radius);font-size:var(--primary-font);min-width:320px;max-width:calc(100vw - 40px);max-height:90vh;transform:translate(var(--drag-x), var(--drag-y));flex-direction:column;animation:.3s ease-out sg-modal-slide-in;display:flex;overflow:hidden;box-shadow:0 2px 16px #00000026}.modal-content.modal-content-closing{animation:.22s ease-in forwards sg-modal-slide-out}@keyframes sg-modal-overlay-fade-in{0%{opacity:0}to{opacity:1}}@keyframes sg-modal-overlay-fade-out{0%{opacity:1}to{opacity:0}}@keyframes sg-modal-slide-in{0%{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}to{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}}@keyframes sg-modal-slide-out{0%{transform:translate(var(--drag-x), var(--drag-y)) scale(1);opacity:1}to{transform:translate(var(--drag-x), calc(var(--drag-y) - 24px)) scale(.97);opacity:0}}.modal-header{background:var(--primary-bg);border-top-left-radius:var(--primary-radius);border-top-right-radius:var(--primary-radius);cursor:grab;touch-action:none;flex:none;align-items:center;gap:8px;padding:16px;display:flex}.modal-header-dragging{cursor:grabbing;-webkit-user-select:none;user-select:none}.modal-icon{color:var(--modal-title-color);display:inline-flex}.modal-title{color:var(--modal-title-color);font-family:var(--font-family);font-size:var(--primary-font);flex:1;margin:0}.modal-close{cursor:pointer;color:var(--modal-title-color);background:0 0;border:none;padding:4px 8px;font-size:20px;line-height:1}.modal-close:disabled{cursor:default;opacity:.6}.modal-children{font-family:var(--font-family);padding:16px;overflow-y:auto}.modal-footer{border-top:1px solid var(--primary-border);flex-wrap:wrap;flex:none;justify-content:flex-end;gap:8px;padding:12px 16px;display:flex}.input-label{font-weight:500;font-family:var(--font-family);font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field--invalid{background-color:#ffe5e5;border-color:#c00}.input-wrapper{margin-bottom:16px}.input-label{font-weight:500;font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field{box-sizing:border-box;border-radius:var(--radius);width:100%;font-size:var(--primary-font);border-style:solid;border-width:1px;padding:8px}.login-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.header.quadrato-header{z-index:999}.quadrato-header-auth{align-items:center;gap:12px;display:flex}.quadrato-header-username{font-size:var(--font-size);color:#333;transition:color .2s}.quadrato-header-username:hover{color:var(--accent)}form{font-family:var(--font-family)}.set-password-modal-form{font-family:var(--font-family);font-size:var(--primary-font);flex-direction:column;gap:16px;display:flex}.set-password-modal-error{color:#d32f2f;font-size:var(--primary-font);margin:0}.sg-color-picker{font-family:var(--font-family);position:relative}.sg-color-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-family:inherit;font-size:13px;display:flex}.sg-color-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-color-picker-swatch{border:1px solid #00000026;border-radius:4px;flex:none;width:18px;height:18px}.sg-color-picker-popover{z-index:30;background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);box-shadow:var(--shadow-1);width:170px;padding:10px;position:absolute;top:calc(100% + 4px);left:0}.sg-color-picker-grid{grid-template-columns:repeat(6,1fr);gap:6px;display:grid}.sg-color-picker-swatch-button{cursor:pointer;border:1px solid #00000026;border-radius:4px;width:20px;height:20px;padding:0}.sg-color-picker-swatch-button.active{border:2px solid var(--accent)}.sg-color-picker-custom{border-top:1px solid var(--input-border);color:var(--ink-muted);cursor:pointer;justify-content:space-between;align-items:center;gap:8px;margin-top:8px;padding-top:8px;font-size:11px;display:flex}.sg-color-picker-custom input[type=color]{cursor:pointer;border:none;width:26px;height:20px;padding:0}.sg-font-picker{font-family:var(--font-family);position:relative}.sg-font-picker-toggle{border-radius:var(--input-radius);border:1px solid var(--input-border);background:var(--input-bg);width:100%;color:inherit;cursor:pointer;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:13px;display:flex}.sg-font-picker-toggle-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.sg-font-picker-toggle-caret{opacity:.5;flex:none;font-size:10px}.sg-font-picker-list{background:var(--input-bg);border:1px solid var(--input-border);border-radius:var(--input-radius);max-height:260px;box-shadow:var(--shadow-1);z-index:30;margin:0;padding:4px 0;list-style:none;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto}.sg-font-picker-option{text-align:left;width:100%;color:inherit;cursor:pointer;background:0 0;border:none;padding:8px 10px;font-size:15px;display:block}.sg-font-picker-option.active{background:var(--accent-soft)}:root{--unit:3px;--primary-bg:#f5f5f5;--primary-border:#ccc;--radius:calc(var(--unit) * 2);--primary-radius:var(--radius);--primary-font:var(--font-size);--primary-hover-bg:#e0e0e0;--modal-bg:#fff;--modal-overlay:#0000004d;--modal-title-color:#222;--input-bg:#fff;--input-border:#ccc;--input-radius:var(--radius);--input-font:1rem;--font-size:14px;--font-family:Arial, sans-serif;--font-size-h1:calc(var(--font-size) * 1.5);--button-bg:#6f9cf7;--button-bg-hover:#5480e6;--button-color:#fff;--button-radius:999px;--button-shadow:0 1px 2px #5480e61f, 0 1px 3px #5480e61a;--button-ease-standard:cubic-bezier(.4, 0, .2, 1);--button-ease-bounce:cubic-bezier(.34, 1.56, .64, 1);--accent:#3d5fc4;--accent-strong:#2e4aa0;--accent-soft:#e2e7f8;--ink-muted:#647089;--shadow-1:0 1px 2px #0f172a14, 0 1px 3px #0f172a0f;--shadow-2:0 4px 12px #0f172a1f}.theme-dark{--primary-bg:#222;--primary-border:#444;--primary-font:1rem;--font-family:"Inter", Arial, sans-serif;--primary-hover-bg:#333;--modal-bg:#222;--modal-title-color:#fff;--input-bg:#333;--input-border:#555;--input-font:1rem;--button-bg:#6f9cf7;--button-bg-hover:#86aefc;--button-color:#fff;--accent:#6f9cf7;--accent-strong:#86aefc;--accent-soft:#6f9cf72e;--ink-muted:#9aa3b5;--shadow-1:0 1px 2px #0000004d, 0 1px 3px #0000003d;--shadow-2:0 4px 12px #0006}.sg-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family);align-items:center;gap:6px;display:flex}.sg-toggle-input{opacity:0;width:1px;height:1px;position:absolute}.sg-toggle-track{background:var(--input-border);border-radius:999px;flex:none;width:34px;height:20px;transition:background .15s cubic-bezier(.4,0,.2,1);position:relative}.sg-toggle-input:checked+.sg-toggle-track{background:var(--accent)}.sg-toggle-thumb{background:var(--input-bg);width:16px;height:16px;box-shadow:var(--shadow-1);border-radius:50%;transition:left .15s cubic-bezier(.4,0,.2,1);position:absolute;top:2px;left:2px}.sg-toggle-input:checked+.sg-toggle-track .sg-toggle-thumb{left:16px}.sg-toggle-input:focus-visible+.sg-toggle-track{outline:2px solid var(--accent-strong);outline-offset:2px}.sg-toggle-label{color:var(--ink-muted);white-space:nowrap;font-size:13px}
2
2
  /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sensorario/sg-components",
3
- "version": "0.0.100",
3
+ "version": "0.0.102",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "scripts": {