@sensorario/sg-components 0.0.105 → 0.0.107

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
+ export declare const ACCESS_TOKEN_COOKIE = "simonegentili.com-access-token";
2
+ /** `domain` and `secure` only where the browser honors them: otherwise it drops the whole cookie (e.g. http://localhost). */
3
+ export declare const cookieScope: () => string;
4
+ export declare const writeCookie: (name: string, value: string, maxAgeSeconds: number, sameSite?: "strict" | "lax") => void;
5
+ /** The JWT shared by every .simonegentili.com app, or null when logged out. */
6
+ export declare const getAccessToken: (cookieName?: string) => string | null;
7
+ export declare const setAccessToken: (token: string, maxAgeSeconds?: number, cookieName?: string) => void;
8
+ export declare const clearAccessToken: (cookieName?: string) => void;
9
+ /** Reads one claim of the token payload without verifying it (the API does that). Default: the username. */
10
+ export declare const getTokenClaim: (token?: string | null, claim?: string) => string | null;
@@ -5,6 +5,10 @@ export type LauncherApp = {
5
5
  url: string;
6
6
  /** Not granted to the logged-in user: opening it shows AppAccessGate's "Richiedi accesso". */
7
7
  locked?: boolean;
8
+ /** Tile background, set from Heimdall's "App" page. */
9
+ color?: string | null;
10
+ /** One of LOGOS' keys, drawn instead of the initial. */
11
+ icon?: string | null;
8
12
  };
9
13
  interface AppLauncherProps {
10
14
  /** Endpoint returning `{ apps: LauncherApp[] }` - the enabled apps, managed from Heimdall. */
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from 'react';
2
+ import './AuthPage.css';
3
+ interface AuthPageProps {
4
+ title: ReactNode;
5
+ children?: ReactNode;
6
+ /** Links under the card, e.g. back to the home page (router-specific, so the app passes it). */
7
+ footer?: ReactNode;
8
+ className?: string;
9
+ }
10
+ export declare const AuthPage: ({ title, children, footer, className }: AuthPageProps) => import("react/jsx-runtime").JSX.Element;
11
+ export default AuthPage;
@@ -0,0 +1,8 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { AuthPage } from './AuthPage';
3
+ declare const meta: Meta<typeof AuthPage>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AuthPage>;
6
+ export declare const Register: Story;
7
+ export declare const RegisterError: Story;
8
+ export declare const Registered: Story;
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+ import './LoginPrompt.css';
3
+ interface LoginPromptProps {
4
+ /** What logging in unlocks, e.g. "Accedi per vedere le sessioni." */
5
+ children?: ReactNode;
6
+ /** Shows a login button, e.g. `() => headerRef.current?.openLoginModal()`. */
7
+ onLogin?: () => void;
8
+ /** Extra content under the button, e.g. a link to the registration page. */
9
+ footer?: ReactNode;
10
+ className?: string;
11
+ }
12
+ export declare const LoginPrompt: ({ children, onLogin, footer, className }: LoginPromptProps) => import("react/jsx-runtime").JSX.Element;
13
+ export default LoginPrompt;
@@ -0,0 +1,8 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { LoginPrompt } from './LoginPrompt';
3
+ declare const meta: Meta<typeof LoginPrompt>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof LoginPrompt>;
6
+ export declare const TextOnly: Story;
7
+ export declare const WithButton: Story;
8
+ export declare const WithRegisterLink: Story;
@@ -0,0 +1,12 @@
1
+ import { type LogoKey } from './logos';
2
+ interface LogoProps {
3
+ name: LogoKey;
4
+ size?: number;
5
+ /** Defaults to the text color around it. */
6
+ color?: string;
7
+ /** Accessible name; without it the logo is decorative. */
8
+ title?: string;
9
+ className?: string;
10
+ }
11
+ export declare const Logo: ({ name, size, color, title, className }: LogoProps) => import("react/jsx-runtime").JSX.Element;
12
+ export default Logo;
@@ -0,0 +1,5 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Logo } from './Logo';
3
+ declare const meta: Meta<typeof Logo>;
4
+ export default meta;
5
+ export declare const All: StoryObj<typeof Logo>;
@@ -0,0 +1,7 @@
1
+ export type LogoKey = "react" | "nextjs" | "keyboard" | "mouse" | "terminal" | "lightbulb" | "joystick" | "dice" | "robot" | "cpu" | "sparkles" | "brain" | "person";
2
+ export declare const LOGOS: Record<LogoKey, {
3
+ label: string;
4
+ viewBox: [number, number, number, number];
5
+ path: string;
6
+ }>;
7
+ export declare const isLogoKey: (value: unknown) => value is LogoKey;
@@ -0,0 +1,9 @@
1
+ import './RegisterForm.css';
2
+ interface RegisterFormProps {
3
+ /** Calls the app's register endpoint; a thrown Error's message is shown to the user. */
4
+ onRegister: (email: string) => Promise<void>;
5
+ /** Called after a successful registration instead of showing the "check your email" message, e.g. to navigate. */
6
+ onRegistered?: (email: string) => void;
7
+ }
8
+ export declare const RegisterForm: ({ onRegister, onRegistered }: RegisterFormProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default RegisterForm;
@@ -0,0 +1,8 @@
1
+ import './VersionNumber.css';
2
+ interface VersionNumberProps {
3
+ /** Usually the app's own __APP_VERSION__, defined in its vite.config. */
4
+ version: string;
5
+ className?: string;
6
+ }
7
+ export declare const VersionNumber: ({ version, className }: VersionNumberProps) => import("react/jsx-runtime").JSX.Element;
8
+ export default VersionNumber;
@@ -0,0 +1,5 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { VersionNumber } from './VersionNumber';
3
+ declare const meta: Meta<typeof VersionNumber>;
4
+ export default meta;
5
+ export declare const Default: StoryObj<typeof VersionNumber>;
package/dist/index.d.ts CHANGED
@@ -31,3 +31,10 @@ export * from './components/Select/Select';
31
31
  export * from './components/FormField/FormField';
32
32
  export * from './components/Tabs/Tabs';
33
33
  import './components/Table/Table.css';
34
+ export * from './components/VersionNumber/VersionNumber';
35
+ export * from './components/LoginPrompt/LoginPrompt';
36
+ export * from './components/AuthPage/AuthPage';
37
+ export * from './components/RegisterForm/RegisterForm';
38
+ export { ACCESS_TOKEN_COOKIE, getAccessToken, setAccessToken, clearAccessToken, getTokenClaim } from './auth';
39
+ export * from './components/Logo/Logo';
40
+ export * from './components/Logo/logos';
package/dist/index.es.js CHANGED
@@ -357,7 +357,19 @@ var w = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
357
357
  onNavigate: e,
358
358
  title: "Simone Gentili - senior web developer, tech author and chess enthusiast",
359
359
  homePageKey: "home"
360
- }), k = {
360
+ }), k = "simonegentili.com-access-token", ee = (e) => document.cookie.split("; ").find((t) => t.startsWith(`${e}=`))?.slice(e.length + 1) || null, te = () => (window.location.hostname.endsWith("simonegentili.com") ? "; domain=.simonegentili.com" : "") + (window.location.protocol === "https:" ? "; secure" : ""), A = (e, t, n, r = "strict") => {
361
+ document.cookie = `${e}=${t}; path=/; max-age=${n}; samesite=${r}${te()}`;
362
+ }, j = (e = k) => ee(e), ne = (e, t = 168 * 3600, n = k) => A(n, e, t), re = (e = k) => {
363
+ A(e, "", 0), document.cookie = `${e}=; path=/; max-age=0`;
364
+ }, M = (e = j(), t = "sub") => {
365
+ if (!e) return null;
366
+ try {
367
+ let n = JSON.parse(atob(e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/")));
368
+ return typeof n[t] == "string" ? n[t] : null;
369
+ } catch {
370
+ return null;
371
+ }
372
+ }, ie = {
361
373
  auth: {
362
374
  login: "Accedi",
363
375
  logout: "Esci",
@@ -394,8 +406,18 @@ var w = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
394
406
  confirm: {
395
407
  confirm: "Conferma",
396
408
  cancel: "Annulla"
409
+ },
410
+ version: { label: "Versione" },
411
+ loginPrompt: { message: "Accedi per continuare." },
412
+ register: {
413
+ title: "Registrati",
414
+ email: "Email",
415
+ placeholder: "La tua email",
416
+ submit: "Registrati",
417
+ sending: "Invio…",
418
+ sent: "Controlla la tua email: ti abbiamo inviato un link per completare la registrazione."
397
419
  }
398
- }, ee = {
420
+ }, ae = {
399
421
  auth: {
400
422
  login: "Log in",
401
423
  logout: "Log out",
@@ -432,8 +454,18 @@ var w = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
432
454
  confirm: {
433
455
  confirm: "Confirm",
434
456
  cancel: "Cancel"
457
+ },
458
+ version: { label: "Version" },
459
+ loginPrompt: { message: "Log in to continue." },
460
+ register: {
461
+ title: "Sign up",
462
+ email: "Email",
463
+ placeholder: "Your email",
464
+ submit: "Sign up",
465
+ sending: "Sending…",
466
+ sent: "Check your email: we sent you a link to complete your registration."
435
467
  }
436
- }, te = {
468
+ }, oe = {
437
469
  auth: {
438
470
  login: "Se connecter",
439
471
  logout: "Se déconnecter",
@@ -470,8 +502,18 @@ var w = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
470
502
  confirm: {
471
503
  confirm: "Confirmer",
472
504
  cancel: "Annuler"
505
+ },
506
+ version: { label: "Version" },
507
+ loginPrompt: { message: "Connectez-vous pour continuer." },
508
+ register: {
509
+ title: "S’inscrire",
510
+ email: "E-mail",
511
+ placeholder: "Votre e-mail",
512
+ submit: "S’inscrire",
513
+ sending: "Envoi…",
514
+ sent: "Consultez votre e-mail : nous vous avons envoyé un lien pour terminer l’inscription."
473
515
  }
474
- }, ne = {
516
+ }, se = {
475
517
  auth: {
476
518
  login: "Anmelden",
477
519
  logout: "Abmelden",
@@ -508,8 +550,18 @@ var w = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
508
550
  confirm: {
509
551
  confirm: "Bestätigen",
510
552
  cancel: "Abbrechen"
553
+ },
554
+ version: { label: "Version" },
555
+ loginPrompt: { message: "Melde dich an, um fortzufahren." },
556
+ register: {
557
+ title: "Registrieren",
558
+ email: "E-Mail",
559
+ placeholder: "Deine E-Mail",
560
+ submit: "Registrieren",
561
+ sending: "Wird gesendet…",
562
+ sent: "Prüfe deine E-Mails: Wir haben dir einen Link zum Abschließen der Registrierung geschickt."
511
563
  }
512
- }, re = {
564
+ }, ce = {
513
565
  auth: {
514
566
  login: "Iniciar sesión",
515
567
  logout: "Cerrar sesión",
@@ -546,8 +598,18 @@ var w = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
546
598
  confirm: {
547
599
  confirm: "Confirmar",
548
600
  cancel: "Cancelar"
601
+ },
602
+ version: { label: "Versión" },
603
+ loginPrompt: { message: "Inicia sesión para continuar." },
604
+ register: {
605
+ title: "Registrarse",
606
+ email: "Correo electrónico",
607
+ placeholder: "Tu correo electrónico",
608
+ submit: "Registrarse",
609
+ sending: "Enviando…",
610
+ sent: "Revisa tu correo: te hemos enviado un enlace para completar el registro."
549
611
  }
550
- }, A = {
612
+ }, le = {
551
613
  auth: {
552
614
  login: "ログイン",
553
615
  logout: "ログアウト",
@@ -584,57 +646,64 @@ var w = ({ privacyPolicyHref: e = "https://simonegentili.com/privacy" }) => {
584
646
  confirm: {
585
647
  confirm: "確認",
586
648
  cancel: "キャンセル"
649
+ },
650
+ version: { label: "バージョン" },
651
+ loginPrompt: { message: "続行するにはログインしてください。" },
652
+ register: {
653
+ title: "新規登録",
654
+ email: "メールアドレス",
655
+ placeholder: "メールアドレス",
656
+ submit: "登録する",
657
+ sending: "送信中…",
658
+ sent: "メールを確認してください。登録を完了するためのリンクを送信しました。"
587
659
  }
588
- }, j = [
660
+ }, N = [
589
661
  "it",
590
662
  "en",
591
663
  "fr",
592
664
  "de",
593
665
  "es",
594
666
  "ja"
595
- ], M = {
667
+ ], P = {
596
668
  it: "Italiano",
597
669
  en: "English",
598
670
  fr: "Français",
599
671
  de: "Deutsch",
600
672
  es: "Español",
601
673
  ja: "日本語"
602
- }, N = "sg-language", P = "it", F = (e) => !!e && j.includes(e), I = () => {
603
- let e = document.cookie.split("; ").find((e) => e.startsWith(`${N}=`))?.slice(12);
604
- return F(e) ? e : null;
605
- }, ie = (e) => {
606
- let t = window.location.hostname.endsWith("simonegentili.com") ? "; domain=.simonegentili.com; secure" : "";
607
- document.cookie = `${N}=${e}; path=/; max-age=31536000; samesite=lax${t}`;
608
- }, L = h.createInstance();
609
- L.init({
674
+ }, F = "sg-language", I = "it", ue = (e) => !!e && N.includes(e), L = () => {
675
+ let e = document.cookie.split("; ").find((e) => e.startsWith(`${F}=`))?.slice(12);
676
+ return ue(e) ? e : null;
677
+ }, de = (e) => A(F, e, 31536e3, "lax"), R = h.createInstance();
678
+ R.init({
610
679
  resources: {
611
- it: { sg: k },
612
- en: { sg: ee },
613
- fr: { sg: te },
614
- de: { sg: ne },
615
- es: { sg: re },
616
- ja: { sg: A }
680
+ it: { sg: ie },
681
+ en: { sg: ae },
682
+ fr: { sg: oe },
683
+ de: { sg: se },
684
+ es: { sg: ce },
685
+ ja: { sg: le }
617
686
  },
618
- lng: I() ?? P,
619
- fallbackLng: P,
620
- supportedLngs: [...j],
687
+ lng: L() ?? I,
688
+ fallbackLng: I,
689
+ supportedLngs: [...N],
621
690
  ns: ["sg", "translation"],
622
691
  defaultNS: "translation",
623
692
  initAsync: !1,
624
693
  interpolation: { escapeValue: !1 }
625
- }), L.on("languageChanged", ie);
626
- var ae = ({ resources: e }) => {
627
- for (let [t, n] of Object.entries(e)) L.addResourceBundle(t, "translation", n, !0, !0);
628
- return p(L), L;
629
- }, R = "https://api.simonegentili.com/heimdall", z = (e) => e.endsWith("/") ? e : `${e}/`, oe = (e) => {
630
- let t = z(window.location.origin + window.location.pathname);
631
- return e.filter((e) => t.startsWith(z(e.url))).sort((e, t) => t.url.length - e.url.length)[0] ?? null;
632
- }, B = ({ token: e, heimdallUrl: t = R }) => {
633
- let { t: n } = m("sg", { i18n: L }), [r, i] = l(null), [o, s] = l(!1), [c, p] = l(!1);
694
+ }), R.on("languageChanged", de);
695
+ var fe = ({ resources: e }) => {
696
+ for (let [t, n] of Object.entries(e)) R.addResourceBundle(t, "translation", n, !0, !0);
697
+ return p(R), R;
698
+ }, z = "https://api.simonegentili.com/heimdall", B = (e) => e.endsWith("/") ? e : `${e}/`, pe = (e) => {
699
+ let t = B(window.location.origin + window.location.pathname);
700
+ return e.filter((e) => t.startsWith(B(e.url))).sort((e, t) => t.url.length - e.url.length)[0] ?? null;
701
+ }, V = ({ token: e, heimdallUrl: t = z }) => {
702
+ let { t: n } = m("sg", { i18n: R }), [r, i] = l(null), [o, s] = l(!1), [c, p] = l(!1);
634
703
  a(() => {
635
704
  e && fetch(`${t}/access`, { headers: { Authorization: `Bearer ${e}` } }).then((e) => e.ok ? e.json() : Promise.reject(e.status)).then((t) => i({
636
705
  token: e,
637
- app: oe(t.apps)
706
+ app: pe(t.apps)
638
707
  })).catch(() => i({
639
708
  token: e,
640
709
  app: null
@@ -688,8 +757,152 @@ var ae = ({ resources: e }) => {
688
757
  ] })]
689
758
  })
690
759
  });
691
- }, V = "https://api.simonegentili.com/heimdall/launcher", H = ({ appsUrl: e = V, label: t, token: n = null }) => {
692
- let { t: r } = m("sg", { i18n: L }), i = t ?? r("launcher.label"), [o, s] = l(!1), [u, p] = l(null), h = u?.token === n ? u.apps : null, [g, v] = l(!1), y = c(null);
760
+ }, H = {
761
+ react: {
762
+ label: "React",
763
+ viewBox: [
764
+ 0,
765
+ 0,
766
+ 24,
767
+ 24
768
+ ],
769
+ path: "M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z"
770
+ },
771
+ nextjs: {
772
+ label: "Next.js",
773
+ viewBox: [
774
+ 0,
775
+ 0,
776
+ 24,
777
+ 24
778
+ ],
779
+ path: "M18.665 21.978C16.758 23.255 14.465 24 12 24 5.377 24 0 18.623 0 12S5.377 0 12 0s12 5.377 12 12c0 3.583-1.574 6.801-4.067 9.001L9.219 7.2H7.2v9.596h1.615V9.251l9.85 12.727Zm-3.332-8.533 1.6 2.061V7.2h-1.6v6.245Z"
780
+ },
781
+ keyboard: {
782
+ label: "Tastiera",
783
+ viewBox: [
784
+ 0,
785
+ 0,
786
+ 16,
787
+ 16
788
+ ],
789
+ path: "M0 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm13 .25v.5c0 .138.112.25.25.25h.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25h-.5a.25.25 0 0 0-.25.25M2.25 8a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h.5A.25.25 0 0 0 3 8.75v-.5A.25.25 0 0 0 2.75 8zM4 8.25v.5c0 .138.112.25.25.25h.5A.25.25 0 0 0 5 8.75v-.5A.25.25 0 0 0 4.75 8h-.5a.25.25 0 0 0-.25.25M6.25 8a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h.5A.25.25 0 0 0 7 8.75v-.5A.25.25 0 0 0 6.75 8zM8 8.25v.5c0 .138.112.25.25.25h.5A.25.25 0 0 0 9 8.75v-.5A.25.25 0 0 0 8.75 8h-.5a.25.25 0 0 0-.25.25M13.25 8a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25zm0 2a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25zm-3-2a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h1.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25zm.75 2.25v.5c0 .138.112.25.25.25h.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25h-.5a.25.25 0 0 0-.25.25M11.25 6a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25zM9 6.25v.5c0 .138.112.25.25.25h.5a.25.25 0 0 0 .25-.25v-.5A.25.25 0 0 0 9.75 6h-.5a.25.25 0 0 0-.25.25M7.25 6a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h.5A.25.25 0 0 0 8 6.75v-.5A.25.25 0 0 0 7.75 6zM5 6.25v.5c0 .138.112.25.25.25h.5A.25.25 0 0 0 6 6.75v-.5A.25.25 0 0 0 5.75 6h-.5a.25.25 0 0 0-.25.25M2.25 6a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h1.5A.25.25 0 0 0 4 6.75v-.5A.25.25 0 0 0 3.75 6zM2 10.25v.5c0 .138.112.25.25.25h.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25h-.5a.25.25 0 0 0-.25.25M4.25 10a.25.25 0 0 0-.25.25v.5c0 .138.112.25.25.25h5.5a.25.25 0 0 0 .25-.25v-.5a.25.25 0 0 0-.25-.25z"
790
+ },
791
+ mouse: {
792
+ label: "Mouse",
793
+ viewBox: [
794
+ 0,
795
+ 0,
796
+ 16,
797
+ 16
798
+ ],
799
+ path: "M3 5a5 5 0 0 1 10 0v6a5 5 0 0 1-10 0zm5.5-1.5a.5.5 0 0 0-1 0v2a.5.5 0 0 0 1 0z"
800
+ },
801
+ terminal: {
802
+ label: "Terminale",
803
+ viewBox: [
804
+ 0,
805
+ 0,
806
+ 16,
807
+ 16
808
+ ],
809
+ path: "M0 3a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2zm9.5 5.5h-3a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1m-6.354-.354a.5.5 0 1 0 .708.708l2-2a.5.5 0 0 0 0-.708l-2-2a.5.5 0 1 0-.708.708L4.793 6.5z"
810
+ },
811
+ lightbulb: {
812
+ label: "Lampadina",
813
+ viewBox: [
814
+ 0,
815
+ 0,
816
+ 16,
817
+ 16
818
+ ],
819
+ path: "M2 6a6 6 0 1 1 10.174 4.31c-.203.196-.359.4-.453.619l-.762 1.769A.5.5 0 0 1 10.5 13h-5a.5.5 0 0 1-.46-.302l-.761-1.77a2 2 0 0 0-.453-.618A5.98 5.98 0 0 1 2 6m3 8.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1l-.224.447a1 1 0 0 1-.894.553H6.618a1 1 0 0 1-.894-.553L5.5 15a.5.5 0 0 1-.5-.5"
820
+ },
821
+ joystick: {
822
+ label: "Joystick",
823
+ viewBox: [
824
+ 0,
825
+ 0,
826
+ 16,
827
+ 16
828
+ ],
829
+ path: "M10 2a2 2 0 0 1-1.5 1.937v5.087c.863.083 1.5.377 1.5.726 0 .414-.895.75-2 .75s-2-.336-2-.75c0-.35.637-.643 1.5-.726V3.937A2 2 0 1 1 10 2 M0 9.665v1.717a1 1 0 0 0 .553.894l6.553 3.277a2 2 0 0 0 1.788 0l6.553-3.277a1 1 0 0 0 .553-.894V9.665c0-.1-.06-.19-.152-.23L9.5 6.715v.993l5.227 2.178a.125.125 0 0 1 .001.23l-5.94 2.546a2 2 0 0 1-1.576 0l-5.94-2.546a.125.125 0 0 1 .001-.23L6.5 7.708l-.013-.988L.152 9.435a.25.25 0 0 0-.152.23"
830
+ },
831
+ dice: {
832
+ label: "Dado",
833
+ viewBox: [
834
+ 0,
835
+ 0,
836
+ 16,
837
+ 16
838
+ ],
839
+ path: "M3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3zm2.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0M12 13.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3M5.5 12a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0M8 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3"
840
+ },
841
+ robot: {
842
+ label: "Robot",
843
+ viewBox: [
844
+ 0,
845
+ 0,
846
+ 16,
847
+ 16
848
+ ],
849
+ path: "M6 12.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5M3 8.062C3 6.76 4.235 5.765 5.53 5.886a26.6 26.6 0 0 0 4.94 0C11.765 5.765 13 6.76 13 8.062v1.157a.93.93 0 0 1-.765.935c-.845.147-2.34.346-4.235.346s-3.39-.2-4.235-.346A.93.93 0 0 1 3 9.219zm4.542-.827a.25.25 0 0 0-.217.068l-.92.9a25 25 0 0 1-1.871-.183.25.25 0 0 0-.068.495c.55.076 1.232.149 2.02.193a.25.25 0 0 0 .189-.071l.754-.736.847 1.71a.25.25 0 0 0 .404.062l.932-.97a25 25 0 0 0 1.922-.188.25.25 0 0 0-.068-.495c-.538.074-1.207.145-1.98.189a.25.25 0 0 0-.166.076l-.754.785-.842-1.7a.25.25 0 0 0-.182-.135 M8.5 1.866a1 1 0 1 0-1 0V3h-2A4.5 4.5 0 0 0 1 7.5V8a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1v1a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1v-.5A4.5 4.5 0 0 0 10.5 3h-2zM14 7.5V13a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7.5A3.5 3.5 0 0 1 5.5 4h5A3.5 3.5 0 0 1 14 7.5"
850
+ },
851
+ cpu: {
852
+ label: "Chip",
853
+ viewBox: [
854
+ 0,
855
+ 0,
856
+ 16,
857
+ 16
858
+ ],
859
+ path: "M6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5z M5.5.5a.5.5 0 0 0-1 0V2A2.5 2.5 0 0 0 2 4.5H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2v1H.5a.5.5 0 0 0 0 1H2A2.5 2.5 0 0 0 4.5 14v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14h1v1.5a.5.5 0 0 0 1 0V14a2.5 2.5 0 0 0 2.5-2.5h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14v-1h1.5a.5.5 0 0 0 0-1H14A2.5 2.5 0 0 0 11.5 2V.5a.5.5 0 0 0-1 0V2h-1V.5a.5.5 0 0 0-1 0V2h-1V.5a.5.5 0 0 0-1 0V2h-1zm1 4.5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3A1.5 1.5 0 0 1 6.5 5"
860
+ },
861
+ sparkles: {
862
+ label: "Scintille",
863
+ viewBox: [
864
+ 0,
865
+ 0,
866
+ 16,
867
+ 16
868
+ ],
869
+ path: "M7.657 6.247c.11-.33.576-.33.686 0l.645 1.937a2.89 2.89 0 0 0 1.829 1.828l1.936.645c.33.11.33.576 0 .686l-1.937.645a2.89 2.89 0 0 0-1.828 1.829l-.645 1.936a.361.361 0 0 1-.686 0l-.645-1.937a2.89 2.89 0 0 0-1.828-1.828l-1.937-.645a.361.361 0 0 1 0-.686l1.937-.645a2.89 2.89 0 0 0 1.828-1.828zM3.794 1.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387A1.73 1.73 0 0 0 4.593 5.69l-.387 1.162a.217.217 0 0 1-.412 0L3.407 5.69A1.73 1.73 0 0 0 2.31 4.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387A1.73 1.73 0 0 0 3.407 2.31zM10.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.16 1.16 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.16 1.16 0 0 0-.732-.732L9.1 2.137a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732z"
870
+ },
871
+ brain: {
872
+ label: "Cervello",
873
+ viewBox: [
874
+ 0,
875
+ 0,
876
+ 256,
877
+ 256
878
+ ],
879
+ path: "M212,76V72a44,44,0,0,0-74.86-31.31,3.93,3.93,0,0,0-1.14,2.8v88.72a4,4,0,0,0,6.2,3.33A47.67,47.67,0,0,1,167.68,128a8.18,8.18,0,0,1,8.31,7.58,8,8,0,0,1-8,8.42,32,32,0,0,0-32,32v33.88a4,4,0,0,0,1.49,3.12,47.92,47.92,0,0,0,74.21-17.16,4,4,0,0,0-4.49-5.56A68.06,68.06,0,0,1,192,192h-7.73a8.18,8.18,0,0,1-8.25-7.47,8,8,0,0,1,8-8.53h8a51.6,51.6,0,0,0,24-5.88v0A52,52,0,0,0,212,76Zm-12,36h-4a36,36,0,0,1-36-36V72a8,8,0,0,1,16,0v4a20,20,0,0,0,20,20h4a8,8,0,0,1,0,16ZM88,28A44.05,44.05,0,0,0,44,72v4a52,52,0,0,0-4,94.12h0A51.6,51.6,0,0,0,64,176h7.73A8.18,8.18,0,0,1,80,183.47,8,8,0,0,1,72,192H64a67.48,67.48,0,0,1-15.21-1.73,4,4,0,0,0-4.5,5.55A47.93,47.93,0,0,0,118.51,213a4,4,0,0,0,1.49-3.12V176a32,32,0,0,0-32-32,8,8,0,0,1-8-8.42A8.18,8.18,0,0,1,88.32,128a47.67,47.67,0,0,1,25.48,7.54,4,4,0,0,0,6.2-3.33V43.49a4,4,0,0,0-1.14-2.81A43.85,43.85,0,0,0,88,28Zm8,48a36,36,0,0,1-36,36H56a8,8,0,0,1,0-16h4A20,20,0,0,0,80,76V72a8,8,0,0,1,16,0Z"
880
+ },
881
+ person: {
882
+ label: "Persona",
883
+ viewBox: [
884
+ 0,
885
+ 0,
886
+ 16,
887
+ 16
888
+ ],
889
+ path: "M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6"
890
+ }
891
+ }, U = (e) => typeof e == "string" && Object.prototype.hasOwnProperty.call(H, e), W = ({ name: e, size: t = 24, color: n = "currentColor", title: r, className: i }) => {
892
+ let { viewBox: a, path: o } = H[e];
893
+ return /* @__PURE__ */ d("svg", {
894
+ className: ["sg-logo", i].filter(Boolean).join(" "),
895
+ width: t,
896
+ height: t,
897
+ viewBox: a.join(" "),
898
+ fill: n,
899
+ role: r ? "img" : void 0,
900
+ "aria-label": r,
901
+ "aria-hidden": r ? void 0 : !0,
902
+ children: /* @__PURE__ */ d("path", { d: o })
903
+ });
904
+ }, G = "https://api.simonegentili.com/heimdall/launcher", K = ({ appsUrl: e = G, label: t, token: n = null }) => {
905
+ let { t: r } = m("sg", { i18n: R }), i = t ?? r("launcher.label"), [o, s] = l(!1), [u, p] = l(null), h = u?.token === n ? u.apps : null, [g, v] = l(!1), y = c(null);
693
906
  return a(() => {
694
907
  !o || h !== null || fetch(e, n ? { headers: { Authorization: `Bearer ${n}` } } : void 0).then((e) => e.ok ? e.json() : Promise.reject(e.status)).then((e) => p({
695
908
  token: n,
@@ -747,7 +960,11 @@ var ae = ({ resources: e }) => {
747
960
  children: [/* @__PURE__ */ f("span", {
748
961
  className: "sg-app-launcher-tile",
749
962
  "aria-hidden": "true",
750
- children: [e.name.charAt(0).toUpperCase(), e.locked && /* @__PURE__ */ d("span", {
963
+ style: e.color ? { "--tile-bg": e.color } : void 0,
964
+ children: [U(e.icon) ? /* @__PURE__ */ d(W, {
965
+ name: e.icon,
966
+ size: 22
967
+ }) : e.name.charAt(0).toUpperCase(), e.locked && /* @__PURE__ */ d("span", {
751
968
  className: "sg-app-launcher-lock",
752
969
  children: /* @__PURE__ */ d(_, {
753
970
  name: "lock",
@@ -769,7 +986,7 @@ var ae = ({ resources: e }) => {
769
986
  })
770
987
  })]
771
988
  });
772
- }, U = ({ src: e, name: t, size: n = 32, className: r }) => {
989
+ }, q = ({ src: e, name: t, size: n = 32, className: r }) => {
773
990
  let i = ["sg-avatar", r].filter(Boolean).join(" "), a = { "--avatar-size": `${n}px` };
774
991
  return e ? /* @__PURE__ */ d("img", {
775
992
  className: i,
@@ -783,8 +1000,8 @@ var ae = ({ resources: e }) => {
783
1000
  "aria-label": t ?? void 0,
784
1001
  children: t?.trim().charAt(0).toUpperCase() || "?"
785
1002
  });
786
- }, W = ({ isLoggedIn: e, handleLogin: t, handleLogout: n }) => {
787
- let { t: r } = m("sg", { i18n: L });
1003
+ }, J = ({ isLoggedIn: e, handleLogin: t, handleLogout: n }) => {
1004
+ let { t: r } = m("sg", { i18n: R });
788
1005
  return /* @__PURE__ */ d(u, { children: e ? /* @__PURE__ */ d("button", {
789
1006
  onClick: n,
790
1007
  className: "sg-authenticator-button",
@@ -794,14 +1011,14 @@ var ae = ({ resources: e }) => {
794
1011
  className: "sg-authenticator-button",
795
1012
  children: r("auth.login")
796
1013
  }) });
797
- }, G = 220, K = ({ open: t, onClose: n, title: r, icon: i, children: o, buttons: s, footer: c, closeLabel: u, className: p }) => {
798
- let { t: h } = m("sg", { i18n: L }), [g, _] = l(!1), [y, b] = l({
1014
+ }, me = 220, Y = ({ open: t, onClose: n, title: r, icon: i, children: o, buttons: s, footer: c, closeLabel: u, className: p }) => {
1015
+ let { t: h } = m("sg", { i18n: R }), [g, _] = l(!1), [y, b] = l({
799
1016
  x: 0,
800
1017
  y: 0
801
1018
  }), x = e.useRef(null), [S, C] = l(!1), w = (e) => {
802
1019
  g || (_(!0), setTimeout(() => {
803
1020
  _(!1), e();
804
- }, G));
1021
+ }, me));
805
1022
  };
806
1023
  a(() => {
807
1024
  if (!t) return;
@@ -889,7 +1106,7 @@ var ae = ({ resources: e }) => {
889
1106
  ]
890
1107
  })
891
1108
  });
892
- }, q = ({ label: e, invalid: t, className: n, id: r, ...i }) => {
1109
+ }, he = ({ label: e, invalid: t, className: n, id: r, ...i }) => {
893
1110
  let a = o(), s = r ?? a;
894
1111
  return /* @__PURE__ */ f("div", {
895
1112
  className: "input-wrapper",
@@ -907,7 +1124,7 @@ var ae = ({ resources: e }) => {
907
1124
  ...i
908
1125
  })]
909
1126
  });
910
- }, J = ({ label: e, invalid: t, className: n, id: r, ...i }) => {
1127
+ }, X = ({ label: e, invalid: t, className: n, id: r, ...i }) => {
911
1128
  let a = o(), s = r ?? a;
912
1129
  return /* @__PURE__ */ f("div", {
913
1130
  className: "input-wrapper",
@@ -926,9 +1143,9 @@ var ae = ({ resources: e }) => {
926
1143
  ...i
927
1144
  })]
928
1145
  });
929
- }, se = ({ open: e, onClose: t, onLogin: n }) => {
930
- let { t: r } = m("sg", { i18n: L }), [i, a] = l(""), [o, s] = l("");
931
- return /* @__PURE__ */ d(K, {
1146
+ }, ge = ({ open: e, onClose: t, onLogin: n }) => {
1147
+ let { t: r } = m("sg", { i18n: R }), [i, a] = l(""), [o, s] = l("");
1148
+ return /* @__PURE__ */ d(Y, {
932
1149
  open: e,
933
1150
  onClose: t,
934
1151
  title: r("auth.login"),
@@ -937,13 +1154,13 @@ var ae = ({ resources: e }) => {
937
1154
  e.preventDefault(), n(i, o);
938
1155
  },
939
1156
  children: [
940
- /* @__PURE__ */ d(q, {
1157
+ /* @__PURE__ */ d(he, {
941
1158
  label: r("auth.username"),
942
1159
  value: i,
943
1160
  onChange: (e) => a(e.target.value),
944
1161
  autoFocus: !0
945
1162
  }),
946
- /* @__PURE__ */ d(J, {
1163
+ /* @__PURE__ */ d(X, {
947
1164
  label: r("auth.password"),
948
1165
  value: o,
949
1166
  onChange: (e) => s(e.target.value)
@@ -956,19 +1173,10 @@ var ae = ({ resources: e }) => {
956
1173
  ]
957
1174
  })
958
1175
  });
959
- }, ce = "simonegentili.com-access-token", Y = "sg-avatar-change", X = (e) => document.cookie.split("; ").some((t) => t.startsWith(`${e}=`) && t.slice(e.length + 1).length > 0), le = (e) => {
960
- let t = document.cookie.split("; ").find((t) => t.startsWith(`${e}=`));
961
- return t ? t.slice(e.length + 1) : null;
962
- }, ue = (e, t) => {
963
- try {
964
- return JSON.parse(atob(e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/")))[t] ?? null;
965
- } catch {
966
- return null;
967
- }
968
- }, Z = r(({ title: e = "Quadrato", homePageKey: t = "home", onNavigate: n, cookieName: r = ce, username: i = null, usernameJwtField: o = "sub", onLogin: c, onLogout: p, onUserAuthenticated: m, appsUrl: h, heimdallUrl: g = R }, _) => {
969
- let [v, y] = l(() => X(r)), [b, x] = l(!1);
1176
+ }, Z = "sg-avatar-change", Q = (e) => j(e) !== null, _e = r(({ title: e = "Quadrato", homePageKey: t = "home", onNavigate: n, cookieName: r = k, username: i = null, usernameJwtField: o = "sub", onLogin: c, onLogout: p, onUserAuthenticated: m, appsUrl: h, heimdallUrl: g = z }, _) => {
1177
+ let [v, y] = l(() => Q(r)), [b, x] = l(!1);
970
1178
  s(_, () => ({ openLoginModal: () => x(!0) }));
971
- let S = v ? le(r) : null, C = i ?? (S ? ue(S, o) : null), [w, T] = l(null), E = S && w?.token === S ? w.src : null;
1179
+ let S = v ? j(r) : null, C = i ?? M(S, o), [w, T] = l(null), E = S && w?.token === S ? w.src : null;
972
1180
  return a(() => {
973
1181
  if (!S) return;
974
1182
  let e = !1;
@@ -986,7 +1194,7 @@ var ae = ({ resources: e }) => {
986
1194
  token: S,
987
1195
  src: e.detail
988
1196
  });
989
- return window.addEventListener(Y, e), () => window.removeEventListener(Y, e);
1197
+ return window.addEventListener(Z, e), () => window.removeEventListener(Z, e);
990
1198
  }, [S]), a(() => {
991
1199
  m?.(v, v ? C : null);
992
1200
  }, []), /* @__PURE__ */ f(u, { children: [
@@ -995,50 +1203,50 @@ var ae = ({ resources: e }) => {
995
1203
  title: e,
996
1204
  homePageKey: t,
997
1205
  className: "quadrato-header",
998
- children: [/* @__PURE__ */ d(H, {
1206
+ children: [/* @__PURE__ */ d(K, {
999
1207
  appsUrl: h,
1000
1208
  token: S
1001
1209
  }), /* @__PURE__ */ f("div", {
1002
1210
  className: "quadrato-header-auth",
1003
1211
  children: [
1004
- v && E && /* @__PURE__ */ d(U, { src: E }),
1212
+ v && E && /* @__PURE__ */ d(q, { src: E }),
1005
1213
  v && C && /* @__PURE__ */ d("span", {
1006
1214
  className: "quadrato-header-username",
1007
1215
  children: C
1008
1216
  }),
1009
- /* @__PURE__ */ d(W, {
1217
+ /* @__PURE__ */ d(J, {
1010
1218
  isLoggedIn: v,
1011
1219
  handleLogin: () => x(!0),
1012
1220
  handleLogout: () => {
1013
1221
  p?.();
1014
- let e = X(r);
1222
+ let e = Q(r);
1015
1223
  y(e), m?.(e, null);
1016
1224
  }
1017
1225
  })
1018
1226
  ]
1019
1227
  })]
1020
1228
  }),
1021
- /* @__PURE__ */ d(B, {
1229
+ /* @__PURE__ */ d(V, {
1022
1230
  token: S,
1023
1231
  heimdallUrl: g
1024
1232
  }),
1025
- /* @__PURE__ */ d(se, {
1233
+ /* @__PURE__ */ d(ge, {
1026
1234
  open: b,
1027
1235
  onClose: () => x(!1),
1028
1236
  onLogin: async (e, t) => {
1029
1237
  await c(e, t);
1030
- let n = X(r);
1238
+ let n = Q(r);
1031
1239
  y(n), x(!1), m?.(n, n ? i ?? e : null);
1032
1240
  }
1033
1241
  })
1034
1242
  ] });
1035
1243
  });
1036
- Z.displayName = "QuadratoHeader";
1244
+ _e.displayName = "QuadratoHeader";
1037
1245
  //#endregion
1038
1246
  //#region src/components/SetPasswordModal/SetPasswordModal.tsx
1039
- var de = ({ open: e, onClose: t, onSubmit: n }) => {
1040
- let { t: r } = m("sg", { i18n: L }), [i, a] = l(""), [o, s] = l(""), [c, u] = l("");
1041
- return /* @__PURE__ */ d(K, {
1247
+ var ve = ({ open: e, onClose: t, onSubmit: n }) => {
1248
+ let { t: r } = m("sg", { i18n: R }), [i, a] = l(""), [o, s] = l(""), [c, u] = l("");
1249
+ return /* @__PURE__ */ d(Y, {
1042
1250
  open: e,
1043
1251
  onClose: t,
1044
1252
  title: r("setPassword.title"),
@@ -1056,13 +1264,13 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1056
1264
  u(""), n(i);
1057
1265
  },
1058
1266
  children: [
1059
- /* @__PURE__ */ d(J, {
1267
+ /* @__PURE__ */ d(X, {
1060
1268
  label: r("setPassword.newPassword"),
1061
1269
  value: i,
1062
1270
  onChange: (e) => a(e.target.value),
1063
1271
  autoFocus: !0
1064
1272
  }),
1065
- /* @__PURE__ */ d(J, {
1273
+ /* @__PURE__ */ d(X, {
1066
1274
  label: r("setPassword.confirmPassword"),
1067
1275
  value: o,
1068
1276
  onChange: (e) => s(e.target.value)
@@ -1079,7 +1287,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1079
1287
  ]
1080
1288
  })
1081
1289
  });
1082
- }, fe = ({ value: e, onChange: t, swatches: n }) => {
1290
+ }, ye = ({ value: e, onChange: t, swatches: n }) => {
1083
1291
  let [r, i] = l(!1), o = c(null);
1084
1292
  return a(() => {
1085
1293
  if (!r) return;
@@ -1128,7 +1336,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1128
1336
  })]
1129
1337
  })]
1130
1338
  });
1131
- }, Q = (e) => e.split(",")[0].replace(/'/g, ""), pe = ({ value: e, onChange: t, options: n }) => {
1339
+ }, be = (e) => e.split(",")[0].replace(/'/g, ""), xe = ({ value: e, onChange: t, options: n }) => {
1132
1340
  let [r, i] = l(!1), o = c(null);
1133
1341
  return a(() => {
1134
1342
  if (!r) return;
@@ -1150,7 +1358,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1150
1358
  style: { fontFamily: e },
1151
1359
  children: [/* @__PURE__ */ d("span", {
1152
1360
  className: "sg-font-picker-toggle-label",
1153
- children: Q(e)
1361
+ children: be(e)
1154
1362
  }), /* @__PURE__ */ d("span", {
1155
1363
  className: "sg-font-picker-toggle-caret",
1156
1364
  children: r ? "▲" : "▼"
@@ -1164,11 +1372,11 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1164
1372
  t(n), i(!1);
1165
1373
  },
1166
1374
  style: { fontFamily: n },
1167
- children: Q(n)
1375
+ children: be(n)
1168
1376
  }) }, n))
1169
1377
  })]
1170
1378
  });
1171
- }, me = ({ checked: e, onChange: t, label: n, icons: r, layout: i = "inline" }) => /* @__PURE__ */ f("label", {
1379
+ }, Se = ({ checked: e, onChange: t, label: n, icons: r, layout: i = "inline" }) => /* @__PURE__ */ f("label", {
1172
1380
  className: i === "row" ? "sg-toggle sg-toggle--row" : "sg-toggle",
1173
1381
  children: [
1174
1382
  /* @__PURE__ */ d("input", {
@@ -1190,19 +1398,19 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1190
1398
  children: r
1191
1399
  })
1192
1400
  ]
1193
- }), he = ({ className: e }) => {
1194
- let { t, i18n: n } = m("sg", { i18n: L });
1401
+ }), Ce = ({ className: e }) => {
1402
+ let { t, i18n: n } = m("sg", { i18n: R });
1195
1403
  return /* @__PURE__ */ d("select", {
1196
1404
  className: ["sg-language-switcher", e].filter(Boolean).join(" "),
1197
1405
  value: n.resolvedLanguage,
1198
1406
  onChange: (e) => n.changeLanguage(e.target.value),
1199
1407
  "aria-label": t("languageSwitcher.label"),
1200
- children: j.map((e) => /* @__PURE__ */ d("option", {
1408
+ children: N.map((e) => /* @__PURE__ */ d("option", {
1201
1409
  value: e,
1202
- children: M[e]
1410
+ children: P[e]
1203
1411
  }, e))
1204
1412
  });
1205
- }, ge = ({ value: e, max: t = 100, label: n, ariaLabel: r, tone: i = "accent", size: a = "md", className: o }) => {
1413
+ }, we = ({ value: e, max: t = 100, label: n, ariaLabel: r, tone: i = "accent", size: a = "md", className: o }) => {
1206
1414
  let s = t > 0 ? Math.min(100, Math.max(0, e / t * 100)) : 0;
1207
1415
  return /* @__PURE__ */ f("div", {
1208
1416
  className: [
@@ -1227,8 +1435,8 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1227
1435
  children: n
1228
1436
  })]
1229
1437
  });
1230
- }, _e = ({ kind: e = "info", boxed: t = !1, children: n, className: r }) => {
1231
- let { t: i } = m("sg", { i18n: L });
1438
+ }, Te = ({ kind: e = "info", boxed: t = !1, children: n, className: r }) => {
1439
+ let { t: i } = m("sg", { i18n: R });
1232
1440
  return /* @__PURE__ */ f("p", {
1233
1441
  className: [
1234
1442
  "sg-status",
@@ -1242,7 +1450,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1242
1450
  "aria-hidden": "true"
1243
1451
  }), n ?? (e === "loading" ? i("status.loading") : null)]
1244
1452
  });
1245
- }, ve = ({ header: e, actions: t, children: r, variant: i = "default", interactive: a = !1, as: o = "div", href: s, className: c }) => n(o, {
1453
+ }, Ee = ({ header: e, actions: t, children: r, variant: i = "default", interactive: a = !1, as: o = "div", href: s, className: c }) => n(o, {
1246
1454
  className: [
1247
1455
  "sg-card",
1248
1456
  `sg-card--${i}`,
@@ -1256,8 +1464,8 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1256
1464
  }), r, t && /* @__PURE__ */ d("div", {
1257
1465
  className: "sg-card-actions",
1258
1466
  children: t
1259
- })), ye = ({ children: e, tone: t = "neutral", onClick: n, selected: r = !1, onRemove: i, removeLabel: a, className: o }) => {
1260
- let { t: s } = m("sg", { i18n: L });
1467
+ })), De = ({ children: e, tone: t = "neutral", onClick: n, selected: r = !1, onRemove: i, removeLabel: a, className: o }) => {
1468
+ let { t: s } = m("sg", { i18n: R });
1261
1469
  return /* @__PURE__ */ f("span", {
1262
1470
  className: [
1263
1471
  "sg-badge",
@@ -1279,9 +1487,9 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1279
1487
  children: "×"
1280
1488
  })]
1281
1489
  });
1282
- }, $ = ({ open: e, title: t, children: n, onConfirm: r, onCancel: i, confirmLabel: a, cancelLabel: o, danger: s = !1, icon: c }) => {
1283
- let { t: l } = m("sg", { i18n: L });
1284
- return /* @__PURE__ */ d(K, {
1490
+ }, Oe = ({ open: e, title: t, children: n, onConfirm: r, onCancel: i, confirmLabel: a, cancelLabel: o, danger: s = !1, icon: c }) => {
1491
+ let { t: l } = m("sg", { i18n: R });
1492
+ return /* @__PURE__ */ d(Y, {
1285
1493
  open: e,
1286
1494
  onClose: i,
1287
1495
  title: t,
@@ -1301,7 +1509,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1301
1509
  children: n
1302
1510
  })
1303
1511
  });
1304
- }, be = ({ invalid: e, className: t, rows: n = 3, ...r }) => /* @__PURE__ */ d("textarea", {
1512
+ }, ke = ({ invalid: e, className: t, rows: n = 3, ...r }) => /* @__PURE__ */ d("textarea", {
1305
1513
  rows: n,
1306
1514
  className: [
1307
1515
  "input-field",
@@ -1310,7 +1518,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1310
1518
  t
1311
1519
  ].filter(Boolean).join(" "),
1312
1520
  ...r
1313
- }), xe = ({ invalid: e, className: t, children: n, ...r }) => /* @__PURE__ */ d("select", {
1521
+ }), Ae = ({ invalid: e, className: t, children: n, ...r }) => /* @__PURE__ */ d("select", {
1314
1522
  className: [
1315
1523
  "input-field",
1316
1524
  "sg-select",
@@ -1319,7 +1527,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1319
1527
  ].filter(Boolean).join(" "),
1320
1528
  ...r,
1321
1529
  children: n
1322
- }), Se = ({ label: e, children: n, hint: r, error: a, className: s }) => {
1530
+ }), $ = ({ label: e, children: n, hint: r, error: a, className: s }) => {
1323
1531
  let c = o(), l = i(n) ? n : null, u = l?.props.id ?? c, p = `${u}-note`, m = a ?? r;
1324
1532
  return /* @__PURE__ */ f("div", {
1325
1533
  className: ["sg-field", s].filter(Boolean).join(" "),
@@ -1342,7 +1550,7 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1342
1550
  })
1343
1551
  ]
1344
1552
  });
1345
- }, Ce = ({ items: e, value: t, onChange: n, variant: r = "underline", ariaLabel: i, className: a }) => {
1553
+ }, je = ({ items: e, value: t, onChange: n, variant: r = "underline", ariaLabel: i, className: a }) => {
1346
1554
  let o = c(null);
1347
1555
  return /* @__PURE__ */ d("div", {
1348
1556
  ref: o,
@@ -1372,6 +1580,84 @@ var de = ({ open: e, onClose: t, onSubmit: n }) => {
1372
1580
  }, e.value);
1373
1581
  })
1374
1582
  });
1583
+ }, Me = ({ version: e, className: t }) => {
1584
+ let { t: n } = m("sg", { i18n: R });
1585
+ return /* @__PURE__ */ f("p", {
1586
+ className: ["sg-version", t].filter(Boolean).join(" "),
1587
+ children: [
1588
+ n("version.label"),
1589
+ " v",
1590
+ e
1591
+ ]
1592
+ });
1593
+ }, Ne = ({ children: e, onLogin: t, footer: n, className: r }) => {
1594
+ let { t: i } = m("sg", { i18n: R });
1595
+ return /* @__PURE__ */ f("div", {
1596
+ className: ["sg-login-prompt", r].filter(Boolean).join(" "),
1597
+ children: [
1598
+ /* @__PURE__ */ d("p", {
1599
+ className: "sg-login-prompt-message",
1600
+ children: e ?? i("loginPrompt.message")
1601
+ }),
1602
+ t && /* @__PURE__ */ d(v, {
1603
+ label: i("auth.login"),
1604
+ onClick: t
1605
+ }),
1606
+ n && /* @__PURE__ */ d("div", {
1607
+ className: "sg-login-prompt-footer",
1608
+ children: n
1609
+ })
1610
+ ]
1611
+ });
1612
+ }, Pe = ({ title: e, children: t, footer: n, className: r }) => /* @__PURE__ */ f("div", {
1613
+ className: ["sg-auth-page", r].filter(Boolean).join(" "),
1614
+ children: [/* @__PURE__ */ f("div", {
1615
+ className: "sg-auth-page-card",
1616
+ children: [/* @__PURE__ */ d("h1", {
1617
+ className: "sg-auth-page-title",
1618
+ children: e
1619
+ }), t]
1620
+ }), n && /* @__PURE__ */ d("div", {
1621
+ className: "sg-auth-page-footer",
1622
+ children: n
1623
+ })]
1624
+ }), Fe = ({ onRegister: e, onRegistered: t }) => {
1625
+ let { t: n } = m("sg", { i18n: R }), [r, i] = l(""), [a, o] = l(!1), [s, c] = l(!1), [u, p] = l(null);
1626
+ return s ? /* @__PURE__ */ d(Te, {
1627
+ boxed: !0,
1628
+ children: n("register.sent")
1629
+ }) : /* @__PURE__ */ f("form", {
1630
+ className: "sg-register-form",
1631
+ onSubmit: async (n) => {
1632
+ n.preventDefault();
1633
+ let i = r.trim();
1634
+ o(!0), p(null);
1635
+ try {
1636
+ await e(i), t ? t(i) : c(!0);
1637
+ } catch (e) {
1638
+ p(e instanceof Error ? e.message : String(e));
1639
+ } finally {
1640
+ o(!1);
1641
+ }
1642
+ },
1643
+ children: [/* @__PURE__ */ d($, {
1644
+ label: n("register.email"),
1645
+ error: u ?? void 0,
1646
+ children: /* @__PURE__ */ d("input", {
1647
+ className: "input-field",
1648
+ type: "email",
1649
+ autoComplete: "email",
1650
+ placeholder: n("register.placeholder"),
1651
+ value: r,
1652
+ onChange: (e) => i(e.target.value),
1653
+ required: !0
1654
+ })
1655
+ }), /* @__PURE__ */ d(v, {
1656
+ type: "submit",
1657
+ label: n(a ? "register.sending" : "register.submit"),
1658
+ disabled: a || r.trim() === ""
1659
+ })]
1660
+ });
1375
1661
  };
1376
1662
  //#endregion
1377
- export { Y as AVATAR_CHANGE_EVENT, B as AppAccessGate, H as AppLauncher, W as Authenticator, U as Avatar, ye as Badge, v as Button, ve as Card, fe as ColorPicker, $ as ConfirmModal, w as CookieConsent, V as DEFAULT_APPS_URL, R as DEFAULT_HEIMDALL_URL, pe as FontPicker, y as Footer, Se as FormField, D as Header, _ as Icon, q as Input, N as LANGUAGE_COOKIE, M as LANGUAGE_NAMES, he as LanguageSwitcher, K as Modal, J as PasswordInput, ge as ProgressBar, Z as QuadratoHeader, E as SGFooter, O as SGHeader, j as SUPPORTED_LANGUAGES, xe as Select, de as SetPasswordModal, _e as StatusMessage, Ce as Tabs, be as Textarea, me as Toggle, ae as createI18n, I as readLanguageCookie, L as sgI18n };
1663
+ export { k as ACCESS_TOKEN_COOKIE, Z as AVATAR_CHANGE_EVENT, V as AppAccessGate, K as AppLauncher, Pe as AuthPage, J as Authenticator, q as Avatar, De as Badge, v as Button, Ee as Card, ye as ColorPicker, Oe as ConfirmModal, w as CookieConsent, G as DEFAULT_APPS_URL, z as DEFAULT_HEIMDALL_URL, xe as FontPicker, y as Footer, $ as FormField, D as Header, _ as Icon, he as Input, F as LANGUAGE_COOKIE, P as LANGUAGE_NAMES, H as LOGOS, Ce as LanguageSwitcher, Ne as LoginPrompt, W as Logo, Y as Modal, X as PasswordInput, we as ProgressBar, _e as QuadratoHeader, Fe as RegisterForm, E as SGFooter, O as SGHeader, N as SUPPORTED_LANGUAGES, Ae as Select, ve as SetPasswordModal, Te as StatusMessage, je as Tabs, ke as Textarea, Se as Toggle, Me as VersionNumber, re as clearAccessToken, fe as createI18n, j as getAccessToken, M as getTokenClaim, U as isLogoKey, L as readLanguageCookie, ne as setAccessToken, R as sgI18n };
@@ -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--secondary{--button-bg:var(--sg-surface);--button-bg-hover:var(--sg-surface-hover);--button-color:var(--sg-text);--button-shadow:none;border:1px solid var(--sg-border)}.custom-button--danger{--button-bg:var(--sg-danger);--button-bg-hover:var(--sg-danger);--button-color:var(--sg-on-accent)}.custom-button--danger:hover:not(:disabled){filter:brightness(.92)}.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:var(--sg-text-secondary);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:var(--sg-link);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:var(--sg-text-secondary);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:var(--sg-link);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{background-color:var(--sg-surface);width:100%;color:var(--sg-text);border-bottom:1px solid var(--sg-border-subtle);box-shadow:var(--sg-shadow-1);z-index:100;font-size:var(--font-size);position:sticky;top:0}.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:var(--sg-text);font-size:24px;font-weight:700;transition:color .2s}.logo:hover{color:var(--accent)}.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);color:var(--sg-text);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:var(--sg-danger)}.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;color:var(--sg-text);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);width:40px;height:40px;color:var(--sg-on-accent);justify-content:center;align-items:center;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-app-launcher-tile{position:relative}.sg-app-launcher-app.locked .sg-app-launcher-tile{background:var(--ink-muted)}.sg-app-launcher-app.locked .sg-app-launcher-name{color:var(--ink-muted)}.sg-app-launcher-lock{border:2px solid var(--modal-bg);background:var(--modal-title-color);width:20px;height:20px;color:var(--modal-bg);border-radius:50%;justify-content:center;align-items:center;display:flex;position:absolute;bottom:-6px;right:-6px}.sg-visually-hidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.sg-avatar{--avatar-size:32px;--avatar-bg:var(--sg-accent);--avatar-color:var(--sg-on-accent);box-sizing:border-box;width:var(--avatar-size);height:var(--avatar-size);object-fit:cover;background:var(--avatar-bg);color:var(--avatar-color);box-shadow:var(--sg-shadow-1);font-family:var(--font-family);font-size:calc(var(--avatar-size) * .42);-webkit-user-select:none;user-select:none;border-radius:50%;flex:none;justify-content:center;align-items:center;font-weight:600;display:inline-flex}.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:var(--sg-text);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;color:var(--sg-text);box-shadow:var(--sg-shadow-3);transform:translate(var(--drag-x), var(--drag-y));flex-direction:column;animation:.3s ease-out sg-modal-slide-in;display:flex;overflow:hidden}.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-size:var(--primary-font);margin-bottom:4px;display:block}.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:var(--sg-text);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:var(--sg-danger);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 var(--sg-border-subtle);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{border:1px solid var(--sg-border-subtle);cursor:pointer;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)}.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}.sg-toggle-icons{align-items:center;gap:4px;display:inline-flex}.sg-toggle--row{gap:12px;width:100%;margin:8px 0}.sg-toggle--row .sg-toggle-label{color:var(--sg-text);font-size:var(--primary-font);white-space:normal;flex:1;order:-2}.sg-toggle--row .sg-toggle-icons{order:-1}.sg-language-switcher{border:1px solid var(--input-border);border-radius:var(--input-radius);background:var(--input-bg);color:var(--sg-text);font-family:var(--font-family);font-size:var(--primary-font);cursor:pointer;padding:4px 8px}.sg-progress{--progress-height:8px;--progress-track:var(--sg-surface-hover);--progress-fill:var(--sg-accent);font-family:var(--font-family);align-items:center;gap:12px;display:flex}.sg-progress--sm{--progress-height:6px}.sg-progress--success{--progress-fill:var(--sg-success)}.sg-progress--danger{--progress-fill:var(--sg-danger)}.sg-progress-track{height:var(--progress-height);background:var(--progress-track);border-radius:999px;flex:1;overflow:hidden}.sg-progress-fill{background:var(--progress-fill);height:100%;transition:width .2s var(--button-ease-standard);border-radius:999px}.sg-progress-label{color:var(--sg-text-muted);white-space:nowrap;font-size:12px}.sg-status{--status-color:var(--sg-text-muted);--status-bg:var(--sg-surface-muted);color:var(--status-color);font-family:var(--font-family);font-size:var(--primary-font);align-items:center;gap:8px;margin:0;display:flex}.sg-status--error{--status-color:var(--sg-danger);--status-bg:var(--sg-danger-soft)}.sg-status--boxed{border-radius:var(--radius);background:var(--status-bg);padding:8px 12px}.sg-status-spinner{border:2px solid var(--sg-border);border-top-color:var(--sg-accent);border-radius:50%;flex:none;width:14px;height:14px;animation:.8s linear infinite sg-status-spin}@keyframes sg-status-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.sg-status-spinner{animation-duration:2.4s}}.sg-card{--card-bg:var(--sg-surface);--card-border:var(--sg-border-subtle);--card-radius:calc(var(--radius) * 2);--card-shadow:var(--sg-shadow-1);--card-shadow-hover:var(--sg-shadow-2);--card-padding:16px;box-sizing:border-box;padding:var(--card-padding);border:1px solid var(--card-border);border-radius:var(--card-radius);background:var(--card-bg);box-shadow:var(--card-shadow);color:var(--sg-text);font-family:var(--font-family);text-align:left;text-decoration:none;display:block}.sg-card--mini{--card-padding:8px 12px}.sg-card--interactive{cursor:pointer;transition:box-shadow .18s var(--button-ease-standard), transform .2s var(--button-ease-bounce), border-color .18s var(--button-ease-standard)}.sg-card--interactive:hover,.sg-card--interactive:focus-visible{box-shadow:var(--card-shadow-hover);border-color:var(--sg-accent);transform:translateY(-2px)}.sg-card-header{justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:8px;display:flex}.sg-card-actions{flex-wrap:wrap;gap:8px 16px;margin-top:12px;display:flex}.sg-card-actions a{color:var(--sg-link)}.sg-badge{--badge-bg:var(--sg-surface-muted);--badge-border:var(--sg-border);--badge-color:var(--sg-text);border:1px solid var(--badge-border);background:var(--badge-bg);color:var(--badge-color);font-family:var(--font-family);white-space:nowrap;border-radius:999px;align-items:center;gap:4px;padding:3px 10px;font-size:13px;line-height:1.3;display:inline-flex}.sg-badge--accent,.sg-badge--selected{--badge-bg:var(--sg-accent-soft);--badge-border:var(--sg-accent);--badge-color:var(--sg-accent-strong)}.sg-badge--success{--badge-bg:var(--sg-success-soft);--badge-border:var(--sg-success);--badge-color:var(--sg-success)}.sg-badge--danger{--badge-bg:var(--sg-danger-soft);--badge-border:var(--sg-danger);--badge-color:var(--sg-danger)}.sg-badge:has(.sg-badge-toggle){transition:transform .2s var(--button-ease-bounce);padding:0}.sg-badge:has(.sg-badge-toggle):hover{transform:translateY(-1px)}.sg-badge-toggle{border-radius:inherit;color:inherit;font:inherit;cursor:pointer;background:0 0;border:none;padding:3px 10px}.sg-badge:has(.sg-badge-remove){padding-right:3px}.sg-badge-remove{width:20px;height:20px;color:inherit;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;padding:0;font-size:15px;line-height:1;display:inline-flex}.sg-badge-remove:hover{background:var(--sg-surface-hover)}.sg-confirm-message{max-width:420px;color:var(--sg-text);line-height:1.5}.sg-confirm-message>p{margin:0}.sg-textarea{resize:vertical;font-family:inherit;line-height:1.4}.sg-select{cursor:pointer;font-family:inherit}.input-wrapper{margin-bottom:16px}.input-label{font-weight:500;font-family:var(--font-family);font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field{box-sizing:border-box;border-radius:var(--radius);border-style:solid;border-width:1px;border-color:var(--input-border);background-color:var(--input-bg);width:100%;color:var(--sg-text);font-size:var(--primary-font);padding:8px}.input-field--invalid{background-color:var(--sg-danger-soft);border-color:var(--sg-danger)}.sg-field{font-family:var(--font-family);flex-direction:column;gap:4px;margin-bottom:16px;display:flex}.sg-field .input-label,.sg-field .input-wrapper{margin-bottom:0}.sg-field-hint,.sg-field-error{margin:0;font-size:12px}.sg-field-hint{color:var(--sg-text-muted)}.sg-field-error{color:var(--sg-danger)}.sg-tabs{--tabs-gap:4px;gap:var(--tabs-gap);font-family:var(--font-family);-webkit-overflow-scrolling:touch;display:flex;overflow-x:auto}.sg-tab{color:var(--sg-text-muted);font:inherit;font-size:var(--primary-font);white-space:nowrap;cursor:pointer;transition:background .15s var(--button-ease-standard), color .15s var(--button-ease-standard);background:0 0;border:none;flex:none;padding:8px 16px}.sg-tab:disabled{opacity:.5;cursor:default}.sg-tab:focus-visible{outline:2px solid var(--sg-accent-strong);outline-offset:2px}.sg-tabs--underline{--tabs-gap:8px;border-bottom:1px solid var(--sg-border)}.sg-tabs--underline .sg-tab{border-bottom:2px solid #0000;margin-bottom:-1px}.sg-tabs--underline .sg-tab:hover:not(:disabled){color:var(--sg-text)}.sg-tabs--underline .sg-tab--active{border-bottom-color:var(--sg-accent-strong);color:var(--sg-accent-strong);font-weight:600}.sg-tabs--pills .sg-tab{background:var(--sg-surface-muted);color:var(--sg-text);border-radius:999px}.sg-tabs--pills .sg-tab:hover:not(:disabled):not(.sg-tab--active){background:var(--sg-surface-hover)}.sg-tabs--pills .sg-tab--active{background:var(--sg-accent);color:var(--sg-on-accent);box-shadow:var(--sg-shadow-1)}.sg-tabs--segmented{border:1px solid var(--sg-border);background:var(--sg-surface-muted);border-radius:999px;padding:4px}.sg-tabs--segmented .sg-tab{color:var(--sg-accent-strong);border-radius:999px;flex:1;padding:6px 16px;font-weight:600}.sg-tabs--segmented .sg-tab:hover:not(:disabled):not(.sg-tab--active){background:var(--sg-accent-soft)}.sg-tabs--segmented .sg-tab--active{background:var(--sg-accent);color:var(--sg-on-accent)}:root{--sg-color-white:#fff;--sg-color-black:#000;--sg-color-gray-50:#f5f5f5;--sg-color-gray-100:#e1e5e9;--sg-color-gray-150:#e0e0e0;--sg-color-gray-200:#e6e6e6;--sg-color-gray-300:#ccc;--sg-color-gray-350:#bdbdbd;--sg-color-gray-400:#9aa3b5;--sg-color-gray-500:#647089;--sg-color-gray-600:#555;--sg-color-gray-650:#444;--sg-color-gray-700:#333;--sg-color-gray-750:#2a2a2a;--sg-color-gray-800:#222;--sg-color-gray-900:#1a1a1a;--sg-color-blue-50:#e2e7f8;--sg-color-blue-300:#86aefc;--sg-color-blue-400:#6f9cf7;--sg-color-blue-500:#5480e6;--sg-color-blue-600:#3d5fc4;--sg-color-blue-700:#2e4aa0;--sg-color-sky-500:#1ea7fd;--sg-color-green-50:#e8f5e9;--sg-color-green-400:#66bb6a;--sg-color-green-700:#2e7d32;--sg-color-red-50:#ffe5e5;--sg-color-red-400:#e57373;--sg-color-red-600:#c0392b;--sg-bg:var(--sg-color-white);--sg-surface:var(--sg-color-white);--sg-surface-muted:var(--sg-color-gray-50);--sg-surface-hover:var(--sg-color-gray-150);--sg-border:var(--sg-color-gray-300);--sg-border-subtle:var(--sg-color-gray-100);--sg-text:var(--sg-color-gray-700);--sg-text-heading:var(--sg-color-gray-800);--sg-text-secondary:var(--sg-color-gray-600);--sg-text-muted:var(--sg-color-gray-500);--sg-accent:var(--sg-color-blue-600);--sg-accent-strong:var(--sg-color-blue-700);--sg-accent-soft:var(--sg-color-blue-50);--sg-on-accent:var(--sg-color-white);--sg-action:var(--sg-color-blue-400);--sg-action-hover:var(--sg-color-blue-500);--sg-link:var(--sg-color-sky-500);--sg-success:var(--sg-color-green-700);--sg-success-soft:var(--sg-color-green-50);--sg-danger:var(--sg-color-red-600);--sg-danger-soft:var(--sg-color-red-50);--sg-overlay:#0000004d;--sg-shadow-1:0 1px 2px #0f172a14, 0 1px 3px #0f172a0f;--sg-shadow-2:0 4px 12px #0f172a1f;--sg-shadow-3:0 2px 16px #00000026;--sg-action-shadow:0 1px 2px #5480e61f, 0 1px 3px #5480e61a;--unit:3px;--radius:calc(var(--unit) * 2);--font-size:14px;--font-family:Arial, sans-serif;--font-size-h1:calc(var(--font-size) * 1.5);--primary-bg:var(--sg-surface-muted);--primary-border:var(--sg-border);--primary-radius:var(--radius);--primary-font:var(--font-size);--primary-hover-bg:var(--sg-surface-hover);--modal-bg:var(--sg-surface);--modal-overlay:var(--sg-overlay);--modal-title-color:var(--sg-text-heading);--input-bg:var(--sg-surface);--input-border:var(--sg-border);--input-radius:var(--radius);--input-font:1rem;--button-bg:var(--sg-action);--button-bg-hover:var(--sg-action-hover);--button-color:var(--sg-on-accent);--button-radius:999px;--button-shadow:var(--sg-action-shadow);--button-ease-standard:cubic-bezier(.4, 0, .2, 1);--button-ease-bounce:cubic-bezier(.34, 1.56, .64, 1);--accent:var(--sg-accent);--accent-strong:var(--sg-accent-strong);--accent-soft:var(--sg-accent-soft);--ink-muted:var(--sg-text-muted);--shadow-1:var(--sg-shadow-1);--shadow-2:var(--sg-shadow-2)}:root[data-theme=dark]{--sg-bg:var(--sg-color-gray-900);--sg-surface:var(--sg-color-gray-800);--sg-surface-muted:var(--sg-color-gray-750);--sg-surface-hover:var(--sg-color-gray-700);--sg-border:var(--sg-color-gray-600);--sg-border-subtle:var(--sg-color-gray-650);--sg-text:var(--sg-color-gray-200);--sg-text-heading:var(--sg-color-white);--sg-text-secondary:var(--sg-color-gray-350);--sg-text-muted:var(--sg-color-gray-400);--sg-accent:var(--sg-color-blue-400);--sg-accent-strong:var(--sg-color-blue-300);--sg-accent-soft:#6f9cf72e;--sg-action-hover:var(--sg-color-blue-300);--sg-link:var(--sg-color-blue-300);--sg-success:var(--sg-color-green-400);--sg-success-soft:#66bb6a26;--sg-danger:var(--sg-color-red-400);--sg-danger-soft:#e5737326;--sg-overlay:#0009;--sg-shadow-1:0 1px 2px #0000004d, 0 1px 3px #0000003d;--sg-shadow-2:0 4px 12px #0006;--sg-shadow-3:0 2px 16px #00000080}.sg-table-scroll{-webkit-overflow-scrolling:touch;overflow-x:auto}.sg-table{--table-border:var(--sg-border-subtle);--table-head-bg:var(--sg-surface-muted);--table-row-hover:var(--sg-surface-muted);--table-cell-padding:8px 12px;border-collapse:collapse;width:100%;color:var(--sg-text);font-family:var(--font-family);font-size:var(--primary-font)}.sg-table th,.sg-table td{padding:var(--table-cell-padding);border-bottom:1px solid var(--table-border);text-align:left;vertical-align:top}.sg-table th{background:var(--table-head-bg);color:var(--sg-text-secondary);text-transform:uppercase;letter-spacing:.03em;white-space:nowrap;font-size:12px;font-weight:600}.sg-table tbody tr:hover{background:var(--table-row-hover)}.sg-table .sg-table-num{text-align:right;font-variant-numeric:tabular-nums}
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--secondary{--button-bg:var(--sg-surface);--button-bg-hover:var(--sg-surface-hover);--button-color:var(--sg-text);--button-shadow:none;border:1px solid var(--sg-border)}.custom-button--danger{--button-bg:var(--sg-danger);--button-bg-hover:var(--sg-danger);--button-color:var(--sg-on-accent)}.custom-button--danger:hover:not(:disabled){filter:brightness(.92)}.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:var(--sg-text-secondary);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:var(--sg-link);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:var(--sg-text-secondary);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:var(--sg-link);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{background-color:var(--sg-surface);width:100%;color:var(--sg-text);border-bottom:1px solid var(--sg-border-subtle);box-shadow:var(--sg-shadow-1);z-index:100;font-size:var(--font-size);position:sticky;top:0}.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:var(--sg-text);font-size:24px;font-weight:700;transition:color .2s}.logo:hover{color:var(--accent)}.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);color:var(--sg-text);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:var(--sg-danger)}.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;color:var(--sg-text);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(--tile-bg,var(--accent));width:40px;height:40px;color:var(--sg-on-accent);justify-content:center;align-items:center;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-app-launcher-tile{position:relative}.sg-app-launcher-app.locked .sg-app-launcher-tile{background:var(--ink-muted)}.sg-app-launcher-app.locked .sg-app-launcher-name{color:var(--ink-muted)}.sg-app-launcher-lock{border:2px solid var(--modal-bg);background:var(--modal-title-color);width:20px;height:20px;color:var(--modal-bg);border-radius:50%;justify-content:center;align-items:center;display:flex;position:absolute;bottom:-6px;right:-6px}.sg-visually-hidden{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}.sg-avatar{--avatar-size:32px;--avatar-bg:var(--sg-accent);--avatar-color:var(--sg-on-accent);box-sizing:border-box;width:var(--avatar-size);height:var(--avatar-size);object-fit:cover;background:var(--avatar-bg);color:var(--avatar-color);box-shadow:var(--sg-shadow-1);font-family:var(--font-family);font-size:calc(var(--avatar-size) * .42);-webkit-user-select:none;user-select:none;border-radius:50%;flex:none;justify-content:center;align-items:center;font-weight:600;display:inline-flex}.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:var(--sg-text);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;color:var(--sg-text);box-shadow:var(--sg-shadow-3);transform:translate(var(--drag-x), var(--drag-y));flex-direction:column;animation:.3s ease-out sg-modal-slide-in;display:flex;overflow:hidden}.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-size:var(--primary-font);margin-bottom:4px;display:block}.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:var(--sg-text);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:var(--sg-danger);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 var(--sg-border-subtle);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{border:1px solid var(--sg-border-subtle);cursor:pointer;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)}.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}.sg-toggle-icons{align-items:center;gap:4px;display:inline-flex}.sg-toggle--row{gap:12px;width:100%;margin:8px 0}.sg-toggle--row .sg-toggle-label{color:var(--sg-text);font-size:var(--primary-font);white-space:normal;flex:1;order:-2}.sg-toggle--row .sg-toggle-icons{order:-1}.sg-language-switcher{border:1px solid var(--input-border);border-radius:var(--input-radius);background:var(--input-bg);color:var(--sg-text);font-family:var(--font-family);font-size:var(--primary-font);cursor:pointer;padding:4px 8px}.sg-progress{--progress-height:8px;--progress-track:var(--sg-surface-hover);--progress-fill:var(--sg-accent);font-family:var(--font-family);align-items:center;gap:12px;display:flex}.sg-progress--sm{--progress-height:6px}.sg-progress--success{--progress-fill:var(--sg-success)}.sg-progress--danger{--progress-fill:var(--sg-danger)}.sg-progress-track{height:var(--progress-height);background:var(--progress-track);border-radius:999px;flex:1;overflow:hidden}.sg-progress-fill{background:var(--progress-fill);height:100%;transition:width .2s var(--button-ease-standard);border-radius:999px}.sg-progress-label{color:var(--sg-text-muted);white-space:nowrap;font-size:12px}.sg-status{--status-color:var(--sg-text-muted);--status-bg:var(--sg-surface-muted);color:var(--status-color);font-family:var(--font-family);font-size:var(--primary-font);align-items:center;gap:8px;margin:0;display:flex}.sg-status--error{--status-color:var(--sg-danger);--status-bg:var(--sg-danger-soft)}.sg-status--boxed{border-radius:var(--radius);background:var(--status-bg);padding:8px 12px}.sg-status-spinner{border:2px solid var(--sg-border);border-top-color:var(--sg-accent);border-radius:50%;flex:none;width:14px;height:14px;animation:.8s linear infinite sg-status-spin}@keyframes sg-status-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.sg-status-spinner{animation-duration:2.4s}}.sg-card{--card-bg:var(--sg-surface);--card-border:var(--sg-border-subtle);--card-radius:calc(var(--radius) * 2);--card-shadow:var(--sg-shadow-1);--card-shadow-hover:var(--sg-shadow-2);--card-padding:16px;box-sizing:border-box;padding:var(--card-padding);border:1px solid var(--card-border);border-radius:var(--card-radius);background:var(--card-bg);box-shadow:var(--card-shadow);color:var(--sg-text);font-family:var(--font-family);text-align:left;text-decoration:none;display:block}.sg-card--mini{--card-padding:8px 12px}.sg-card--interactive{cursor:pointer;transition:box-shadow .18s var(--button-ease-standard), transform .2s var(--button-ease-bounce), border-color .18s var(--button-ease-standard)}.sg-card--interactive:hover,.sg-card--interactive:focus-visible{box-shadow:var(--card-shadow-hover);border-color:var(--sg-accent);transform:translateY(-2px)}.sg-card-header{justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:8px;display:flex}.sg-card-actions{flex-wrap:wrap;gap:8px 16px;margin-top:12px;display:flex}.sg-card-actions a{color:var(--sg-link)}.sg-badge{--badge-bg:var(--sg-surface-muted);--badge-border:var(--sg-border);--badge-color:var(--sg-text);border:1px solid var(--badge-border);background:var(--badge-bg);color:var(--badge-color);font-family:var(--font-family);white-space:nowrap;border-radius:999px;align-items:center;gap:4px;padding:3px 10px;font-size:13px;line-height:1.3;display:inline-flex}.sg-badge--accent,.sg-badge--selected{--badge-bg:var(--sg-accent-soft);--badge-border:var(--sg-accent);--badge-color:var(--sg-accent-strong)}.sg-badge--success{--badge-bg:var(--sg-success-soft);--badge-border:var(--sg-success);--badge-color:var(--sg-success)}.sg-badge--danger{--badge-bg:var(--sg-danger-soft);--badge-border:var(--sg-danger);--badge-color:var(--sg-danger)}.sg-badge:has(.sg-badge-toggle){transition:transform .2s var(--button-ease-bounce);padding:0}.sg-badge:has(.sg-badge-toggle):hover{transform:translateY(-1px)}.sg-badge-toggle{border-radius:inherit;color:inherit;font:inherit;cursor:pointer;background:0 0;border:none;padding:3px 10px}.sg-badge:has(.sg-badge-remove){padding-right:3px}.sg-badge-remove{width:20px;height:20px;color:inherit;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;padding:0;font-size:15px;line-height:1;display:inline-flex}.sg-badge-remove:hover{background:var(--sg-surface-hover)}.sg-confirm-message{max-width:420px;color:var(--sg-text);line-height:1.5}.sg-confirm-message>p{margin:0}.sg-textarea{resize:vertical;font-family:inherit;line-height:1.4}.sg-select{cursor:pointer;font-family:inherit}.input-wrapper{margin-bottom:16px}.input-label{font-weight:500;font-family:var(--font-family);font-size:var(--primary-font);margin-bottom:4px;display:block}.input-field{box-sizing:border-box;border-radius:var(--radius);border-style:solid;border-width:1px;border-color:var(--input-border);background-color:var(--input-bg);width:100%;color:var(--sg-text);font-size:var(--primary-font);padding:8px}.input-field--invalid,.input-field[aria-invalid=true]{background-color:var(--sg-danger-soft);border-color:var(--sg-danger)}.sg-field{font-family:var(--font-family);flex-direction:column;gap:4px;margin-bottom:16px;display:flex}.sg-field .input-label,.sg-field .input-wrapper{margin-bottom:0}.sg-field-hint,.sg-field-error{margin:0;font-size:12px}.sg-field-hint{color:var(--sg-text-muted)}.sg-field-error{color:var(--sg-danger)}.sg-tabs{--tabs-gap:4px;gap:var(--tabs-gap);font-family:var(--font-family);-webkit-overflow-scrolling:touch;display:flex;overflow-x:auto}.sg-tab{color:var(--sg-text-muted);font:inherit;font-size:var(--primary-font);white-space:nowrap;cursor:pointer;transition:background .15s var(--button-ease-standard), color .15s var(--button-ease-standard);background:0 0;border:none;flex:none;padding:8px 16px}.sg-tab:disabled{opacity:.5;cursor:default}.sg-tab:focus-visible{outline:2px solid var(--sg-accent-strong);outline-offset:2px}.sg-tabs--underline{--tabs-gap:8px;border-bottom:1px solid var(--sg-border)}.sg-tabs--underline .sg-tab{border-bottom:2px solid #0000;margin-bottom:-1px}.sg-tabs--underline .sg-tab:hover:not(:disabled){color:var(--sg-text)}.sg-tabs--underline .sg-tab--active{border-bottom-color:var(--sg-accent-strong);color:var(--sg-accent-strong);font-weight:600}.sg-tabs--pills .sg-tab{background:var(--sg-surface-muted);color:var(--sg-text);border-radius:999px}.sg-tabs--pills .sg-tab:hover:not(:disabled):not(.sg-tab--active){background:var(--sg-surface-hover)}.sg-tabs--pills .sg-tab--active{background:var(--sg-accent);color:var(--sg-on-accent);box-shadow:var(--sg-shadow-1)}.sg-tabs--segmented{border:1px solid var(--sg-border);background:var(--sg-surface-muted);border-radius:999px;padding:4px}.sg-tabs--segmented .sg-tab{color:var(--sg-accent-strong);border-radius:999px;flex:1;padding:6px 16px;font-weight:600}.sg-tabs--segmented .sg-tab:hover:not(:disabled):not(.sg-tab--active){background:var(--sg-accent-soft)}.sg-tabs--segmented .sg-tab--active{background:var(--sg-accent);color:var(--sg-on-accent)}.sg-table-scroll{-webkit-overflow-scrolling:touch;overflow-x:auto}.sg-table{--table-border:var(--sg-border-subtle);--table-head-bg:var(--sg-surface-muted);--table-row-hover:var(--sg-surface-muted);--table-cell-padding:8px 12px;border-collapse:collapse;width:100%;color:var(--sg-text);font-family:var(--font-family);font-size:var(--primary-font)}.sg-table th,.sg-table td{padding:var(--table-cell-padding);border-bottom:1px solid var(--table-border);text-align:left;vertical-align:top}.sg-table th{background:var(--table-head-bg);color:var(--sg-text-secondary);text-transform:uppercase;letter-spacing:.03em;white-space:nowrap;font-size:12px;font-weight:600}.sg-table tbody tr:hover{background:var(--table-row-hover)}.sg-table .sg-table-num{text-align:right;font-variant-numeric:tabular-nums}.sg-version{color:var(--sg-text-muted);font-family:var(--font-family);text-align:center;margin:16px 0 0;font-size:12px}.sg-login-prompt{color:var(--sg-text-muted);font-family:var(--font-family);text-align:center;flex-direction:column;align-items:center;gap:16px;padding:48px 16px;display:flex}.sg-login-prompt-message{max-width:420px;font-size:var(--primary-font);margin:0;line-height:1.5}.sg-login-prompt-footer{font-size:13px}.sg-login-prompt-footer a{color:var(--sg-link)}.sg-auth-page{box-sizing:border-box;font-family:var(--font-family);flex-direction:column;align-items:center;gap:16px;padding:48px 16px;display:flex}.sg-auth-page-card{box-sizing:border-box;border:1px solid var(--sg-border-subtle);border-radius:calc(var(--radius) * 2);background:var(--sg-surface);width:100%;max-width:400px;box-shadow:var(--sg-shadow-1);color:var(--sg-text);padding:24px}.sg-auth-page-card p{margin:0 0 12px;line-height:1.5}.sg-auth-page-title{color:var(--sg-text-heading);font-size:var(--font-size-h1);margin:0 0 16px}.sg-auth-page-footer{font-size:13px}.sg-auth-page-footer a{color:var(--sg-link)}:root{--sg-color-white:#fff;--sg-color-black:#000;--sg-color-gray-50:#f5f5f5;--sg-color-gray-100:#e1e5e9;--sg-color-gray-150:#e0e0e0;--sg-color-gray-200:#e6e6e6;--sg-color-gray-300:#ccc;--sg-color-gray-350:#bdbdbd;--sg-color-gray-400:#9aa3b5;--sg-color-gray-500:#647089;--sg-color-gray-600:#555;--sg-color-gray-650:#444;--sg-color-gray-700:#333;--sg-color-gray-750:#2a2a2a;--sg-color-gray-800:#222;--sg-color-gray-900:#1a1a1a;--sg-color-blue-50:#e2e7f8;--sg-color-blue-300:#86aefc;--sg-color-blue-400:#6f9cf7;--sg-color-blue-500:#5480e6;--sg-color-blue-600:#3d5fc4;--sg-color-blue-700:#2e4aa0;--sg-color-sky-500:#1ea7fd;--sg-color-green-50:#e8f5e9;--sg-color-green-400:#66bb6a;--sg-color-green-700:#2e7d32;--sg-color-red-50:#ffe5e5;--sg-color-red-400:#e57373;--sg-color-red-600:#c0392b;--sg-bg:var(--sg-color-white);--sg-surface:var(--sg-color-white);--sg-surface-muted:var(--sg-color-gray-50);--sg-surface-hover:var(--sg-color-gray-150);--sg-border:var(--sg-color-gray-300);--sg-border-subtle:var(--sg-color-gray-100);--sg-text:var(--sg-color-gray-700);--sg-text-heading:var(--sg-color-gray-800);--sg-text-secondary:var(--sg-color-gray-600);--sg-text-muted:var(--sg-color-gray-500);--sg-accent:var(--sg-color-blue-600);--sg-accent-strong:var(--sg-color-blue-700);--sg-accent-soft:var(--sg-color-blue-50);--sg-on-accent:var(--sg-color-white);--sg-action:var(--sg-color-blue-400);--sg-action-hover:var(--sg-color-blue-500);--sg-link:var(--sg-color-sky-500);--sg-success:var(--sg-color-green-700);--sg-success-soft:var(--sg-color-green-50);--sg-danger:var(--sg-color-red-600);--sg-danger-soft:var(--sg-color-red-50);--sg-overlay:#0000004d;--sg-shadow-1:0 1px 2px #0f172a14, 0 1px 3px #0f172a0f;--sg-shadow-2:0 4px 12px #0f172a1f;--sg-shadow-3:0 2px 16px #00000026;--sg-action-shadow:0 1px 2px #5480e61f, 0 1px 3px #5480e61a;--unit:3px;--radius:calc(var(--unit) * 2);--font-size:14px;--font-family:Arial, sans-serif;--font-size-h1:calc(var(--font-size) * 1.5);--primary-bg:var(--sg-surface-muted);--primary-border:var(--sg-border);--primary-radius:var(--radius);--primary-font:var(--font-size);--primary-hover-bg:var(--sg-surface-hover);--modal-bg:var(--sg-surface);--modal-overlay:var(--sg-overlay);--modal-title-color:var(--sg-text-heading);--input-bg:var(--sg-surface);--input-border:var(--sg-border);--input-radius:var(--radius);--input-font:1rem;--button-bg:var(--sg-action);--button-bg-hover:var(--sg-action-hover);--button-color:var(--sg-on-accent);--button-radius:999px;--button-shadow:var(--sg-action-shadow);--button-ease-standard:cubic-bezier(.4, 0, .2, 1);--button-ease-bounce:cubic-bezier(.34, 1.56, .64, 1);--accent:var(--sg-accent);--accent-strong:var(--sg-accent-strong);--accent-soft:var(--sg-accent-soft);--ink-muted:var(--sg-text-muted);--shadow-1:var(--sg-shadow-1);--shadow-2:var(--sg-shadow-2)}:root[data-theme=dark]{--sg-bg:var(--sg-color-gray-900);--sg-surface:var(--sg-color-gray-800);--sg-surface-muted:var(--sg-color-gray-750);--sg-surface-hover:var(--sg-color-gray-700);--sg-border:var(--sg-color-gray-600);--sg-border-subtle:var(--sg-color-gray-650);--sg-text:var(--sg-color-gray-200);--sg-text-heading:var(--sg-color-white);--sg-text-secondary:var(--sg-color-gray-350);--sg-text-muted:var(--sg-color-gray-400);--sg-accent:var(--sg-color-blue-400);--sg-accent-strong:var(--sg-color-blue-300);--sg-accent-soft:#6f9cf72e;--sg-action-hover:var(--sg-color-blue-300);--sg-link:var(--sg-color-blue-300);--sg-success:var(--sg-color-green-400);--sg-success-soft:#66bb6a26;--sg-danger:var(--sg-color-red-400);--sg-danger-soft:#e5737326;--sg-overlay:#0009;--sg-shadow-1:0 1px 2px #0000004d, 0 1px 3px #0000003d;--sg-shadow-2:0 4px 12px #0006;--sg-shadow-3:0 2px 16px #00000080}.sg-register-form{flex-direction:column;display:flex}.sg-register-form .custom-button{width:100%}
2
2
  /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sensorario/sg-components",
3
- "version": "0.0.105",
3
+ "version": "0.0.107",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "scripts": {