From abfd2c4fae63acad0622ce856a752ea8af888410 Mon Sep 17 00:00:00 2001 From: Isaac Aracena Date: Fri, 14 Aug 2026 16:34:38 -0400 Subject: [PATCH] =?UTF-8?q?build:=20actualizar=20dist=20con=20la=20versi?= =?UTF-8?q?=C3=B3n=20de=20producci=C3=B3n=20m=C3=A1s=20reciente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-ACCESOS-CENTRALIZADOS-FINAL.md | 24 + README-LED-ACCESO-JEFE-INMEDIATO.md | 69 +++ SUPABASE-GLM-HUB-COMPLETO.sql | 226 ++++++-- ...B-FINAL-LED-JEFE-ACCESOS-CENTRALIZADOS.sql | 487 ++++++++++++++++++ ...BASE-GLM-HUB-LED-ACCESO-JEFE-INMEDIATO.sql | 487 ++++++++++++++++++ dist/assets/index-9ByAKvcq.css | 1 - dist/assets/index-CIGqNuJ5.css | 1 + dist/assets/index-CnXPZvfE.js | 179 +++++++ dist/assets/index-Kd6NFVcJ.js | 179 ------- dist/index.html | 4 +- ...GLM-Hub-Solicitudes-Acceso-Aprobacion.json | 313 +++++++---- scripts/build-static-esm.mjs | 7 +- src/App.tsx | 83 ++- src/repository.ts | 12 + src/styles.css | 72 ++- 15 files changed, 1794 insertions(+), 350 deletions(-) create mode 100644 README-ACCESOS-CENTRALIZADOS-FINAL.md create mode 100644 README-LED-ACCESO-JEFE-INMEDIATO.md create mode 100644 SUPABASE-GLM-HUB-FINAL-LED-JEFE-ACCESOS-CENTRALIZADOS.sql create mode 100644 SUPABASE-GLM-HUB-LED-ACCESO-JEFE-INMEDIATO.sql delete mode 100644 dist/assets/index-9ByAKvcq.css create mode 100644 dist/assets/index-CIGqNuJ5.css create mode 100644 dist/assets/index-CnXPZvfE.js delete mode 100644 dist/assets/index-Kd6NFVcJ.js diff --git a/README-ACCESOS-CENTRALIZADOS-FINAL.md b/README-ACCESOS-CENTRALIZADOS-FINAL.md new file mode 100644 index 0000000..fb2b62b --- /dev/null +++ b/README-ACCESOS-CENTRALIZADOS-FINAL.md @@ -0,0 +1,24 @@ +# GLM Hub · Accesos centralizados + +La versión final utiliza `public.glm_hub_app_access` como **registro informativo único para el LED del Hub**. Esta tabla no reemplaza el login ni los permisos reales de las aplicaciones. + +## Cómo se usa + +- **Aplicación abierta a todo GLM:** una fila con el nombre de la aplicación y `email = *`. +- **Aplicación restringida:** una fila por usuario con el nombre de la aplicación y su correo. +- **Revocar acceso en el Hub:** eliminar la fila o cambiar `is_active` a `false`. +- El `app_id` se completa automáticamente. Desde Supabase Table Editor solo necesitas completar `app_name` y `email`. + +## Flujo operativo + +Cuando IT otorgue acceso real a una aplicación restringida, debe agregar también al usuario en `glm_hub_app_access`. El Hub mostrará **Disponible** en verde. Si no existe un registro activo para ese usuario y tampoco existe una fila `*` para esa aplicación, mostrará **Sin acceso** en rojo. + +## Aplicaciones actuales + +El script final realiza una carga inicial automática: BambooHR, CDC Brief, cinco Cruces de Seguridad Social, Validación de IR - Nicaragua y GLM ID Card Generator quedan abiertos a todo GLM. CDC Project Management se copia inicialmente desde `tablero_cdc_allowed_users`; Portal de Verificación de Nóminas desde `cruce_cuentas_usuarios_autorizados`; y Seguimiento de Impuestos GLM desde `tax_calendar_access`. + +Después de esa carga inicial, la fuente del LED es únicamente `glm_hub_app_access`. Los logins de las aplicaciones siguen funcionando como hoy. + +## n8n + +No se necesita ninguna modificación adicional en n8n para la tabla central. El workflow de solicitudes incluido en el ZIP conserva la mejora previa del jefe inmediato. diff --git a/README-LED-ACCESO-JEFE-INMEDIATO.md b/README-LED-ACCESO-JEFE-INMEDIATO.md new file mode 100644 index 0000000..2cdb27d --- /dev/null +++ b/README-LED-ACCESO-JEFE-INMEDIATO.md @@ -0,0 +1,69 @@ +# GLM Hub — LED de acceso + jefe inmediato + +## Qué cambia + +Esta versión agrega dos mejoras sin cambiar el modelo actual de autenticación del Hub: + +1. Cada aplicación publicada muestra el estado **Con acceso / Sin acceso** del usuario conectado. +2. Las solicitudes de acceso se envían a **Isaac Aracena, José Leopoldo Gómez, Máximo Gómez y al jefe inmediato del solicitante**, cuando `empleados_glm.supervisor_email` está disponible. + +La primera decisión registrada sigue siendo definitiva para todos los aprobadores. + +## Fuentes de acceso utilizadas + +El Hub no replica los permisos de las aplicaciones restringidas: consulta su fuente real en Supabase. + +- **CDC Project Management** → `tablero_cdc_allowed_users` (`email`, `is_active`). +- **Portal de Verificación de Nóminas** → `cruce_cuentas_usuarios_autorizados` (`email`). +- **Seguimiento de Impuestos GLM** → `tax_calendar_access` (`email`, `active`). +- **BambooHR, CDC Brief, los 5 Cruces de Seguridad Social, Validación de IR - Nicaragua y GLM ID Card Generator** → acceso general para usuarios autenticados `@gomezleemarketing.com`. +- Cualquier aplicación futura que no esté clasificada se muestra por seguridad como **Sin acceso** hasta agregar su regla al RPC. + +El estado se vuelve a comprobar al iniciar sesión, cada 60 segundos y cuando el usuario vuelve a enfocar la pestaña del Hub. + +## Orden de implementación + +### 1. Supabase + +Ejecutar completo: + +`SUPABASE-GLM-HUB-LED-ACCESO-JEFE-INMEDIATO.sql` + +Este script: + +- elimina la restricción que limitaba los aprobadores a tres correos exactos; +- conserva a los tres aprobadores base; +- obtiene el jefe desde `empleados_glm.work_email → supervisor_email`; +- evita duplicados; +- no rompe la solicitud si el jefe no está disponible; +- crea el RPC `glm_hub_get_my_app_access()` para el LED. + +### 2. n8n + +Actualizar el workflow **GLM Hub - Solicitudes de acceso y aprobación** con: + +`n8n/GLM-Hub-Solicitudes-Acceso-Aprobacion.json` + +No se modificó el workflow de Gemini. Tampoco se cambió la forma actual en que el workflow usa las credenciales/keys de Supabase, por solicitud expresa. + +### 3. Frontend + +Publicar el contenido nuevo de `dist/` en el mismo subdominio del GLM Hub. + +## Prueba recomendada + +1. Iniciar sesión con un usuario GLM que no sea administrador. +2. Confirmar que cada app muestre **Con acceso** o **Sin acceso**. +3. Verificar un usuario presente y otro ausente en cada una de las tres tablas restringidas. +4. Enviar una solicitud de acceso. +5. En la ejecución de n8n, revisar `Emitir enlaces de aprobación`: debe devolver 3 aprobadores base y, cuando exista, un cuarto aprobador correspondiente al `supervisor_email`. +6. Confirmar que todos reciban su correo. +7. Aprobar con uno de ellos y comprobar que un segundo intento muestre que la solicitud ya fue atendida. +8. Agregar/eliminar al usuario en la tabla real de una app restringida y volver al Hub; al recuperar el foco (o como máximo en 60 segundos) el LED debe actualizarse. + +## Comportamiento de seguridad + +- Un usuario sin registro en `glm_hub_authorized_users` sigue entrando al Hub si pertenece a `@gomezleemarketing.com`. +- `glm_hub_authorized_users` continúa usándose para administradores y bloqueos excepcionales. +- El LED es informativo: no sustituye la protección interna de cada aplicación. +- Las aplicaciones no clasificadas no se marcan automáticamente como autorizadas. diff --git a/SUPABASE-GLM-HUB-COMPLETO.sql b/SUPABASE-GLM-HUB-COMPLETO.sql index 98b42d2..3f893c5 100644 --- a/SUPABASE-GLM-HUB-COMPLETO.sql +++ b/SUPABASE-GLM-HUB-COMPLETO.sql @@ -546,13 +546,10 @@ create table if not exists public.glm_hub_access_request_approvers ( clicked_at timestamptz, created_at timestamptz not null default now(), - constraint glm_hub_access_request_approvers_email_check + constraint glm_hub_access_request_approvers_email_normalized_check check ( - approver_email in ( - 'iaracena@gomezleemarketing.com', - 'jgomez@gomezleemarketing.com', - 'mgomez@gomezleemarketing.com' - ) + approver_email = lower(btrim(approver_email)) + and approver_email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' ), constraint glm_hub_access_request_approvers_unique_request_email unique (request_id, approver_email) @@ -696,8 +693,9 @@ revoke all on function public.glm_hub_prepare_access_request(uuid) from public, grant execute on function public.glm_hub_prepare_access_request(uuid) to authenticated; grant execute on function public.glm_hub_prepare_access_request(uuid) to service_role; --- Emite o recupera los tres enlaces de decisión. Solo n8n, usando la clave --- service_role guardada en su nodo HTTP Request, puede ejecutar esta función. +-- Emite o recupera los enlaces de decisión para los tres aprobadores base y, +-- cuando está disponible, para el jefe inmediato del solicitante. Solo n8n, +-- usando la clave service_role guardada en su nodo HTTP Request, puede ejecutar esta función. create or replace function public.glm_hub_issue_access_request_tokens(p_request_id uuid) returns jsonb language plpgsql @@ -707,9 +705,6 @@ set search_path = '' as $$ declare v_request public.glm_hub_access_requests%rowtype; - v_token_isaac text; - v_token_jose text; - v_token_maximo text; begin select request.* into v_request @@ -722,45 +717,72 @@ begin return jsonb_build_object('ok', false, 'error', 'La solicitud no existe o ya fue atendida.'); end if; - if not exists ( - select 1 - from public.glm_hub_access_request_approvers as approver - where approver.request_id = p_request_id - ) then - v_token_isaac := encode(extensions.gen_random_bytes(32), 'hex'); - v_token_jose := encode(extensions.gen_random_bytes(32), 'hex'); - v_token_maximo := encode(extensions.gen_random_bytes(32), 'hex'); - - insert into public.glm_hub_access_request_approvers ( - request_id, + with supervisor_candidate as ( + select + coalesce( + nullif(btrim(employee.supervisor), ''), + nullif(btrim(supervisor_employee.name), ''), + split_part(lower(btrim(employee.supervisor_email)), '@', 1) + ) as approver_name, + lower(btrim(employee.supervisor_email)) as approver_email, + 40 as priority + from public.empleados_glm as employee + left join public.empleados_glm as supervisor_employee + on lower(btrim(supervisor_employee.work_email)) = lower(btrim(employee.supervisor_email)) + where lower(btrim(employee.work_email)) = v_request.requester_email + and nullif(btrim(employee.supervisor_email), '') is not null + order by + case when employee.status::text = 'Active' then 0 else 1 end, + employee.id + limit 1 + ), + candidate_approvers as ( + select 'Isaac Aracena'::text as approver_name, + 'iaracena@gomezleemarketing.com'::text as approver_email, + 10 as priority + union all + select 'José Leopoldo Gómez', 'jgomez@gomezleemarketing.com', 20 + union all + select 'Máximo Gómez', 'mgomez@gomezleemarketing.com', 30 + union all + select approver_name, approver_email, priority + from supervisor_candidate + ), + deduplicated as ( + select distinct on (approver_email) approver_name, approver_email, - decision_token, - decision_token_hash - ) - values - ( - p_request_id, - 'Isaac Aracena', - 'iaracena@gomezleemarketing.com', - v_token_isaac, - encode(extensions.digest(v_token_isaac, 'sha256'), 'hex') - ), - ( - p_request_id, - 'José Leopoldo Gómez', - 'jgomez@gomezleemarketing.com', - v_token_jose, - encode(extensions.digest(v_token_jose, 'sha256'), 'hex') - ), - ( - p_request_id, - 'Máximo Gómez', - 'mgomez@gomezleemarketing.com', - v_token_maximo, - encode(extensions.digest(v_token_maximo, 'sha256'), 'hex') - ); - end if; + priority + from candidate_approvers + where approver_email is not null + and approver_email <> '' + and approver_email <> v_request.requester_email + and approver_email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' + order by approver_email, priority + ), + tokenized as ( + select + approver_name, + approver_email, + priority, + encode(extensions.gen_random_bytes(32), 'hex') as decision_token + from deduplicated + ) + insert into public.glm_hub_access_request_approvers ( + request_id, + approver_name, + approver_email, + decision_token, + decision_token_hash + ) + select + p_request_id, + tokenized.approver_name, + tokenized.approver_email, + tokenized.decision_token, + encode(extensions.digest(tokenized.decision_token, 'sha256'), 'hex') + from tokenized + on conflict (request_id, approver_email) do nothing; return jsonb_build_object( 'ok', true, @@ -770,13 +792,23 @@ begin 'appName', v_request.app_name, 'appCategory', v_request.app_category, 'approvers', ( - select jsonb_agg( - jsonb_build_object( - 'name', approver.approver_name, - 'email', approver.approver_email, - 'token', approver.decision_token - ) - order by approver.approver_email + select coalesce( + jsonb_agg( + jsonb_build_object( + 'name', approver.approver_name, + 'email', approver.approver_email, + 'token', approver.decision_token + ) + order by + case approver.approver_email + when 'iaracena@gomezleemarketing.com' then 1 + when 'jgomez@gomezleemarketing.com' then 2 + when 'mgomez@gomezleemarketing.com' then 3 + else 4 + end, + approver.approver_email + ), + '[]'::jsonb ) from public.glm_hub_access_request_approvers as approver where approver.request_id = p_request_id @@ -886,7 +918,89 @@ grant execute on function public.glm_hub_decide_access_request(text, text) to au grant execute on function public.glm_hub_decide_access_request(text, text) to service_role; -- -------------------------------------------------------------------------- --- 7. REALTIME DEL CATÁLOGO +-- 7. ESTADO DE ACCESO POR APLICACIÓN +-- -------------------------------------------------------------------------- + +create or replace function public.glm_hub_get_my_app_access() +returns table ( + app_id uuid, + app_name text, + has_access boolean +) +language plpgsql +stable +security definer +set search_path = '' +as $$ +declare + v_email text; +begin + v_email := lower(btrim(coalesce(auth.jwt() ->> 'email', ''))); + + if auth.uid() is null or v_email = '' then + return; + end if; + + if v_email !~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@gomezleemarketing\.com$' then + return; + end if; + + return query + select + app.id, + app.name, + case + -- Aplicaciones restringidas: consultar su fuente real de autorización. + when lower(btrim(app.name)) = 'cdc project management' then exists ( + select 1 + from public.tablero_cdc_allowed_users as allowed_user + where lower(btrim(allowed_user.email)) = v_email + and coalesce(allowed_user.is_active, false) = true + ) + + when lower(btrim(app.name)) = 'portal de verificación de nóminas' then exists ( + select 1 + from public.cruce_cuentas_usuarios_autorizados as allowed_user + where lower(btrim(allowed_user.email)) = v_email + ) + + when lower(btrim(app.name)) = 'seguimiento de impuestos glm' then exists ( + select 1 + from public.tax_calendar_access as allowed_user + where lower(btrim(allowed_user.email)) = v_email + and coalesce(allowed_user.active, false) = true + ) + + -- Aplicaciones disponibles para cualquier usuario GLM autenticado. + when lower(btrim(app.name)) in ( + 'bamboohr', + 'cdc brief', + 'cruce de seguridad social - honduras', + 'cruce de seguridad social - guatemala', + 'cruce de seguridad social - costa rica', + 'cruce de seguridad social - república dominicana', + 'cruce de seguridad social - el salvador', + 'validación de ir - nicaragua', + 'glm id card generator' + ) then true + + -- Seguridad por defecto: una aplicación nueva/no clasificada nunca se + -- muestra como autorizada hasta definir su fuente de permisos. + else false + end as has_access + from public.glm_hub_apps as app + where app.visibility = 'published' + order by app.name; +end; +$$; + +alter function public.glm_hub_get_my_app_access() owner to postgres; +revoke all on function public.glm_hub_get_my_app_access() from public, anon; +grant execute on function public.glm_hub_get_my_app_access() to authenticated; +grant execute on function public.glm_hub_get_my_app_access() to service_role; + +-- -------------------------------------------------------------------------- +-- 8. REALTIME DEL CATÁLOGO -- -------------------------------------------------------------------------- -- Hace que una aplicación creada/editada/eliminada por un administrador diff --git a/SUPABASE-GLM-HUB-FINAL-LED-JEFE-ACCESOS-CENTRALIZADOS.sql b/SUPABASE-GLM-HUB-FINAL-LED-JEFE-ACCESOS-CENTRALIZADOS.sql new file mode 100644 index 0000000..1f84d79 --- /dev/null +++ b/SUPABASE-GLM-HUB-FINAL-LED-JEFE-ACCESOS-CENTRALIZADOS.sql @@ -0,0 +1,487 @@ +-- ============================================================================ +-- GLM HUB · VERSIÓN FINAL +-- LED DE DISPONIBILIDAD + REGISTRO CENTRAL DE ACCESOS + JEFE INMEDIATO +-- GomezLee Marketing +-- Fecha: 2026-08-14 +-- +-- OBJETIVO +-- 1) Mantener a Isaac + José Leopoldo + Máximo como aprobadores base. +-- 2) Agregar al jefe inmediato desde empleados_glm.supervisor_email. +-- 3) Crear UNA tabla central que el Hub usa únicamente para saber si debe mostrar +-- "Disponible" o "Sin acceso". +-- 4) NO modifica el login ni los permisos reales de ninguna aplicación. +-- 5) NO modifica claves, credenciales ni configuración de EasyPanel/n8n. +-- +-- TABLA CENTRAL +-- public.glm_hub_app_access +-- app_name = nombre visible de la aplicación en el Hub +-- email = correo autorizado +-- email='*' significa que TODOS los usuarios @gomezleemarketing.com tienen acceso +-- is_active=false permite desactivar el registro sin borrarlo +-- +-- OPERACIÓN FUTURA +-- - App abierta a todo GLM: agregar una fila con app_name + email='*'. +-- - App restringida: agregar una fila por usuario con app_name + su correo. +-- - Revocar: borrar la fila o cambiar is_active a false. +-- ============================================================================ + +begin; + +-- -------------------------------------------------------------------------- +-- 1. APROBADORES DINÁMICOS: 3 BASE + JEFE INMEDIATO +-- -------------------------------------------------------------------------- + +alter table public.glm_hub_access_request_approvers + drop constraint if exists glm_hub_access_request_approvers_email_check; + +alter table public.glm_hub_access_request_approvers + drop constraint if exists glm_hub_access_request_approvers_email_normalized_check; + +alter table public.glm_hub_access_request_approvers + add constraint glm_hub_access_request_approvers_email_normalized_check + check ( + approver_email = lower(btrim(approver_email)) + and approver_email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' + ); + +create or replace function public.glm_hub_issue_access_request_tokens(p_request_id uuid) +returns jsonb +language plpgsql +volatile +security definer +set search_path = '' +as $$ +declare + v_request public.glm_hub_access_requests%rowtype; +begin + select request.* + into v_request + from public.glm_hub_access_requests as request + where request.id = p_request_id + and request.status = 'pending' + for update; + + if not found then + return jsonb_build_object('ok', false, 'error', 'La solicitud no existe o ya fue atendida.'); + end if; + + with supervisor_candidate as ( + select + coalesce( + nullif(btrim(employee.supervisor), ''), + nullif(btrim(supervisor_employee.name), ''), + split_part(lower(btrim(employee.supervisor_email)), '@', 1) + ) as approver_name, + lower(btrim(employee.supervisor_email)) as approver_email, + 40 as priority + from public.empleados_glm as employee + left join public.empleados_glm as supervisor_employee + on lower(btrim(supervisor_employee.work_email)) = lower(btrim(employee.supervisor_email)) + where lower(btrim(employee.work_email)) = v_request.requester_email + and nullif(btrim(employee.supervisor_email), '') is not null + order by + case when employee.status::text = 'Active' then 0 else 1 end, + employee.id + limit 1 + ), + candidate_approvers as ( + select 'Isaac Aracena'::text as approver_name, + 'iaracena@gomezleemarketing.com'::text as approver_email, + 10 as priority + union all + select 'José Leopoldo Gómez', 'jgomez@gomezleemarketing.com', 20 + union all + select 'Máximo Gómez', 'mgomez@gomezleemarketing.com', 30 + union all + select approver_name, approver_email, priority + from supervisor_candidate + ), + deduplicated as ( + select distinct on (approver_email) + approver_name, + approver_email, + priority + from candidate_approvers + where approver_email is not null + and approver_email <> '' + and approver_email <> v_request.requester_email + and approver_email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' + order by approver_email, priority + ), + tokenized as ( + select + approver_name, + approver_email, + priority, + encode(extensions.gen_random_bytes(32), 'hex') as decision_token + from deduplicated + ) + insert into public.glm_hub_access_request_approvers ( + request_id, + approver_name, + approver_email, + decision_token, + decision_token_hash + ) + select + p_request_id, + tokenized.approver_name, + tokenized.approver_email, + tokenized.decision_token, + encode(extensions.digest(tokenized.decision_token, 'sha256'), 'hex') + from tokenized + on conflict (request_id, approver_email) do nothing; + + return jsonb_build_object( + 'ok', true, + 'requestId', v_request.id, + 'requesterName', v_request.requester_name, + 'requesterEmail', v_request.requester_email, + 'appName', v_request.app_name, + 'appCategory', v_request.app_category, + 'approvers', ( + select coalesce( + jsonb_agg( + jsonb_build_object( + 'name', approver.approver_name, + 'email', approver.approver_email, + 'token', approver.decision_token + ) + order by + case approver.approver_email + when 'iaracena@gomezleemarketing.com' then 1 + when 'jgomez@gomezleemarketing.com' then 2 + when 'mgomez@gomezleemarketing.com' then 3 + else 4 + end, + approver.approver_email + ), + '[]'::jsonb + ) + from public.glm_hub_access_request_approvers as approver + where approver.request_id = p_request_id + ) + ); +end; +$$; + +alter function public.glm_hub_issue_access_request_tokens(uuid) owner to postgres; +revoke all on function public.glm_hub_issue_access_request_tokens(uuid) from public, anon, authenticated; +grant execute on function public.glm_hub_issue_access_request_tokens(uuid) to service_role; + +-- -------------------------------------------------------------------------- +-- 2. TABLA CENTRAL DE ACCESOS DEL HUB +-- -------------------------------------------------------------------------- +-- Esta tabla es INFORMATIVA para el Hub. No sustituye el login/seguridad real +-- de cada aplicación. +-- +-- app_id es rellenado automáticamente a partir de app_name, de forma que desde +-- el Table Editor basta con escribir el nombre de la app y el correo. +-- -------------------------------------------------------------------------- + +create table if not exists public.glm_hub_app_access ( + id uuid primary key default extensions.gen_random_uuid(), + app_name text not null, + email text not null, + is_active boolean not null default true, + app_id uuid references public.glm_hub_apps(id) on delete cascade, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now(), + constraint glm_hub_app_access_email_check + check ( + email = '*' + or email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' + ) +); + +comment on table public.glm_hub_app_access is + 'Registro central informativo de accesos mostrado por GLM Hub. No reemplaza los permisos reales de cada aplicación.'; +comment on column public.glm_hub_app_access.app_name is + 'Nombre de la aplicación tal como aparece en glm_hub_apps.'; +comment on column public.glm_hub_app_access.email is + 'Correo autorizado. El valor * significa todos los usuarios GLM autenticados.'; +comment on column public.glm_hub_app_access.is_active is + 'TRUE = acceso mostrado como Disponible; FALSE = registro desactivado.'; +comment on column public.glm_hub_app_access.app_id is + 'Se completa automáticamente usando app_name.'; + +create unique index if not exists glm_hub_app_access_app_email_uidx + on public.glm_hub_app_access (app_id, email); + +create index if not exists glm_hub_app_access_email_idx + on public.glm_hub_app_access (email) + where is_active = true; + +-- Normaliza correos y permite trabajar por nombre de aplicación desde Table Editor. +create or replace function public.glm_hub_app_access_prepare_row() +returns trigger +language plpgsql +security definer +set search_path = '' +as $$ +declare + v_app_id uuid; + v_app_name text; +begin + new.app_name := btrim(coalesce(new.app_name, '')); + new.email := lower(btrim(coalesce(new.email, ''))); + + if new.app_name = '' then + raise exception 'Debes indicar app_name.'; + end if; + + if new.email = '' then + raise exception 'Debes indicar email. Usa * si la aplicación está disponible para todo GLM.'; + end if; + + -- Si el usuario cambió app_name manualmente, ese nombre manda y se resuelve + -- nuevamente el UUID. En INSERT también permite dejar app_id vacío. + if tg_op = 'INSERT' then + select app.id, app.name + into v_app_id, v_app_name + from public.glm_hub_apps as app + where lower(btrim(app.name)) = lower(new.app_name) + order by app.created_at + limit 1; + + if v_app_id is null then + raise exception 'No existe una aplicación en GLM Hub llamada "%".', new.app_name; + end if; + + new.app_id := v_app_id; + new.app_name := v_app_name; + elsif new.app_id is null or new.app_name is distinct from old.app_name then + select app.id, app.name + into v_app_id, v_app_name + from public.glm_hub_apps as app + where lower(btrim(app.name)) = lower(new.app_name) + order by app.created_at + limit 1; + + if v_app_id is null then + raise exception 'No existe una aplicación en GLM Hub llamada "%".', new.app_name; + end if; + + new.app_id := v_app_id; + new.app_name := v_app_name; + else + select app.name + into v_app_name + from public.glm_hub_apps as app + where app.id = new.app_id; + + if v_app_name is null then + raise exception 'El app_id indicado no existe en glm_hub_apps.'; + end if; + + new.app_name := v_app_name; + end if; + + new.updated_at := now(); + return new; +end; +$$; + +drop trigger if exists glm_hub_app_access_prepare_row_trigger + on public.glm_hub_app_access; + +create trigger glm_hub_app_access_prepare_row_trigger +before insert or update on public.glm_hub_app_access +for each row +execute function public.glm_hub_app_access_prepare_row(); + +-- Si un administrador cambia el nombre de una app en el Hub, el nombre visible +-- de los registros centrales se mantiene sincronizado por app_id. +create or replace function public.glm_hub_sync_access_app_name() +returns trigger +language plpgsql +security definer +set search_path = '' +as $$ +begin + if new.name is distinct from old.name then + update public.glm_hub_app_access + set app_name = new.name, + updated_at = now() + where app_id = new.id; + end if; + return new; +end; +$$; + +drop trigger if exists glm_hub_sync_access_app_name_trigger + on public.glm_hub_apps; + +create trigger glm_hub_sync_access_app_name_trigger +after update of name on public.glm_hub_apps +for each row +execute function public.glm_hub_sync_access_app_name(); + +-- Nadie necesita leer esta tabla directamente desde el navegador. El frontend +-- consulta únicamente el RPC seguro glm_hub_get_my_app_access(). +alter table public.glm_hub_app_access enable row level security; +revoke all on table public.glm_hub_app_access from anon, authenticated; +grant all on table public.glm_hub_app_access to service_role; + +-- -------------------------------------------------------------------------- +-- 3. CARGA INICIAL DE LOS ACCESOS ACTUALES +-- -------------------------------------------------------------------------- +-- A) Apps abiertas para cualquier usuario GLM -> una sola fila con email='*'. +-- -------------------------------------------------------------------------- + +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select app.id, app.name, '*', true +from public.glm_hub_apps as app +where lower(btrim(app.name)) in ( + 'bamboohr', + 'cdc brief', + 'cruce de seguridad social - honduras', + 'cruce de seguridad social - guatemala', + 'cruce de seguridad social - costa rica', + 'cruce de seguridad social - república dominicana', + 'cruce de seguridad social - el salvador', + 'validación de ir - nicaragua', + 'glm id card generator' +) +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- B) CDC Project Management -> snapshot inicial desde tablero_cdc_allowed_users. +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select + app.id, + app.name, + lower(btrim(allowed_user.email)), + true +from public.glm_hub_apps as app +cross join public.tablero_cdc_allowed_users as allowed_user +where lower(btrim(app.name)) = 'cdc project management' + and nullif(btrim(allowed_user.email), '') is not null + and coalesce(allowed_user.is_active, false) = true +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- C) Portal de Verificación de Nóminas -> snapshot inicial desde la tabla actual. +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select + app.id, + app.name, + lower(btrim(allowed_user.email)), + true +from public.glm_hub_apps as app +cross join public.cruce_cuentas_usuarios_autorizados as allowed_user +where lower(btrim(app.name)) = 'portal de verificación de nóminas' + and nullif(btrim(allowed_user.email), '') is not null +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- D) Seguimiento de Impuestos GLM -> snapshot inicial desde tax_calendar_access. +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select + app.id, + app.name, + lower(btrim(allowed_user.email)), + true +from public.glm_hub_apps as app +cross join public.tax_calendar_access as allowed_user +where lower(btrim(app.name)) = 'seguimiento de impuestos glm' + and nullif(btrim(allowed_user.email), '') is not null + and coalesce(allowed_user.active, false) = true +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- -------------------------------------------------------------------------- +-- 4. RPC FINAL PARA EL LED DEL HUB +-- -------------------------------------------------------------------------- +-- El Hub ya NO consulta las tablas particulares de cada aplicación. +-- Solo lee este registro central. +-- -------------------------------------------------------------------------- + +create or replace function public.glm_hub_get_my_app_access() +returns table ( + app_id uuid, + app_name text, + has_access boolean +) +language plpgsql +stable +security definer +set search_path = '' +as $$ +declare + v_email text; +begin + v_email := lower(btrim(coalesce(auth.jwt() ->> 'email', ''))); + + if auth.uid() is null or v_email = '' then + return; + end if; + + -- El GLM Hub continúa reservado al dominio corporativo principal. + if v_email !~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@gomezleemarketing\.com$' then + return; + end if; + + return query + select + app.id, + app.name, + exists ( + select 1 + from public.glm_hub_app_access as access_row + where access_row.app_id = app.id + and access_row.is_active = true + and ( + access_row.email = '*' + or access_row.email = v_email + ) + ) as has_access + from public.glm_hub_apps as app + where app.visibility = 'published' + order by app.name; +end; +$$; + +alter function public.glm_hub_get_my_app_access() owner to postgres; +revoke all on function public.glm_hub_get_my_app_access() from public, anon; +grant execute on function public.glm_hub_get_my_app_access() to authenticated; +grant execute on function public.glm_hub_get_my_app_access() to service_role; + +commit; + +-- ============================================================================ +-- VERIFICACIONES OPCIONALES DESPUÉS DE EJECUTAR +-- ============================================================================ + +-- Ver toda la matriz central: +-- select app_name, email, is_active +-- from public.glm_hub_app_access +-- order by app_name, email; + +-- Agregar acceso individual a una futura app restringida DESDE SQL: +-- insert into public.glm_hub_app_access (app_name, email) +-- values ('Nombre exacto de la aplicación', 'usuario@gomezleemarketing.com'); +-- +-- En el Table Editor puedes hacer exactamente lo mismo dejando app_id vacío. + +-- Marcar una futura app como abierta para todo GLM: +-- insert into public.glm_hub_app_access (app_name, email) +-- values ('Nombre exacto de la aplicación', '*'); + +-- Revocar sin borrar historial: +-- update public.glm_hub_app_access +-- set is_active = false +-- where lower(app_name) = lower('Nombre exacto de la aplicación') +-- and email = 'usuario@gomezleemarketing.com'; diff --git a/SUPABASE-GLM-HUB-LED-ACCESO-JEFE-INMEDIATO.sql b/SUPABASE-GLM-HUB-LED-ACCESO-JEFE-INMEDIATO.sql new file mode 100644 index 0000000..1f84d79 --- /dev/null +++ b/SUPABASE-GLM-HUB-LED-ACCESO-JEFE-INMEDIATO.sql @@ -0,0 +1,487 @@ +-- ============================================================================ +-- GLM HUB · VERSIÓN FINAL +-- LED DE DISPONIBILIDAD + REGISTRO CENTRAL DE ACCESOS + JEFE INMEDIATO +-- GomezLee Marketing +-- Fecha: 2026-08-14 +-- +-- OBJETIVO +-- 1) Mantener a Isaac + José Leopoldo + Máximo como aprobadores base. +-- 2) Agregar al jefe inmediato desde empleados_glm.supervisor_email. +-- 3) Crear UNA tabla central que el Hub usa únicamente para saber si debe mostrar +-- "Disponible" o "Sin acceso". +-- 4) NO modifica el login ni los permisos reales de ninguna aplicación. +-- 5) NO modifica claves, credenciales ni configuración de EasyPanel/n8n. +-- +-- TABLA CENTRAL +-- public.glm_hub_app_access +-- app_name = nombre visible de la aplicación en el Hub +-- email = correo autorizado +-- email='*' significa que TODOS los usuarios @gomezleemarketing.com tienen acceso +-- is_active=false permite desactivar el registro sin borrarlo +-- +-- OPERACIÓN FUTURA +-- - App abierta a todo GLM: agregar una fila con app_name + email='*'. +-- - App restringida: agregar una fila por usuario con app_name + su correo. +-- - Revocar: borrar la fila o cambiar is_active a false. +-- ============================================================================ + +begin; + +-- -------------------------------------------------------------------------- +-- 1. APROBADORES DINÁMICOS: 3 BASE + JEFE INMEDIATO +-- -------------------------------------------------------------------------- + +alter table public.glm_hub_access_request_approvers + drop constraint if exists glm_hub_access_request_approvers_email_check; + +alter table public.glm_hub_access_request_approvers + drop constraint if exists glm_hub_access_request_approvers_email_normalized_check; + +alter table public.glm_hub_access_request_approvers + add constraint glm_hub_access_request_approvers_email_normalized_check + check ( + approver_email = lower(btrim(approver_email)) + and approver_email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' + ); + +create or replace function public.glm_hub_issue_access_request_tokens(p_request_id uuid) +returns jsonb +language plpgsql +volatile +security definer +set search_path = '' +as $$ +declare + v_request public.glm_hub_access_requests%rowtype; +begin + select request.* + into v_request + from public.glm_hub_access_requests as request + where request.id = p_request_id + and request.status = 'pending' + for update; + + if not found then + return jsonb_build_object('ok', false, 'error', 'La solicitud no existe o ya fue atendida.'); + end if; + + with supervisor_candidate as ( + select + coalesce( + nullif(btrim(employee.supervisor), ''), + nullif(btrim(supervisor_employee.name), ''), + split_part(lower(btrim(employee.supervisor_email)), '@', 1) + ) as approver_name, + lower(btrim(employee.supervisor_email)) as approver_email, + 40 as priority + from public.empleados_glm as employee + left join public.empleados_glm as supervisor_employee + on lower(btrim(supervisor_employee.work_email)) = lower(btrim(employee.supervisor_email)) + where lower(btrim(employee.work_email)) = v_request.requester_email + and nullif(btrim(employee.supervisor_email), '') is not null + order by + case when employee.status::text = 'Active' then 0 else 1 end, + employee.id + limit 1 + ), + candidate_approvers as ( + select 'Isaac Aracena'::text as approver_name, + 'iaracena@gomezleemarketing.com'::text as approver_email, + 10 as priority + union all + select 'José Leopoldo Gómez', 'jgomez@gomezleemarketing.com', 20 + union all + select 'Máximo Gómez', 'mgomez@gomezleemarketing.com', 30 + union all + select approver_name, approver_email, priority + from supervisor_candidate + ), + deduplicated as ( + select distinct on (approver_email) + approver_name, + approver_email, + priority + from candidate_approvers + where approver_email is not null + and approver_email <> '' + and approver_email <> v_request.requester_email + and approver_email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' + order by approver_email, priority + ), + tokenized as ( + select + approver_name, + approver_email, + priority, + encode(extensions.gen_random_bytes(32), 'hex') as decision_token + from deduplicated + ) + insert into public.glm_hub_access_request_approvers ( + request_id, + approver_name, + approver_email, + decision_token, + decision_token_hash + ) + select + p_request_id, + tokenized.approver_name, + tokenized.approver_email, + tokenized.decision_token, + encode(extensions.digest(tokenized.decision_token, 'sha256'), 'hex') + from tokenized + on conflict (request_id, approver_email) do nothing; + + return jsonb_build_object( + 'ok', true, + 'requestId', v_request.id, + 'requesterName', v_request.requester_name, + 'requesterEmail', v_request.requester_email, + 'appName', v_request.app_name, + 'appCategory', v_request.app_category, + 'approvers', ( + select coalesce( + jsonb_agg( + jsonb_build_object( + 'name', approver.approver_name, + 'email', approver.approver_email, + 'token', approver.decision_token + ) + order by + case approver.approver_email + when 'iaracena@gomezleemarketing.com' then 1 + when 'jgomez@gomezleemarketing.com' then 2 + when 'mgomez@gomezleemarketing.com' then 3 + else 4 + end, + approver.approver_email + ), + '[]'::jsonb + ) + from public.glm_hub_access_request_approvers as approver + where approver.request_id = p_request_id + ) + ); +end; +$$; + +alter function public.glm_hub_issue_access_request_tokens(uuid) owner to postgres; +revoke all on function public.glm_hub_issue_access_request_tokens(uuid) from public, anon, authenticated; +grant execute on function public.glm_hub_issue_access_request_tokens(uuid) to service_role; + +-- -------------------------------------------------------------------------- +-- 2. TABLA CENTRAL DE ACCESOS DEL HUB +-- -------------------------------------------------------------------------- +-- Esta tabla es INFORMATIVA para el Hub. No sustituye el login/seguridad real +-- de cada aplicación. +-- +-- app_id es rellenado automáticamente a partir de app_name, de forma que desde +-- el Table Editor basta con escribir el nombre de la app y el correo. +-- -------------------------------------------------------------------------- + +create table if not exists public.glm_hub_app_access ( + id uuid primary key default extensions.gen_random_uuid(), + app_name text not null, + email text not null, + is_active boolean not null default true, + app_id uuid references public.glm_hub_apps(id) on delete cascade, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now(), + constraint glm_hub_app_access_email_check + check ( + email = '*' + or email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-z0-9.-]+\.[a-z]{2,}$' + ) +); + +comment on table public.glm_hub_app_access is + 'Registro central informativo de accesos mostrado por GLM Hub. No reemplaza los permisos reales de cada aplicación.'; +comment on column public.glm_hub_app_access.app_name is + 'Nombre de la aplicación tal como aparece en glm_hub_apps.'; +comment on column public.glm_hub_app_access.email is + 'Correo autorizado. El valor * significa todos los usuarios GLM autenticados.'; +comment on column public.glm_hub_app_access.is_active is + 'TRUE = acceso mostrado como Disponible; FALSE = registro desactivado.'; +comment on column public.glm_hub_app_access.app_id is + 'Se completa automáticamente usando app_name.'; + +create unique index if not exists glm_hub_app_access_app_email_uidx + on public.glm_hub_app_access (app_id, email); + +create index if not exists glm_hub_app_access_email_idx + on public.glm_hub_app_access (email) + where is_active = true; + +-- Normaliza correos y permite trabajar por nombre de aplicación desde Table Editor. +create or replace function public.glm_hub_app_access_prepare_row() +returns trigger +language plpgsql +security definer +set search_path = '' +as $$ +declare + v_app_id uuid; + v_app_name text; +begin + new.app_name := btrim(coalesce(new.app_name, '')); + new.email := lower(btrim(coalesce(new.email, ''))); + + if new.app_name = '' then + raise exception 'Debes indicar app_name.'; + end if; + + if new.email = '' then + raise exception 'Debes indicar email. Usa * si la aplicación está disponible para todo GLM.'; + end if; + + -- Si el usuario cambió app_name manualmente, ese nombre manda y se resuelve + -- nuevamente el UUID. En INSERT también permite dejar app_id vacío. + if tg_op = 'INSERT' then + select app.id, app.name + into v_app_id, v_app_name + from public.glm_hub_apps as app + where lower(btrim(app.name)) = lower(new.app_name) + order by app.created_at + limit 1; + + if v_app_id is null then + raise exception 'No existe una aplicación en GLM Hub llamada "%".', new.app_name; + end if; + + new.app_id := v_app_id; + new.app_name := v_app_name; + elsif new.app_id is null or new.app_name is distinct from old.app_name then + select app.id, app.name + into v_app_id, v_app_name + from public.glm_hub_apps as app + where lower(btrim(app.name)) = lower(new.app_name) + order by app.created_at + limit 1; + + if v_app_id is null then + raise exception 'No existe una aplicación en GLM Hub llamada "%".', new.app_name; + end if; + + new.app_id := v_app_id; + new.app_name := v_app_name; + else + select app.name + into v_app_name + from public.glm_hub_apps as app + where app.id = new.app_id; + + if v_app_name is null then + raise exception 'El app_id indicado no existe en glm_hub_apps.'; + end if; + + new.app_name := v_app_name; + end if; + + new.updated_at := now(); + return new; +end; +$$; + +drop trigger if exists glm_hub_app_access_prepare_row_trigger + on public.glm_hub_app_access; + +create trigger glm_hub_app_access_prepare_row_trigger +before insert or update on public.glm_hub_app_access +for each row +execute function public.glm_hub_app_access_prepare_row(); + +-- Si un administrador cambia el nombre de una app en el Hub, el nombre visible +-- de los registros centrales se mantiene sincronizado por app_id. +create or replace function public.glm_hub_sync_access_app_name() +returns trigger +language plpgsql +security definer +set search_path = '' +as $$ +begin + if new.name is distinct from old.name then + update public.glm_hub_app_access + set app_name = new.name, + updated_at = now() + where app_id = new.id; + end if; + return new; +end; +$$; + +drop trigger if exists glm_hub_sync_access_app_name_trigger + on public.glm_hub_apps; + +create trigger glm_hub_sync_access_app_name_trigger +after update of name on public.glm_hub_apps +for each row +execute function public.glm_hub_sync_access_app_name(); + +-- Nadie necesita leer esta tabla directamente desde el navegador. El frontend +-- consulta únicamente el RPC seguro glm_hub_get_my_app_access(). +alter table public.glm_hub_app_access enable row level security; +revoke all on table public.glm_hub_app_access from anon, authenticated; +grant all on table public.glm_hub_app_access to service_role; + +-- -------------------------------------------------------------------------- +-- 3. CARGA INICIAL DE LOS ACCESOS ACTUALES +-- -------------------------------------------------------------------------- +-- A) Apps abiertas para cualquier usuario GLM -> una sola fila con email='*'. +-- -------------------------------------------------------------------------- + +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select app.id, app.name, '*', true +from public.glm_hub_apps as app +where lower(btrim(app.name)) in ( + 'bamboohr', + 'cdc brief', + 'cruce de seguridad social - honduras', + 'cruce de seguridad social - guatemala', + 'cruce de seguridad social - costa rica', + 'cruce de seguridad social - república dominicana', + 'cruce de seguridad social - el salvador', + 'validación de ir - nicaragua', + 'glm id card generator' +) +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- B) CDC Project Management -> snapshot inicial desde tablero_cdc_allowed_users. +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select + app.id, + app.name, + lower(btrim(allowed_user.email)), + true +from public.glm_hub_apps as app +cross join public.tablero_cdc_allowed_users as allowed_user +where lower(btrim(app.name)) = 'cdc project management' + and nullif(btrim(allowed_user.email), '') is not null + and coalesce(allowed_user.is_active, false) = true +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- C) Portal de Verificación de Nóminas -> snapshot inicial desde la tabla actual. +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select + app.id, + app.name, + lower(btrim(allowed_user.email)), + true +from public.glm_hub_apps as app +cross join public.cruce_cuentas_usuarios_autorizados as allowed_user +where lower(btrim(app.name)) = 'portal de verificación de nóminas' + and nullif(btrim(allowed_user.email), '') is not null +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- D) Seguimiento de Impuestos GLM -> snapshot inicial desde tax_calendar_access. +insert into public.glm_hub_app_access (app_id, app_name, email, is_active) +select + app.id, + app.name, + lower(btrim(allowed_user.email)), + true +from public.glm_hub_apps as app +cross join public.tax_calendar_access as allowed_user +where lower(btrim(app.name)) = 'seguimiento de impuestos glm' + and nullif(btrim(allowed_user.email), '') is not null + and coalesce(allowed_user.active, false) = true +on conflict (app_id, email) +do update set + app_name = excluded.app_name, + is_active = true, + updated_at = now(); + +-- -------------------------------------------------------------------------- +-- 4. RPC FINAL PARA EL LED DEL HUB +-- -------------------------------------------------------------------------- +-- El Hub ya NO consulta las tablas particulares de cada aplicación. +-- Solo lee este registro central. +-- -------------------------------------------------------------------------- + +create or replace function public.glm_hub_get_my_app_access() +returns table ( + app_id uuid, + app_name text, + has_access boolean +) +language plpgsql +stable +security definer +set search_path = '' +as $$ +declare + v_email text; +begin + v_email := lower(btrim(coalesce(auth.jwt() ->> 'email', ''))); + + if auth.uid() is null or v_email = '' then + return; + end if; + + -- El GLM Hub continúa reservado al dominio corporativo principal. + if v_email !~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@gomezleemarketing\.com$' then + return; + end if; + + return query + select + app.id, + app.name, + exists ( + select 1 + from public.glm_hub_app_access as access_row + where access_row.app_id = app.id + and access_row.is_active = true + and ( + access_row.email = '*' + or access_row.email = v_email + ) + ) as has_access + from public.glm_hub_apps as app + where app.visibility = 'published' + order by app.name; +end; +$$; + +alter function public.glm_hub_get_my_app_access() owner to postgres; +revoke all on function public.glm_hub_get_my_app_access() from public, anon; +grant execute on function public.glm_hub_get_my_app_access() to authenticated; +grant execute on function public.glm_hub_get_my_app_access() to service_role; + +commit; + +-- ============================================================================ +-- VERIFICACIONES OPCIONALES DESPUÉS DE EJECUTAR +-- ============================================================================ + +-- Ver toda la matriz central: +-- select app_name, email, is_active +-- from public.glm_hub_app_access +-- order by app_name, email; + +-- Agregar acceso individual a una futura app restringida DESDE SQL: +-- insert into public.glm_hub_app_access (app_name, email) +-- values ('Nombre exacto de la aplicación', 'usuario@gomezleemarketing.com'); +-- +-- En el Table Editor puedes hacer exactamente lo mismo dejando app_id vacío. + +-- Marcar una futura app como abierta para todo GLM: +-- insert into public.glm_hub_app_access (app_name, email) +-- values ('Nombre exacto de la aplicación', '*'); + +-- Revocar sin borrar historial: +-- update public.glm_hub_app_access +-- set is_active = false +-- where lower(app_name) = lower('Nombre exacto de la aplicación') +-- and email = 'usuario@gomezleemarketing.com'; diff --git a/dist/assets/index-9ByAKvcq.css b/dist/assets/index-9ByAKvcq.css deleted file mode 100644 index b800778..0000000 --- a/dist/assets/index-9ByAKvcq.css +++ /dev/null @@ -1 +0,0 @@ -:root{font-family:Arial,sans-serif;color:#4a4a4a;background:#fff;font-synthesis:none;text-rendering:optimizeLegibility;--glm-blue: #4f758b;--glm-blue-mid: #5b7f95;--glm-steel: #6b8fa3;--glm-green: #6cc24a;--glm-lime: #c4d600;--glm-teal: #2c6e6f;--glm-orange: #ff6a13;--text: #4a4a4a;--muted: #6b6b6b;--line: #d0d0d0;--paper: #ffffff;--soft: #f5f5f5;--green-soft: #eef6e8;--danger: #b13b2d;--sidebar-width: 244px}*{box-sizing:border-box}html{min-width:320px;min-height:100%;scroll-behavior:smooth}body{min-width:320px;min-height:100vh;margin:0;background:var(--paper);color:var(--text)}button,input,textarea,select{font:inherit}button,a,input,textarea,select{-webkit-tap-highlight-color:transparent}input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:none}button{color:inherit}button:not(:disabled){cursor:pointer}button:disabled{cursor:wait;opacity:.66}img{display:block;max-width:100%}::selection{background:#eef6e8;color:#2c4a59}:focus-visible{outline:3px solid var(--glm-green);outline-offset:3px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.brand-logo{width:202px;height:auto}.brand-logo--compact{width:154px}.section-kicker,.eyebrow{margin:0 0 10px;color:var(--glm-blue);font-size:.72rem;font-weight:700;letter-spacing:.17em;line-height:1.2}.primary-button,.secondary-button,.danger-button{min-height:48px;display:inline-flex;align-items:center;justify-content:center;gap:10px;border:1px solid transparent;border-radius:3px;padding:0 20px;font-weight:700;transition:background-color .16s ease,color .16s ease,border-color .16s ease,transform .16s ease}.primary-button{position:relative;overflow:hidden;background:var(--glm-blue);color:#fff}.primary-button:after{content:"";position:absolute;left:0;bottom:0;width:100%;height:3px;background:var(--glm-green)}.primary-button:hover{background:#3f6378;transform:translateY(-1px)}.primary-button--full{width:100%}.primary-button--full svg:last-child{margin-left:auto}.secondary-button{background:#fff;border-color:var(--glm-blue);color:var(--glm-blue)}.secondary-button:hover{background:var(--soft)}.secondary-button--quiet{border-color:var(--line);color:var(--text)}.danger-button{background:transparent;border-color:#e4c6c1;color:var(--danger)}.danger-button:hover{background:#fdecea;border-color:var(--danger)}.danger-button--solid{background:var(--danger);border-color:var(--danger);color:#fff}.text-button{min-height:40px;border:0;border-bottom:1px solid currentColor;padding:0;background:transparent;color:var(--glm-blue);font-weight:700}.text-button--muted{color:var(--muted);font-size:.78rem}.text-button--danger{color:var(--danger);font-size:.78rem}.icon-button,.favorite-button{width:44px;height:44px;display:inline-grid;flex:0 0 auto;place-items:center;border:1px solid var(--line);border-radius:50%;background:#fff;color:var(--glm-blue)}.icon-button:hover,.favorite-button:hover{border-color:var(--glm-blue);background:var(--soft)}.icon-button--quiet{width:36px;height:36px;border-color:transparent;background:transparent}.icon-button--accent{border-radius:3px;background:var(--glm-blue);border-color:var(--glm-blue);color:#fff}.favorite-button.is-favorite{border-color:#d7e58f;background:#f8f9df;color:#718000}.app-mark{position:relative;display:inline-grid;flex:0 0 auto;place-items:center;overflow:visible;background:transparent}.app-mark--small{width:44px;height:44px}.app-mark--regular{width:58px;height:58px}.app-mark--large{width:72px;height:72px}.app-mark img{display:block;width:100%;height:100%;object-fit:contain}.app-mark__placeholder{color:#a7a7a7}.login-shell{min-height:100vh;display:grid;grid-template-columns:minmax(0,1.28fr) minmax(420px,.72fr);background:#fff}.login-story{position:relative;min-height:100vh;display:flex;flex-direction:column;overflow:hidden;border-right:1px solid var(--line);padding:42px clamp(40px,5vw,82px) 36px;background:#fff}.login-story:before{content:"";position:absolute;top:0;left:clamp(40px,5vw,82px);width:3px;height:126px;background:var(--glm-green)}.login-story__topline{position:relative;z-index:2;display:flex;align-items:flex-start;justify-content:space-between;gap:24px;padding-left:18px}.login-story__edition{padding-top:10px;color:var(--glm-blue);font-size:.7rem;font-weight:700;letter-spacing:.18em}.login-story__content{position:relative;z-index:2;width:min(760px,92%);margin:auto 0;padding:80px 0 76px}.login-story h1{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:clamp(3.5rem,6.35vw,7.7rem);font-weight:900;letter-spacing:-.075em;line-height:.85}.login-story h1 span{display:block;margin-top:.14em;color:var(--text);font-family:Arial,sans-serif;font-size:.49em;font-weight:400;letter-spacing:-.052em;line-height:1}.login-story__lede{max-width:540px;margin:36px 0 0;padding-left:20px;border-left:3px solid var(--glm-green);color:var(--text);font-size:clamp(1rem,1.35vw,1.2rem);line-height:1.55}.login-story__signal{position:relative;z-index:2;display:grid;grid-template-columns:auto minmax(40px,1fr) auto;align-items:center;gap:14px;max-width:530px;color:var(--glm-blue);font-size:.7rem;font-weight:700;letter-spacing:.14em}.login-story__signal-line{height:1px;background:var(--line)}.login-story__signal-line:before{content:"";display:block;width:18%;height:2px;background:var(--glm-green)}.login-story__place{position:relative;z-index:2;margin:10px 0 0;color:var(--muted);font-size:.65rem;letter-spacing:.16em}.login-story__type{position:absolute;right:-.06em;bottom:-.28em;color:var(--soft);font-family:Arial Black,Arial,sans-serif;font-size:clamp(13rem,27vw,31rem);font-weight:900;letter-spacing:-.13em;line-height:1;pointer-events:none;-webkit-user-select:none;user-select:none}.login-panel{min-height:100vh;display:grid;place-items:center;padding:48px clamp(34px,4vw,72px);background:var(--soft)}.login-panel__inner{width:min(100%,460px)}.login-panel__heading h2{margin:0 0 10px;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:clamp(2rem,3vw,3rem);letter-spacing:-.045em;line-height:1}.login-panel__heading>p:last-child{margin:0;color:var(--muted);line-height:1.55}.login-form{margin-top:34px}.form-field{display:grid;gap:8px;margin-bottom:20px}.form-field label{color:var(--text);font-size:.81rem;font-weight:700}.form-field label>span{margin-left:6px;color:var(--muted);font-size:.72rem;font-weight:400}.form-field label>.required-mark,.editor-form__section-title>.required-mark{margin-left:4px;color:var(--danger);font-size:1em;font-weight:700}.form-field__label-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.form-field__label-row>span{color:var(--muted);font-size:.7rem}.form-field input,.form-field textarea,.form-field select{width:100%;border:1px solid var(--line);border-radius:3px;background:#fff;color:var(--text);transition:border-color .14s ease,box-shadow .14s ease}.form-field input,.form-field select{height:50px;padding:0 14px}.form-field textarea{min-height:94px;resize:vertical;padding:13px 14px;line-height:1.5}.form-field input::placeholder,.form-field textarea::placeholder{color:#8a8a8a}.form-field input:hover,.form-field textarea:hover,.form-field select:hover{border-color:#97a9b3}.form-field input:focus,.form-field textarea:focus,.form-field select:focus{border-color:var(--glm-blue);box-shadow:inset 3px 0 0 var(--glm-green);outline:none}.form-field input[aria-invalid=true],.form-field textarea[aria-invalid=true]{border-color:var(--danger)}.password-field,.url-field{position:relative}.password-field input{padding-right:50px}.password-field__toggle{position:absolute;top:3px;right:3px;width:44px;height:44px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue)}.form-error,.field-error{color:var(--danger);font-size:.77rem;line-height:1.4}.form-error{margin:-4px 0 18px;padding:11px 12px;border-left:3px solid var(--danger);background:#fdecea}.check-control{min-height:44px;display:flex;align-items:center;gap:10px;margin:2px 0 18px;color:var(--text);font-size:.8rem;cursor:pointer}.check-control input{position:absolute;width:1px;height:1px;overflow:hidden;opacity:0}.check-control>span{width:20px;height:20px;display:grid;place-items:center;border:1px solid var(--line);border-radius:2px;background:#fff;color:transparent}.check-control input:checked+span{border-color:var(--glm-blue);background:var(--glm-blue);color:#fff}.check-control input:focus-visible+span{outline:3px solid var(--glm-green);outline-offset:3px}.demo-access{margin-top:30px}.demo-access__label,.app-preview__label{display:flex;align-items:center;gap:12px;color:var(--muted);font-size:.62rem;font-weight:700;letter-spacing:.14em}.demo-access__rule,.app-preview__rule{height:1px;flex:1;background:var(--line)}.demo-access__options{margin-top:10px;border-top:1px solid var(--line)}.demo-access__options button{width:100%;min-height:62px;display:grid;grid-template-columns:24px 1fr 20px;align-items:center;gap:12px;border:0;border-bottom:1px solid var(--line);padding:8px 4px;background:transparent;color:var(--glm-blue);text-align:left}.demo-access__options button:hover{padding-left:10px;background:#fff}.demo-access__options button span{display:grid;gap:3px}.demo-access__options button strong{color:var(--text);font-size:.8rem}.demo-access__options button small{color:var(--muted);font-size:.69rem}.demo-note{margin:18px 0 0;color:var(--muted);font-size:.68rem;line-height:1.45}.app-shell{min-height:100vh;background:#fff}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:20;width:var(--sidebar-width);display:flex;flex-direction:column;border-right:1px solid var(--line);background:#fff}.sidebar__brand{height:116px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;border-bottom:1px solid var(--line);padding:0 26px}.sidebar__brand span{color:var(--glm-blue);font-size:.58rem;font-weight:700;letter-spacing:.28em}.sidebar__nav{display:grid;gap:4px;padding:28px 16px}.sidebar__nav button{position:relative;min-height:52px;display:flex;align-items:center;gap:14px;border:0;border-radius:2px;padding:0 14px;background:transparent;color:var(--muted);font-size:.82rem;font-weight:700;text-align:left}.sidebar__nav button:hover{background:var(--soft);color:var(--glm-blue)}.sidebar__nav button.is-active{background:var(--green-soft);color:var(--glm-blue)}.sidebar__meta{padding:22px 28px;border-top:1px solid var(--line)}.sidebar__meta p{margin:12px 0 0;color:var(--muted);font-size:.6rem;font-weight:700;letter-spacing:.14em}.sidebar__meta p+p{margin-top:4px}.sidebar__account{margin-top:auto;min-height:88px;display:flex;align-items:center;gap:10px;border-top:1px solid var(--line);padding:16px}.avatar{width:38px;height:38px;display:grid;flex:0 0 auto;place-items:center;overflow:hidden;border-radius:50%;background:var(--glm-blue);color:#fff;font-size:.67rem;font-weight:700;letter-spacing:.03em}.avatar img{display:block;width:100%;height:100%;object-fit:cover}.sidebar__account-copy{min-width:0;flex:1;display:grid;gap:3px}.sidebar__account-copy strong,.sidebar__account-copy small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sidebar__account-copy strong{color:var(--text);font-size:.77rem}.sidebar__account-copy small{color:var(--muted);font-size:.62rem}.sidebar__account .icon-button{width:38px;height:38px;border:0}.mobile-header,.mobile-nav{display:none}.page-content{min-height:100vh;margin-left:var(--sidebar-width);padding:42px clamp(36px,5vw,82px) 72px}.page-header{display:flex;align-items:flex-end;justify-content:space-between;gap:30px;padding-bottom:30px;border-bottom:1px solid var(--line)}.page-header__meta{margin:0 0 9px;color:var(--glm-blue);font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.page-header h1{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:clamp(2.4rem,4.2vw,4.85rem);letter-spacing:-.065em;line-height:.9}.page-header__aside{display:grid;justify-items:end;padding-bottom:4px}.page-header__aside>span:last-child{color:var(--muted);font-size:.82rem;font-weight:700;line-height:1.35;white-space:nowrap}.inline-alert{margin-top:18px;border-left:3px solid var(--glm-orange);padding:12px 14px;background:#fff8e1;color:var(--text);font-size:.82rem}.search-stage{position:relative;overflow:hidden;display:flex;flex-direction:column;align-items:stretch;gap:22px;margin-top:38px;border-left:3px solid var(--glm-green);padding:34px 38px 32px;background:var(--soft)}.search-stage__copy,.hub-search{position:relative;z-index:2}.search-stage h2,.section-heading h2,.admin-bridge h2,.access-request-bridge h2,.admin-list h2,.app-editor h2{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;letter-spacing:-.04em}.search-stage h2{max-width:100%;font-size:clamp(2rem,3.3vw,3.5rem);line-height:1.05}.hub-search{min-height:62px;display:grid;grid-template-columns:24px 1fr auto;align-items:center;gap:13px;border-bottom:2px solid var(--glm-blue);background:#fff;padding:0 16px;color:var(--glm-blue)}.hub-search:focus-within{border-bottom-color:var(--glm-green);box-shadow:0 0 0 1px var(--line)}.hub-search input{width:100%;height:60px;border:0;outline:0;background:transparent;color:var(--text);font-size:.96rem}.hub-search input::placeholder{color:#747474}.hub-search button{width:40px;height:40px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue)}.hub-search kbd{border:1px solid var(--line);border-radius:3px;padding:4px 7px;background:var(--soft);color:var(--muted);font-family:Arial,sans-serif;font-size:.65rem}.search-stage__coordinate{position:absolute;top:-.31em;right:.02em;color:#e9e9e9;font-family:Arial Black,Arial,sans-serif;font-size:clamp(5.5rem,10vw,10rem);letter-spacing:-.08em;line-height:1;-webkit-user-select:none;user-select:none}.quick-section,.directory-section{margin-top:64px}.section-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:28px;margin-bottom:22px}.section-heading h2{font-size:clamp(1.75rem,2.5vw,2.8rem)}.section-heading>p{max-width:340px;margin:0 0 2px;color:var(--muted);font-size:.82rem;line-height:1.5;text-align:right}.quick-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));align-items:stretch;gap:14px}.quick-launch{--card-accent: var(--glm-green);min-width:0;min-height:360px;display:flex;flex-direction:column;border:1px solid var(--line);border-top:3px solid var(--glm-green);border-radius:2px;padding:28px;background:#fff;transition:border-color .16s ease,transform .16s ease}.quick-launch:hover{border-right-color:var(--glm-blue);border-bottom-color:var(--glm-blue);border-left-color:var(--glm-blue);transform:translateY(-3px)}.quick-launch__top{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}.quick-launch__copy{flex:1;margin-top:48px}.quick-launch__category{color:var(--glm-blue);font-size:.64rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.quick-launch h3,.preview-card h3{margin:9px 0 8px;color:var(--text);font-family:Arial Black,Arial,sans-serif;font-size:1.35rem;letter-spacing:-.035em;line-height:1.05}.quick-launch h3{color:var(--glm-blue);font-size:1.55rem}.quick-launch p,.preview-card p{margin:0;color:var(--muted);font-size:.82rem;line-height:1.5}.quick-launch__action{width:100%;min-height:46px;display:flex;align-items:center;justify-content:space-between;gap:14px;margin-top:auto;border:0;border-top:1px solid var(--line);padding:13px 0 0;background:transparent;color:var(--glm-blue);font-size:.76rem;font-weight:700;text-align:left}.quick-launch__action:hover{color:var(--glm-teal)}.section-heading--directory{padding-bottom:18px;border-bottom:1px solid var(--line)}.directory-count{display:flex;align-items:baseline;gap:7px}.directory-count strong{color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:2rem;letter-spacing:-.06em}.directory-count span{color:var(--muted);font-size:.7rem}.filter-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:18px;flex-wrap:wrap}.category-filters{display:flex;align-items:center;gap:4px}.filter-bar__search{flex:1;max-width:360px;min-width:220px;min-height:42px;display:grid;grid-template-columns:18px 1fr auto;align-items:center;gap:10px;border:1px solid var(--line);border-radius:2px;background:#fff;padding:0 12px;color:var(--glm-blue);transition:border-color .16s ease,box-shadow .16s ease}.filter-bar__search:focus-within{border-color:var(--glm-blue);box-shadow:0 0 0 1px var(--glm-blue)}.filter-bar__search input{width:100%;height:40px;border:0;outline:0;background:transparent;color:var(--text);font-size:.82rem}.filter-bar__search input::placeholder{color:#8a8a8a}.filter-bar__search button{width:24px;height:24px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue);padding:0}.category-filters button,.favorites-filter{min-height:44px;border:0;border-bottom:2px solid transparent;padding:0 12px;background:transparent;color:var(--muted);font-size:.74rem;font-weight:700;white-space:nowrap}.category-filters button:hover,.favorites-filter:hover{color:var(--glm-blue)}.category-filters button.is-active{border-bottom-color:var(--glm-green);color:var(--glm-blue)}.favorites-filter{display:inline-flex;align-items:center;gap:8px}.favorites-filter.is-active{border-bottom-color:var(--glm-lime);color:#617000}.directory-list{border-top:1px solid var(--text)}.pagination{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:24px}.pagination__pages{display:flex;align-items:center;justify-content:center;gap:6px}.pagination__arrow,.pagination__page{width:36px;height:36px;display:grid;flex:0 0 auto;place-items:center;border:1px solid var(--line);border-radius:3px;background:#fff;color:var(--glm-blue);font-size:.74rem;font-weight:700;transition:background-color .14s ease,border-color .14s ease,color .14s ease}.pagination__arrow:hover:not(:disabled),.pagination__page:hover:not(.is-active){border-color:var(--glm-blue);background:var(--soft)}.pagination__page.is-active{border-color:var(--glm-blue);background:var(--glm-blue);color:#fff}.pagination__arrow:disabled{cursor:not-allowed;opacity:.35}.pagination__ellipsis{width:24px;color:var(--muted);font-size:.8rem;line-height:1;text-align:center}.pagination--compact{gap:5px}.pagination--compact .pagination__pages{gap:4px}.pagination--compact .pagination__arrow,.pagination--compact .pagination__page{width:30px;height:30px;font-size:.66rem}.pagination--compact .pagination__ellipsis{width:16px;font-size:.7rem}.directory-row{min-height:92px;display:grid;grid-template-columns:42px 44px minmax(220px,1fr) 110px 128px 44px 86px;align-items:center;gap:14px;border-bottom:1px solid var(--line);padding:14px 0;transition:background-color .14s ease,padding .14s ease}.directory-row:hover{padding-right:10px;padding-left:10px;background:var(--soft)}.directory-row__number{color:#919191;font-family:Arial Black,Arial,sans-serif;font-size:.65rem;letter-spacing:.06em}.directory-row__copy{min-width:0}.directory-row__copy h3{margin:0 0 5px;color:var(--text);font-size:.92rem;line-height:1.2}.directory-row__copy p{overflow:hidden;margin:0;color:var(--muted);font-size:.72rem;line-height:1.4;text-overflow:ellipsis;white-space:nowrap}.directory-row__category{color:var(--glm-blue);font-size:.65rem;font-weight:700}.availability{display:inline-flex;align-items:center;gap:7px;color:var(--muted);font-size:.67rem;font-weight:700;white-space:nowrap}.availability>span{width:7px;height:7px;flex:0 0 auto;border-radius:50%;background:var(--line)}.availability--ready>span{background:var(--glm-green);box-shadow:0 0 0 3px var(--green-soft)}.availability--pending>span{background:var(--glm-orange);box-shadow:0 0 0 3px #fff1e8}.directory-row .favorite-button{width:40px;height:40px;border:0;background:transparent}.directory-row__open{min-height:42px;display:flex;align-items:center;justify-content:flex-end;gap:7px;border:0;background:transparent;color:var(--glm-blue);font-size:.74rem;font-weight:700}.empty-state{min-height:280px;display:grid;grid-template-columns:minmax(110px,.35fr) minmax(260px,.65fr);align-items:center;gap:40px;border-top:1px solid var(--text);border-bottom:1px solid var(--line);padding:38px}.empty-state__mark{color:var(--soft);font-family:Arial Black,Arial,sans-serif;font-size:10rem;letter-spacing:-.1em;line-height:.7}.empty-state h3{margin:0 0 8px;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:1.6rem;letter-spacing:-.04em}.empty-state p:not(.section-kicker){margin:0 0 18px;color:var(--muted);font-size:.84rem;line-height:1.5}.admin-bridge{position:relative;overflow:hidden;min-height:190px;display:grid;grid-template-columns:minmax(70px,.25fr) minmax(300px,1fr) auto;align-items:center;gap:30px;margin-top:70px;border-top:1px solid var(--text);border-bottom:3px solid var(--glm-green);padding:30px 8px}.admin-bridge__number{color:var(--glm-green);font-family:Arial Black,Arial,sans-serif;font-size:7rem;line-height:.7}.admin-bridge h2{font-size:2rem}.admin-bridge p:not(.section-kicker){margin:8px 0 0;color:var(--muted);font-size:.84rem;line-height:1.5}.access-request-bridge{position:relative;min-height:190px;display:grid;grid-template-columns:minmax(70px,.25fr) minmax(300px,1fr) auto;align-items:center;gap:30px;margin-top:70px;border-top:1px solid var(--text);border-bottom:3px solid var(--glm-green);padding:30px 8px}.access-request-bridge__number{color:var(--glm-green);font-family:Arial Black,Arial,sans-serif;font-size:6.5rem;line-height:.72}.access-request-bridge h2{font-size:2rem}.access-request-bridge p:not(.section-kicker){margin:8px 0 0;color:var(--muted);font-size:.84rem;line-height:1.5}.access-request-dialog{width:min(560px,calc(100vw - 32px));border:0;border-top:4px solid var(--glm-green);border-radius:3px;padding:34px;color:var(--text);box-shadow:0 24px 80px #2d363b38}.access-request-dialog::backdrop{background:#2330378f}.access-request-dialog__close{position:absolute;top:12px;right:12px;width:40px;height:40px;display:grid;place-items:center;border:0;background:transparent;color:var(--muted)}.access-request-dialog h2{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:2rem;letter-spacing:-.04em}.access-request-dialog__intro{margin:10px 0 34px;color:var(--muted);font-size:.82rem;line-height:1.55}.access-request-dialog form{display:grid;gap:20px;margin-top:4px}.access-request-dialog__actions{display:flex;justify-content:flex-end;gap:10px;margin-top:8px;padding-top:22px;border-top:1px solid var(--line)}.back-button{min-height:40px;display:inline-flex;align-items:center;gap:8px;margin-bottom:18px;border:0;border-bottom:1px solid var(--line);padding:0;background:transparent;color:var(--glm-blue);font-size:.75rem;font-weight:700}.admin-header{align-items:center}.admin-header__note{display:flex;align-items:center;gap:12px;border-left:3px solid var(--glm-green);padding:10px 0 10px 14px;color:var(--glm-blue)}.admin-header__note span{display:grid;gap:3px}.admin-header__note strong{color:var(--text);font-size:.74rem}.admin-header__note small{color:var(--muted);font-size:.66rem}.admin-workspace{min-height:680px;display:grid;grid-template-columns:300px minmax(0,1fr);margin-top:34px;border:1px solid var(--line)}.admin-list{min-width:0;display:flex;flex-direction:column;border-right:1px solid var(--line);background:var(--soft)}.admin-list__top{min-height:94px;display:flex;align-items:center;justify-content:space-between;gap:20px;border-bottom:1px solid var(--line);padding:20px}.admin-list h2{font-size:1.25rem}.admin-list__search{display:grid;grid-template-columns:20px 1fr auto;align-items:center;gap:9px;margin:14px;border:1px solid var(--line);background:#fff;padding:0 11px;color:var(--glm-blue)}.admin-list__search input{width:100%;height:42px;border:0;outline:0;background:transparent;font-size:.77rem}.admin-list__search button{width:24px;height:24px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue)}.admin-list__items{min-height:0;flex:1;overflow-y:auto;border-top:1px solid var(--line)}.admin-list__items>button,.admin-list__item-row{position:relative;width:100%;min-height:70px;display:grid;grid-template-columns:44px minmax(0,1fr) auto;align-items:center;gap:11px;border:0;border-bottom:1px solid var(--line);padding:10px 14px;background:transparent;text-align:left;cursor:pointer}.admin-list__items>button:hover,.admin-list__item-row:hover{background:#fff}.admin-list__items>button.is-active,.admin-list__item-row.is-active{background:#fff}.admin-list__items>button.is-active:before,.admin-list__item-row.is-active:before{content:"";position:absolute;top:0;bottom:0;left:0;width:3px;background:var(--glm-green)}.admin-list__item-info{min-width:0;display:flex;flex-direction:column;gap:3px;text-align:left}.admin-list__item-info strong{display:block;color:var(--text);font-size:.76rem;font-weight:700;line-height:1.25}.admin-list__item-info small{display:block;color:var(--muted);font-size:.64rem;font-weight:400;line-height:1.2}.admin-list__item-actions{display:flex;align-items:center;gap:8px}.admin-list__delete-icon{width:28px;height:28px;display:grid;place-items:center;border:0;border-radius:3px;background:transparent;color:#a0a0a0;transition:color .14s ease,background-color .14s ease}.admin-list__delete-icon:hover{color:var(--danger);background:#fdecea}.admin-list__items strong,.admin-list__items small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.admin-list__new-icon{width:38px;height:38px;display:grid;place-items:center;border:1px dashed var(--glm-blue);border-radius:3px;color:var(--glm-blue)}.mini-status{color:var(--glm-blue);font-size:.57rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.mini-status.is-hidden{color:var(--muted)}.admin-list>.pagination{flex:0 0 auto;justify-content:space-between;margin-top:0;border-top:1px solid var(--line);padding:10px 12px;background:#fff}.app-editor{min-width:0;padding:28px clamp(24px,3.4vw,52px) 44px}.app-editor__heading{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;border-bottom:1px solid var(--line);padding-bottom:20px}.app-editor h2{font-size:clamp(1.5rem,2.4vw,2.35rem)}.dirty-state{display:inline-flex;align-items:center;gap:7px;color:var(--muted);font-size:.65rem;font-weight:700;white-space:nowrap}.dirty-state>span{width:7px;height:7px;border-radius:50%;background:var(--glm-green)}.dirty-state.is-dirty>span{background:var(--glm-orange)}.editor-layout{display:grid;grid-template-columns:minmax(0,1fr) 260px;align-items:start;gap:clamp(28px,4vw,54px);margin-top:28px}.editor-form__section{display:grid;gap:18px;margin:0;border-bottom:1px solid var(--line);padding:0 0 28px}.editor-form__section+.editor-form__section{padding-top:28px}.editor-form__section-title{margin:0 0 2px;color:var(--glm-blue);font-size:.72rem;font-weight:700;letter-spacing:.12em;line-height:1.2;text-transform:uppercase}.editor-form .form-field{margin:0}.form-split{display:grid;grid-template-columns:1fr 1fr;gap:16px}.field-meta{display:flex;justify-content:space-between;gap:14px;color:var(--muted);font-size:.66rem;line-height:1.4}.field-meta>span:last-child{flex:0 0 auto}.field-meta--counter-only{justify-content:flex-end}.field-help{color:var(--muted);font-size:.67rem;line-height:1.4}.field-error--standalone{margin:0}.icon-config{display:flex;align-items:center;gap:18px}.ai-icon-actions{display:flex;align-items:center}.ai-icon-button{min-height:44px}.icon-dropzone{min-height:80px;display:grid;flex:1;grid-template-columns:42px 1fr;align-items:center;gap:13px;border:1px dashed var(--glm-blue);border-radius:3px;padding:14px;background:var(--soft);cursor:pointer;transition:border-color .14s ease,background-color .14s ease}.icon-dropzone:hover,.icon-dropzone.is-dragging{border-color:var(--glm-green);background:var(--green-soft)}.icon-dropzone input{position:absolute;width:1px;height:1px;overflow:hidden;opacity:0}.icon-dropzone:focus-within{outline:3px solid var(--glm-green);outline-offset:3px}.icon-dropzone__symbol{width:42px;height:42px;display:grid;place-items:center;border-radius:3px;background:#fff;color:var(--glm-blue)}.icon-dropzone>span:last-child{display:grid;gap:4px}.icon-dropzone strong{color:var(--text);font-size:.77rem}.icon-dropzone small{color:var(--muted);font-size:.65rem}.url-field{display:grid;grid-template-columns:24px 1fr;align-items:center;border:1px solid var(--line);border-radius:3px;padding:0 12px;background:#fff;color:var(--glm-blue)}.url-field:focus-within{border-color:var(--glm-blue);box-shadow:inset 3px 0 0 var(--glm-green)}.url-field input{border:0;box-shadow:none;padding:0 3px}.url-field input:focus{box-shadow:none}.editor-actions{display:flex;align-items:center;gap:10px;padding-top:26px}.editor-actions .danger-button{margin-left:auto}.app-preview{position:sticky;top:28px}.preview-card{min-height:302px;display:flex;flex-direction:column;align-items:flex-start;margin-top:14px;border:1px solid var(--line);border-top:3px solid var(--glm-green);padding:22px;background:#fff}.preview-card .app-mark{margin-bottom:36px}.preview-card .availability{margin-top:auto;padding-top:24px}.app-preview__note{margin:12px 0 0;color:var(--muted);font-size:.65rem;line-height:1.45}.confirm-dialog{width:min(440px,calc(100vw - 32px));border:0;border-top:4px solid var(--danger);border-radius:3px;padding:30px;color:var(--text);box-shadow:0 24px 80px #2d363b38}.confirm-dialog::backdrop{background:#2330378f}.confirm-dialog__close{position:absolute;top:12px;right:12px;width:40px;height:40px;display:grid;place-items:center;border:0;background:transparent;color:var(--muted)}.confirm-dialog__icon{width:48px;height:48px;display:grid;place-items:center;margin-bottom:28px;border-radius:50%;background:#fdecea;color:var(--danger)}.confirm-dialog h2{margin:0;color:var(--text);font-family:Arial Black,Arial,sans-serif;font-size:1.6rem;letter-spacing:-.04em}.confirm-dialog>p:not(.section-kicker){margin:12px 0 0;color:var(--muted);font-size:.82rem;line-height:1.55}.confirm-dialog__actions{display:flex;justify-content:flex-end;gap:10px;margin-top:28px}.generation-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:200;display:grid;place-items:center;padding:24px;background:#162128b8;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.generation-overlay__card{width:min(460px,100%);display:grid;justify-items:center;border-top:4px solid var(--glm-green);padding:38px 34px;background:#fff;box-shadow:0 24px 70px #00000047;text-align:center}.generation-overlay__card h2{margin:10px 0 0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:1.75rem;letter-spacing:-.04em}.generation-overlay__card>p:last-child{max-width:350px;margin:12px 0 0;color:var(--muted);font-size:.82rem;line-height:1.5}.generation-spinner{width:40px;height:40px;margin-bottom:20px;border:4px solid var(--line);border-top-color:var(--glm-green);border-radius:50%;animation:glm-spin .8s linear infinite}.catalog-loading{min-height:100vh;display:grid;place-items:center;align-content:center;gap:18px;background:#fff;color:var(--glm-blue);font-size:.85rem;font-weight:700}.catalog-loading .brand-logo{width:150px;margin-bottom:8px}.catalog-loading .generation-spinner,.catalog-loading p{margin:0}@keyframes glm-spin{to{transform:rotate(360deg)}}.toast-stack{position:fixed;right:24px;bottom:24px;z-index:100;width:min(390px,calc(100vw - 32px));display:grid;gap:10px}.toast{position:relative;display:grid;grid-template-columns:3px 1fr 36px;align-items:center;gap:14px;overflow:hidden;border:1px solid var(--line);border-radius:3px;padding:13px 10px 13px 0;background:#fff;box-shadow:0 16px 44px #32444e29}.toast__signal{align-self:stretch;background:var(--glm-green)}.toast>div,.toast .icon-button{align-self:center}.toast--info .toast__signal{background:var(--glm-blue)}.toast--error .toast__signal{background:var(--danger)}.toast strong{display:block;margin-top:0;color:var(--text);font-size:.8rem}.toast p{margin:4px 0 0;color:var(--muted);font-size:.7rem;line-height:1.45}@media(max-width:1240px){:root{--sidebar-width: 214px}.sidebar__brand{padding:0 20px}.sidebar__brand .brand-logo{width:140px}.sidebar__account-copy{display:none}.directory-row{grid-template-columns:34px 44px minmax(190px,1fr) 112px 44px 80px}.directory-row__category{display:none}.editor-layout{grid-template-columns:minmax(0,1fr) 230px;gap:28px}}@media(max-width:1360px){.editor-layout{grid-template-columns:1fr}.app-preview{position:static}.preview-card{width:100%;min-height:260px}}@media(max-width:1040px){.page-content{padding-right:32px;padding-left:32px}.search-stage{gap:20px}.quick-grid{grid-template-columns:1fr 1fr}.directory-row{grid-template-columns:34px 44px minmax(160px,1fr) 108px 44px 44px}.directory-row__open span{display:none}.admin-workspace{grid-template-columns:250px minmax(0,1fr)}}@media(max-width:860px){:root{--mobile-header-height: 72px;--mobile-nav-height: 72px}.login-shell{grid-template-columns:1fr}.login-story{min-height:540px;border-right:0;border-bottom:1px solid var(--line)}.login-story__content{margin:auto 0 0;padding:72px 0 54px}.login-story__type{right:-.03em;bottom:-.3em;font-size:20rem}.login-panel{min-height:auto;padding-top:64px;padding-bottom:64px}.sidebar{display:none}.mobile-header{position:fixed;top:0;right:0;left:0;z-index:30;height:var(--mobile-header-height);display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line);padding:10px 22px;background:#fffffff5}.mobile-header:before{content:"";position:absolute;top:0;left:0;width:94px;height:3px;background:var(--glm-green)}.mobile-header .brand-logo{width:135px}.mobile-nav{position:fixed;right:0;bottom:0;left:0;z-index:30;min-height:var(--mobile-nav-height);display:flex;align-items:stretch;justify-content:center;border-top:1px solid var(--line);background:#fffffffa}.mobile-nav button{min-width:92px;min-height:66px;display:grid;place-items:center;align-content:center;gap:5px;border:0;border-top:3px solid transparent;background:transparent;color:var(--muted);font-size:.62rem;font-weight:700}.mobile-nav button.is-active{border-top-color:var(--glm-green);color:var(--glm-blue)}.page-content{margin-left:0;padding-top:calc(var(--mobile-header-height) + 34px);padding-bottom:calc(var(--mobile-nav-height) + 42px)}.filter-bar{align-items:flex-start;flex-direction:column}.category-filters{width:100%;overflow-x:auto;padding-bottom:3px}.directory-row{grid-template-columns:44px minmax(150px,1fr) 108px 44px 44px}.directory-row__number{display:none}.admin-bridge,.access-request-bridge{grid-template-columns:80px 1fr}.admin-bridge .secondary-button,.access-request-bridge .secondary-button{grid-column:2;justify-self:start}.admin-workspace{grid-template-columns:1fr}.admin-list{max-height:360px;border-right:0;border-bottom:1px solid var(--line)}.admin-list__items{max-height:210px}}@media(max-width:620px){.login-story{min-height:480px;padding:26px 22px 24px}.login-story:before{left:22px;height:90px}.login-story__topline{padding-left:12px}.login-story .brand-logo{width:160px}.login-story__edition{font-size:.58rem}.login-story__content{width:100%;padding:62px 0 42px}.login-story h1{font-size:clamp(3.25rem,15.5vw,5rem)}.login-story__lede{margin-top:26px;font-size:.95rem}.login-story__signal,.login-story__place{font-size:.54rem}.login-story__type{font-size:12rem}.login-panel{padding:48px 22px}.page-content{padding-right:18px;padding-left:18px}.page-header{padding-bottom:23px}.page-header h1{font-size:2.7rem}.page-header__aside,.admin-header__note{display:none}.search-stage{margin-top:26px;padding:26px 18px 22px}.search-stage__coordinate{opacity:.58}.hub-search{grid-template-columns:22px 1fr auto;min-height:58px;padding:0 12px}.hub-search input{min-width:0;font-size:.84rem}.hub-search kbd{display:none}.pagination{gap:4px}.pagination__pages{gap:3px}.pagination__arrow,.pagination__page{width:32px;height:32px}.quick-section,.directory-section{margin-top:48px}.section-heading{align-items:flex-start;flex-direction:column;gap:12px}.section-heading>p{text-align:left}.section-heading--directory{flex-direction:row;align-items:flex-end}.quick-grid{grid-template-columns:1fr}.quick-launch{min-height:330px;padding:20px}.quick-launch__copy{margin-top:28px}.directory-row{min-height:86px;grid-template-columns:44px minmax(0,1fr) 40px 38px;gap:9px}.directory-row__category,.directory-row .availability{display:none}.directory-row__copy p{max-width:100%}.directory-row .favorite-button,.directory-row__open{width:38px;height:38px;min-height:38px}.empty-state{grid-template-columns:1fr;gap:16px;padding:30px 18px}.empty-state__mark{font-size:6rem}.admin-bridge,.access-request-bridge{grid-template-columns:54px 1fr;gap:16px}.admin-bridge__number,.access-request-bridge__number{font-size:5rem}.admin-bridge h2,.access-request-bridge h2{font-size:1.65rem}.admin-bridge .secondary-button,.access-request-bridge .secondary-button{grid-column:1 / -1;width:100%}.access-request-dialog{padding:28px 20px 22px}.access-request-dialog__actions{flex-direction:column-reverse}.access-request-dialog__actions button{width:100%}.admin-page{padding-right:12px;padding-left:12px}.admin-workspace{margin-top:26px}.app-editor{padding:24px 16px 36px}.app-editor__heading{align-items:flex-start;flex-direction:column;gap:12px}.form-split{grid-template-columns:1fr}.icon-config{align-items:flex-start;flex-direction:column}.icon-dropzone{width:100%}.editor-actions{align-items:stretch;flex-direction:column}.editor-actions .danger-button{margin-left:0}.app-preview{grid-template-columns:1fr}.preview-card{width:100%}.confirm-dialog{padding:26px 20px}.confirm-dialog__actions{align-items:stretch;flex-direction:column}.toast-stack{right:16px;bottom:calc(var(--mobile-nav-height, 0px) + 16px);left:16px;width:auto}}@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}} diff --git a/dist/assets/index-CIGqNuJ5.css b/dist/assets/index-CIGqNuJ5.css new file mode 100644 index 0000000..615cce9 --- /dev/null +++ b/dist/assets/index-CIGqNuJ5.css @@ -0,0 +1 @@ +:root{font-family:Arial,sans-serif;color:#4a4a4a;background:#fff;font-synthesis:none;text-rendering:optimizeLegibility;--glm-blue: #4f758b;--glm-blue-mid: #5b7f95;--glm-steel: #6b8fa3;--glm-green: #6cc24a;--glm-lime: #c4d600;--glm-teal: #2c6e6f;--glm-orange: #ff6a13;--text: #4a4a4a;--muted: #6b6b6b;--line: #d0d0d0;--paper: #ffffff;--soft: #f5f5f5;--green-soft: #eef6e8;--danger: #b13b2d;--sidebar-width: 244px}*{box-sizing:border-box}html{min-width:320px;min-height:100%;scroll-behavior:smooth}body{min-width:320px;min-height:100vh;margin:0;background:var(--paper);color:var(--text)}button,input,textarea,select{font:inherit}button,a,input,textarea,select{-webkit-tap-highlight-color:transparent}input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:none}button{color:inherit}button:not(:disabled){cursor:pointer}button:disabled{cursor:wait;opacity:.66}img{display:block;max-width:100%}::selection{background:#eef6e8;color:#2c4a59}:focus-visible{outline:3px solid var(--glm-green);outline-offset:3px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.brand-logo{width:202px;height:auto}.brand-logo--compact{width:154px}.section-kicker,.eyebrow{margin:0 0 10px;color:var(--glm-blue);font-size:.72rem;font-weight:700;letter-spacing:.17em;line-height:1.2}.primary-button,.secondary-button,.danger-button{min-height:48px;display:inline-flex;align-items:center;justify-content:center;gap:10px;border:1px solid transparent;border-radius:3px;padding:0 20px;font-weight:700;transition:background-color .16s ease,color .16s ease,border-color .16s ease,transform .16s ease}.primary-button{position:relative;overflow:hidden;background:var(--glm-blue);color:#fff}.primary-button:after{content:"";position:absolute;left:0;bottom:0;width:100%;height:3px;background:var(--glm-green)}.primary-button:hover{background:#3f6378;transform:translateY(-1px)}.primary-button--full{width:100%}.primary-button--full svg:last-child{margin-left:auto}.secondary-button{background:#fff;border-color:var(--glm-blue);color:var(--glm-blue)}.secondary-button:hover{background:var(--soft)}.secondary-button--quiet{border-color:var(--line);color:var(--text)}.danger-button{background:transparent;border-color:#e4c6c1;color:var(--danger)}.danger-button:hover{background:#fdecea;border-color:var(--danger)}.danger-button--solid{background:var(--danger);border-color:var(--danger);color:#fff}.text-button{min-height:40px;border:0;border-bottom:1px solid currentColor;padding:0;background:transparent;color:var(--glm-blue);font-weight:700}.text-button--muted{color:var(--muted);font-size:.78rem}.text-button--danger{color:var(--danger);font-size:.78rem}.icon-button,.favorite-button{width:44px;height:44px;display:inline-grid;flex:0 0 auto;place-items:center;border:1px solid var(--line);border-radius:50%;background:#fff;color:var(--glm-blue)}.icon-button:hover,.favorite-button:hover{border-color:var(--glm-blue);background:var(--soft)}.icon-button--quiet{width:36px;height:36px;border-color:transparent;background:transparent}.icon-button--accent{border-radius:3px;background:var(--glm-blue);border-color:var(--glm-blue);color:#fff}.favorite-button.is-favorite{border-color:#d7e58f;background:#f8f9df;color:#718000}.app-mark{position:relative;display:inline-grid;flex:0 0 auto;place-items:center;overflow:visible;background:transparent}.app-mark--small{width:44px;height:44px}.app-mark--regular{width:58px;height:58px}.app-mark--large{width:72px;height:72px}.app-mark img{display:block;width:100%;height:100%;object-fit:contain}.app-mark__placeholder{color:#a7a7a7}.login-shell{min-height:100vh;display:grid;grid-template-columns:minmax(0,1.28fr) minmax(420px,.72fr);background:#fff}.login-story{position:relative;min-height:100vh;display:flex;flex-direction:column;overflow:hidden;border-right:1px solid var(--line);padding:42px clamp(40px,5vw,82px) 36px;background:#fff}.login-story:before{content:"";position:absolute;top:0;left:clamp(40px,5vw,82px);width:3px;height:126px;background:var(--glm-green)}.login-story__topline{position:relative;z-index:2;display:flex;align-items:flex-start;justify-content:space-between;gap:24px;padding-left:18px}.login-story__edition{padding-top:10px;color:var(--glm-blue);font-size:.7rem;font-weight:700;letter-spacing:.18em}.login-story__content{position:relative;z-index:2;width:min(760px,92%);margin:auto 0;padding:80px 0 76px}.login-story h1{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:clamp(3.5rem,6.35vw,7.7rem);font-weight:900;letter-spacing:-.075em;line-height:.85}.login-story h1 span{display:block;margin-top:.14em;color:var(--text);font-family:Arial,sans-serif;font-size:.49em;font-weight:400;letter-spacing:-.052em;line-height:1}.login-story__lede{max-width:540px;margin:36px 0 0;padding-left:20px;border-left:3px solid var(--glm-green);color:var(--text);font-size:clamp(1rem,1.35vw,1.2rem);line-height:1.55}.login-story__signal{position:relative;z-index:2;display:grid;grid-template-columns:auto minmax(40px,1fr) auto;align-items:center;gap:14px;max-width:530px;color:var(--glm-blue);font-size:.7rem;font-weight:700;letter-spacing:.14em}.login-story__signal-line{height:1px;background:var(--line)}.login-story__signal-line:before{content:"";display:block;width:18%;height:2px;background:var(--glm-green)}.login-story__place{position:relative;z-index:2;margin:10px 0 0;color:var(--muted);font-size:.65rem;letter-spacing:.16em}.login-story__type{position:absolute;right:-.06em;bottom:-.28em;color:var(--soft);font-family:Arial Black,Arial,sans-serif;font-size:clamp(13rem,27vw,31rem);font-weight:900;letter-spacing:-.13em;line-height:1;pointer-events:none;-webkit-user-select:none;user-select:none}.login-panel{min-height:100vh;display:grid;place-items:center;padding:48px clamp(34px,4vw,72px);background:var(--soft)}.login-panel__inner{width:min(100%,460px)}.login-panel__heading h2{margin:0 0 10px;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:clamp(2rem,3vw,3rem);letter-spacing:-.045em;line-height:1}.login-panel__heading>p:last-child{margin:0;color:var(--muted);line-height:1.55}.login-form{margin-top:34px}.form-field{display:grid;gap:8px;margin-bottom:20px}.form-field label{color:var(--text);font-size:.81rem;font-weight:700}.form-field label>span{margin-left:6px;color:var(--muted);font-size:.72rem;font-weight:400}.form-field label>.required-mark,.editor-form__section-title>.required-mark{margin-left:4px;color:var(--danger);font-size:1em;font-weight:700}.form-field__label-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.form-field__label-row>span{color:var(--muted);font-size:.7rem}.form-field input,.form-field textarea,.form-field select{width:100%;border:1px solid var(--line);border-radius:3px;background:#fff;color:var(--text);transition:border-color .14s ease,box-shadow .14s ease}.form-field input,.form-field select{height:50px;padding:0 14px}.form-field textarea{min-height:94px;resize:vertical;padding:13px 14px;line-height:1.5}.form-field input::placeholder,.form-field textarea::placeholder{color:#8a8a8a}.form-field input:hover,.form-field textarea:hover,.form-field select:hover{border-color:#97a9b3}.form-field input:focus,.form-field textarea:focus,.form-field select:focus{border-color:var(--glm-blue);box-shadow:inset 3px 0 0 var(--glm-green);outline:none}.form-field input[aria-invalid=true],.form-field textarea[aria-invalid=true]{border-color:var(--danger)}.password-field,.url-field{position:relative}.password-field input{padding-right:50px}.password-field__toggle{position:absolute;top:3px;right:3px;width:44px;height:44px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue)}.form-error,.field-error{color:var(--danger);font-size:.77rem;line-height:1.4}.form-error{margin:-4px 0 18px;padding:11px 12px;border-left:3px solid var(--danger);background:#fdecea}.check-control{min-height:44px;display:flex;align-items:center;gap:10px;margin:2px 0 18px;color:var(--text);font-size:.8rem;cursor:pointer}.check-control input{position:absolute;width:1px;height:1px;overflow:hidden;opacity:0}.check-control>span{width:20px;height:20px;display:grid;place-items:center;border:1px solid var(--line);border-radius:2px;background:#fff;color:transparent}.check-control input:checked+span{border-color:var(--glm-blue);background:var(--glm-blue);color:#fff}.check-control input:focus-visible+span{outline:3px solid var(--glm-green);outline-offset:3px}.demo-access{margin-top:30px}.demo-access__label,.app-preview__label{display:flex;align-items:center;gap:12px;color:var(--muted);font-size:.62rem;font-weight:700;letter-spacing:.14em}.demo-access__rule,.app-preview__rule{height:1px;flex:1;background:var(--line)}.demo-access__options{margin-top:10px;border-top:1px solid var(--line)}.demo-access__options button{width:100%;min-height:62px;display:grid;grid-template-columns:24px 1fr 20px;align-items:center;gap:12px;border:0;border-bottom:1px solid var(--line);padding:8px 4px;background:transparent;color:var(--glm-blue);text-align:left}.demo-access__options button:hover{padding-left:10px;background:#fff}.demo-access__options button span{display:grid;gap:3px}.demo-access__options button strong{color:var(--text);font-size:.8rem}.demo-access__options button small{color:var(--muted);font-size:.69rem}.demo-note{margin:18px 0 0;color:var(--muted);font-size:.68rem;line-height:1.45}.app-shell{min-height:100vh;background:#fff}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:20;width:var(--sidebar-width);display:flex;flex-direction:column;border-right:1px solid var(--line);background:#fff}.sidebar__brand{height:116px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:7px;border-bottom:1px solid var(--line);padding:0 26px}.sidebar__brand span{color:var(--glm-blue);font-size:.58rem;font-weight:700;letter-spacing:.28em}.sidebar__nav{display:grid;gap:4px;padding:28px 16px}.sidebar__nav button{position:relative;min-height:52px;display:flex;align-items:center;gap:14px;border:0;border-radius:2px;padding:0 14px;background:transparent;color:var(--muted);font-size:.82rem;font-weight:700;text-align:left}.sidebar__nav button:hover{background:var(--soft);color:var(--glm-blue)}.sidebar__nav button.is-active{background:var(--green-soft);color:var(--glm-blue)}.sidebar__meta{padding:22px 28px;border-top:1px solid var(--line)}.sidebar__meta p{margin:12px 0 0;color:var(--muted);font-size:.6rem;font-weight:700;letter-spacing:.14em}.sidebar__meta p+p{margin-top:4px}.sidebar__account{margin-top:auto;min-height:88px;display:flex;align-items:center;gap:10px;border-top:1px solid var(--line);padding:16px}.avatar{width:38px;height:38px;display:grid;flex:0 0 auto;place-items:center;overflow:hidden;border-radius:50%;background:var(--glm-blue);color:#fff;font-size:.67rem;font-weight:700;letter-spacing:.03em}.avatar img{display:block;width:100%;height:100%;object-fit:cover}.sidebar__account-copy{min-width:0;flex:1;display:grid;gap:3px}.sidebar__account-copy strong,.sidebar__account-copy small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sidebar__account-copy strong{color:var(--text);font-size:.77rem}.sidebar__account-copy small{color:var(--muted);font-size:.62rem}.sidebar__account .icon-button{width:38px;height:38px;border:0}.mobile-header,.mobile-nav{display:none}.page-content{min-height:100vh;margin-left:var(--sidebar-width);padding:42px clamp(36px,5vw,82px) 72px}.page-header{display:flex;align-items:flex-end;justify-content:space-between;gap:30px;padding-bottom:30px;border-bottom:1px solid var(--line)}.page-header__meta{margin:0 0 9px;color:var(--glm-blue);font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.page-header h1{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:clamp(2.4rem,4.2vw,4.85rem);letter-spacing:-.065em;line-height:.9}.page-header__aside{display:grid;justify-items:end;padding-bottom:4px}.page-header__aside>span:last-child{color:var(--muted);font-size:.82rem;font-weight:700;line-height:1.35;white-space:nowrap}.inline-alert{margin-top:18px;border-left:3px solid var(--glm-orange);padding:12px 14px;background:#fff8e1;color:var(--text);font-size:.82rem}.search-stage{position:relative;overflow:hidden;display:flex;flex-direction:column;align-items:stretch;gap:22px;margin-top:38px;border-left:3px solid var(--glm-green);padding:34px 38px 32px;background:var(--soft)}.search-stage__copy,.hub-search{position:relative;z-index:2}.search-stage h2,.section-heading h2,.admin-bridge h2,.access-request-bridge h2,.admin-list h2,.app-editor h2{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;letter-spacing:-.04em}.search-stage h2{max-width:100%;font-size:clamp(2rem,3.3vw,3.5rem);line-height:1.05}.hub-search{min-height:62px;display:grid;grid-template-columns:24px 1fr auto;align-items:center;gap:13px;border-bottom:2px solid var(--glm-blue);background:#fff;padding:0 16px;color:var(--glm-blue)}.hub-search:focus-within{border-bottom-color:var(--glm-green);box-shadow:0 0 0 1px var(--line)}.hub-search input{width:100%;height:60px;border:0;outline:0;background:transparent;color:var(--text);font-size:.96rem}.hub-search input::placeholder{color:#747474}.hub-search button{width:40px;height:40px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue)}.hub-search kbd{border:1px solid var(--line);border-radius:3px;padding:4px 7px;background:var(--soft);color:var(--muted);font-family:Arial,sans-serif;font-size:.65rem}.search-stage__coordinate{position:absolute;top:-.31em;right:.02em;color:#e9e9e9;font-family:Arial Black,Arial,sans-serif;font-size:clamp(5.5rem,10vw,10rem);letter-spacing:-.08em;line-height:1;-webkit-user-select:none;user-select:none}.quick-section,.directory-section{margin-top:64px}.section-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:28px;margin-bottom:22px}.section-heading h2{font-size:clamp(1.75rem,2.5vw,2.8rem)}.section-heading>p{max-width:340px;margin:0 0 2px;color:var(--muted);font-size:.82rem;line-height:1.5;text-align:right}.quick-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));align-items:stretch;gap:14px}.quick-launch{--card-accent: var(--glm-green);min-width:0;min-height:360px;display:flex;flex-direction:column;border:1px solid var(--line);border-top:3px solid var(--glm-green);border-radius:2px;padding:28px;background:#fff;transition:border-color .16s ease,transform .16s ease}.quick-launch:hover{border-right-color:var(--glm-blue);border-bottom-color:var(--glm-blue);border-left-color:var(--glm-blue);transform:translateY(-3px)}.quick-launch__top{display:flex;align-items:flex-start;justify-content:space-between;gap:20px}.quick-launch__copy{flex:1;margin-top:48px}.quick-launch__meta{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.access-indicator{display:inline-flex;align-items:center;gap:7px;color:var(--muted);font-size:.67rem;font-weight:700;white-space:nowrap}.access-indicator>span{width:7px;height:7px;flex:0 0 auto;border-radius:50%;background:var(--line)}.access-indicator--granted{color:#4f758b}.access-indicator--granted>span{background:var(--glm-green);box-shadow:0 0 0 3px var(--green-soft)}.access-indicator--denied{color:#b3261e}.access-indicator--denied>span{background:#d32f2f;box-shadow:0 0 0 3px #fde8e7}.access-indicator--checking{color:#7a7a7a}.access-indicator--checking>span{background:#a8a8a8;box-shadow:0 0 0 3px #f0f0f0}.quick-launch__category{color:var(--glm-blue);font-size:.64rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}.quick-launch h3,.preview-card h3{margin:9px 0 8px;color:var(--text);font-family:Arial Black,Arial,sans-serif;font-size:1.35rem;letter-spacing:-.035em;line-height:1.05}.quick-launch h3{color:var(--glm-blue);font-size:1.55rem}.quick-launch p,.preview-card p{margin:0;color:var(--muted);font-size:.82rem;line-height:1.5}.quick-launch__action{width:100%;min-height:46px;display:flex;align-items:center;justify-content:space-between;gap:14px;margin-top:auto;border:0;border-top:1px solid var(--line);padding:13px 0 0;background:transparent;color:var(--glm-blue);font-size:.76rem;font-weight:700;text-align:left}.quick-launch__action:hover{color:var(--glm-teal)}.section-heading--directory{padding-bottom:18px;border-bottom:1px solid var(--line)}.directory-count{display:flex;align-items:baseline;gap:7px}.directory-count strong{color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:2rem;letter-spacing:-.06em}.directory-count span{color:var(--muted);font-size:.7rem}.filter-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:18px;flex-wrap:wrap}.category-filters{display:flex;align-items:center;gap:4px}.filter-bar__search{flex:1;max-width:360px;min-width:220px;min-height:42px;display:grid;grid-template-columns:18px 1fr auto;align-items:center;gap:10px;border:1px solid var(--line);border-radius:2px;background:#fff;padding:0 12px;color:var(--glm-blue);transition:border-color .16s ease,box-shadow .16s ease}.filter-bar__search:focus-within{border-color:var(--glm-blue);box-shadow:0 0 0 1px var(--glm-blue)}.filter-bar__search input{width:100%;height:40px;border:0;outline:0;background:transparent;color:var(--text);font-size:.82rem}.filter-bar__search input::placeholder{color:#8a8a8a}.filter-bar__search button{width:24px;height:24px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue);padding:0}.category-filters button,.favorites-filter{min-height:44px;border:0;border-bottom:2px solid transparent;padding:0 12px;background:transparent;color:var(--muted);font-size:.74rem;font-weight:700;white-space:nowrap}.category-filters button:hover,.favorites-filter:hover{color:var(--glm-blue)}.category-filters button.is-active{border-bottom-color:var(--glm-green);color:var(--glm-blue)}.favorites-filter{display:inline-flex;align-items:center;gap:8px}.favorites-filter.is-active{border-bottom-color:var(--glm-lime);color:#617000}.directory-list{border-top:1px solid var(--text)}.pagination{display:flex;align-items:center;justify-content:center;gap:8px;margin-top:24px}.pagination__pages{display:flex;align-items:center;justify-content:center;gap:6px}.pagination__arrow,.pagination__page{width:36px;height:36px;display:grid;flex:0 0 auto;place-items:center;border:1px solid var(--line);border-radius:3px;background:#fff;color:var(--glm-blue);font-size:.74rem;font-weight:700;transition:background-color .14s ease,border-color .14s ease,color .14s ease}.pagination__arrow:hover:not(:disabled),.pagination__page:hover:not(.is-active){border-color:var(--glm-blue);background:var(--soft)}.pagination__page.is-active{border-color:var(--glm-blue);background:var(--glm-blue);color:#fff}.pagination__arrow:disabled{cursor:not-allowed;opacity:.35}.pagination__ellipsis{width:24px;color:var(--muted);font-size:.8rem;line-height:1;text-align:center}.pagination--compact{gap:5px}.pagination--compact .pagination__pages{gap:4px}.pagination--compact .pagination__arrow,.pagination--compact .pagination__page{width:30px;height:30px;font-size:.66rem}.pagination--compact .pagination__ellipsis{width:16px;font-size:.7rem}.directory-row{min-height:92px;display:grid;grid-template-columns:42px 44px minmax(220px,1fr) 110px 128px 44px 86px;align-items:center;gap:14px;border-bottom:1px solid var(--line);padding:14px 0;transition:background-color .14s ease,padding .14s ease}.directory-row:hover{padding-right:10px;padding-left:10px;background:var(--soft)}.directory-row__number{color:#919191;font-family:Arial Black,Arial,sans-serif;font-size:.65rem;letter-spacing:.06em}.directory-row__copy{min-width:0}.directory-row__copy h3{margin:0 0 5px;color:var(--text);font-size:.92rem;line-height:1.2}.directory-row__copy p{overflow:hidden;margin:0;color:var(--muted);font-size:.72rem;line-height:1.4;text-overflow:ellipsis;white-space:nowrap}.directory-row__status{display:inline-flex;align-items:center}.directory-row__category{color:var(--glm-blue);font-size:.65rem;font-weight:700}.availability{display:inline-flex;align-items:center;gap:7px;color:var(--muted);font-size:.67rem;font-weight:700;white-space:nowrap}.availability>span{width:7px;height:7px;flex:0 0 auto;border-radius:50%;background:var(--line)}.availability--ready>span{background:var(--glm-green);box-shadow:0 0 0 3px var(--green-soft)}.availability--pending>span{background:var(--glm-orange);box-shadow:0 0 0 3px #fff1e8}.directory-row .favorite-button{width:40px;height:40px;border:0;background:transparent}.directory-row__open{min-height:42px;display:flex;align-items:center;justify-content:flex-end;gap:7px;border:0;background:transparent;color:var(--glm-blue);font-size:.74rem;font-weight:700}.empty-state{min-height:280px;display:grid;grid-template-columns:minmax(110px,.35fr) minmax(260px,.65fr);align-items:center;gap:40px;border-top:1px solid var(--text);border-bottom:1px solid var(--line);padding:38px}.empty-state__mark{color:var(--soft);font-family:Arial Black,Arial,sans-serif;font-size:10rem;letter-spacing:-.1em;line-height:.7}.empty-state h3{margin:0 0 8px;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:1.6rem;letter-spacing:-.04em}.empty-state p:not(.section-kicker){margin:0 0 18px;color:var(--muted);font-size:.84rem;line-height:1.5}.admin-bridge{position:relative;overflow:hidden;min-height:190px;display:grid;grid-template-columns:minmax(70px,.25fr) minmax(300px,1fr) auto;align-items:center;gap:30px;margin-top:70px;border-top:1px solid var(--text);border-bottom:3px solid var(--glm-green);padding:30px 8px}.admin-bridge__number{color:var(--glm-green);font-family:Arial Black,Arial,sans-serif;font-size:7rem;line-height:.7}.admin-bridge h2{font-size:2rem}.admin-bridge p:not(.section-kicker){margin:8px 0 0;color:var(--muted);font-size:.84rem;line-height:1.5}.access-request-bridge{position:relative;min-height:190px;display:grid;grid-template-columns:minmax(70px,.25fr) minmax(300px,1fr) auto;align-items:center;gap:30px;margin-top:70px;border-top:1px solid var(--text);border-bottom:3px solid var(--glm-green);padding:30px 8px}.access-request-bridge__number{color:var(--glm-green);font-family:Arial Black,Arial,sans-serif;font-size:6.5rem;line-height:.72}.access-request-bridge h2{font-size:2rem}.access-request-bridge p:not(.section-kicker){margin:8px 0 0;color:var(--muted);font-size:.84rem;line-height:1.5}.access-request-dialog{width:min(560px,calc(100vw - 32px));border:0;border-top:4px solid var(--glm-green);border-radius:3px;padding:34px;color:var(--text);box-shadow:0 24px 80px #2d363b38}.access-request-dialog::backdrop{background:#2330378f}.access-request-dialog__close{position:absolute;top:12px;right:12px;width:40px;height:40px;display:grid;place-items:center;border:0;background:transparent;color:var(--muted)}.access-request-dialog h2{margin:0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:2rem;letter-spacing:-.04em}.access-request-dialog__intro{margin:10px 0 34px;color:var(--muted);font-size:.82rem;line-height:1.55}.access-request-dialog form{display:grid;gap:20px;margin-top:4px}.access-request-dialog__actions{display:flex;justify-content:flex-end;gap:10px;margin-top:8px;padding-top:22px;border-top:1px solid var(--line)}.back-button{min-height:40px;display:inline-flex;align-items:center;gap:8px;margin-bottom:18px;border:0;border-bottom:1px solid var(--line);padding:0;background:transparent;color:var(--glm-blue);font-size:.75rem;font-weight:700}.admin-header{align-items:center}.admin-header__note{display:flex;align-items:center;gap:12px;border-left:3px solid var(--glm-green);padding:10px 0 10px 14px;color:var(--glm-blue)}.admin-header__note span{display:grid;gap:3px}.admin-header__note strong{color:var(--text);font-size:.74rem}.admin-header__note small{color:var(--muted);font-size:.66rem}.admin-workspace{min-height:680px;display:grid;grid-template-columns:300px minmax(0,1fr);margin-top:34px;border:1px solid var(--line)}.admin-list{min-width:0;display:flex;flex-direction:column;border-right:1px solid var(--line);background:var(--soft)}.admin-list__top{min-height:94px;display:flex;align-items:center;justify-content:space-between;gap:20px;border-bottom:1px solid var(--line);padding:20px}.admin-list h2{font-size:1.25rem}.admin-list__search{display:grid;grid-template-columns:20px 1fr auto;align-items:center;gap:9px;margin:14px;border:1px solid var(--line);background:#fff;padding:0 11px;color:var(--glm-blue)}.admin-list__search input{width:100%;height:42px;border:0;outline:0;background:transparent;font-size:.77rem}.admin-list__search button{width:24px;height:24px;display:grid;place-items:center;border:0;background:transparent;color:var(--glm-blue)}.admin-list__items{min-height:0;flex:1;overflow-y:auto;border-top:1px solid var(--line)}.admin-list__items>button,.admin-list__item-row{position:relative;width:100%;min-height:70px;display:grid;grid-template-columns:44px minmax(0,1fr) auto;align-items:center;gap:11px;border:0;border-bottom:1px solid var(--line);padding:10px 14px;background:transparent;text-align:left;cursor:pointer}.admin-list__items>button:hover,.admin-list__item-row:hover{background:#fff}.admin-list__items>button.is-active,.admin-list__item-row.is-active{background:#fff}.admin-list__items>button.is-active:before,.admin-list__item-row.is-active:before{content:"";position:absolute;top:0;bottom:0;left:0;width:3px;background:var(--glm-green)}.admin-list__item-info{min-width:0;display:flex;flex-direction:column;gap:3px;text-align:left}.admin-list__item-info strong{display:block;color:var(--text);font-size:.76rem;font-weight:700;line-height:1.25}.admin-list__item-info small{display:block;color:var(--muted);font-size:.64rem;font-weight:400;line-height:1.2}.admin-list__item-actions{display:flex;align-items:center;gap:8px}.admin-list__delete-icon{width:28px;height:28px;display:grid;place-items:center;border:0;border-radius:3px;background:transparent;color:#a0a0a0;transition:color .14s ease,background-color .14s ease}.admin-list__delete-icon:hover{color:var(--danger);background:#fdecea}.admin-list__items strong,.admin-list__items small{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.admin-list__new-icon{width:38px;height:38px;display:grid;place-items:center;border:1px dashed var(--glm-blue);border-radius:3px;color:var(--glm-blue)}.mini-status{color:var(--glm-blue);font-size:.57rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase}.mini-status.is-hidden{color:var(--muted)}.admin-list>.pagination{flex:0 0 auto;justify-content:space-between;margin-top:0;border-top:1px solid var(--line);padding:10px 12px;background:#fff}.app-editor{min-width:0;padding:28px clamp(24px,3.4vw,52px) 44px}.app-editor__heading{display:flex;align-items:flex-start;justify-content:space-between;gap:24px;border-bottom:1px solid var(--line);padding-bottom:20px}.app-editor h2{font-size:clamp(1.5rem,2.4vw,2.35rem)}.dirty-state{display:inline-flex;align-items:center;gap:7px;color:var(--muted);font-size:.65rem;font-weight:700;white-space:nowrap}.dirty-state>span{width:7px;height:7px;border-radius:50%;background:var(--glm-green)}.dirty-state.is-dirty>span{background:var(--glm-orange)}.editor-layout{display:grid;grid-template-columns:minmax(0,1fr) 260px;align-items:start;gap:clamp(28px,4vw,54px);margin-top:28px}.editor-form__section{display:grid;gap:18px;margin:0;border-bottom:1px solid var(--line);padding:0 0 28px}.editor-form__section+.editor-form__section{padding-top:28px}.editor-form__section-title{margin:0 0 2px;color:var(--glm-blue);font-size:.72rem;font-weight:700;letter-spacing:.12em;line-height:1.2;text-transform:uppercase}.editor-form .form-field{margin:0}.form-split{display:grid;grid-template-columns:1fr 1fr;gap:16px}.field-meta{display:flex;justify-content:space-between;gap:14px;color:var(--muted);font-size:.66rem;line-height:1.4}.field-meta>span:last-child{flex:0 0 auto}.field-meta--counter-only{justify-content:flex-end}.field-help{color:var(--muted);font-size:.67rem;line-height:1.4}.field-error--standalone{margin:0}.icon-config{display:flex;align-items:center;gap:18px}.ai-icon-button:disabled{cursor:default}.ai-icon-actions{display:flex;align-items:center}.ai-icon-button{min-height:44px}.icon-dropzone{min-height:80px;display:grid;flex:1;grid-template-columns:42px 1fr;align-items:center;gap:13px;border:1px dashed var(--glm-blue);border-radius:3px;padding:14px;background:var(--soft);cursor:pointer;transition:border-color .14s ease,background-color .14s ease}.icon-dropzone:hover,.icon-dropzone.is-dragging{border-color:var(--glm-green);background:var(--green-soft)}.icon-dropzone input{position:absolute;width:1px;height:1px;overflow:hidden;opacity:0}.icon-dropzone:focus-within{outline:3px solid var(--glm-green);outline-offset:3px}.icon-dropzone__symbol{width:42px;height:42px;display:grid;place-items:center;border-radius:3px;background:#fff;color:var(--glm-blue)}.icon-dropzone>span:last-child{display:grid;gap:4px}.icon-dropzone strong{color:var(--text);font-size:.77rem}.icon-dropzone small{color:var(--muted);font-size:.65rem}.url-field{display:grid;grid-template-columns:24px 1fr;align-items:center;border:1px solid var(--line);border-radius:3px;padding:0 12px;background:#fff;color:var(--glm-blue)}.url-field:focus-within{border-color:var(--glm-blue);box-shadow:inset 3px 0 0 var(--glm-green)}.url-field input{border:0;box-shadow:none;padding:0 3px}.url-field input:focus{box-shadow:none}.editor-actions{display:flex;align-items:center;gap:10px;padding-top:26px}.editor-actions .danger-button{margin-left:auto}.app-preview{position:sticky;top:28px}.preview-card{min-height:302px;display:flex;flex-direction:column;align-items:flex-start;margin-top:14px;border:1px solid var(--line);border-top:3px solid var(--glm-green);padding:22px;background:#fff}.preview-card .app-mark{margin-bottom:36px}.preview-card .availability{margin-top:auto;padding-top:24px}.app-preview__note{margin:12px 0 0;color:var(--muted);font-size:.65rem;line-height:1.45}.confirm-dialog{width:min(440px,calc(100vw - 32px));border:0;border-top:4px solid var(--danger);border-radius:3px;padding:30px;color:var(--text);box-shadow:0 24px 80px #2d363b38}.confirm-dialog::backdrop{background:#2330378f}.confirm-dialog__close{position:absolute;top:12px;right:12px;width:40px;height:40px;display:grid;place-items:center;border:0;background:transparent;color:var(--muted)}.confirm-dialog__icon{width:48px;height:48px;display:grid;place-items:center;margin-bottom:28px;border-radius:50%;background:#fdecea;color:var(--danger)}.confirm-dialog h2{margin:0;color:var(--text);font-family:Arial Black,Arial,sans-serif;font-size:1.6rem;letter-spacing:-.04em}.confirm-dialog>p:not(.section-kicker){margin:12px 0 0;color:var(--muted);font-size:.82rem;line-height:1.55}.confirm-dialog__actions{display:flex;justify-content:flex-end;gap:10px;margin-top:28px}.generation-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:200;display:grid;place-items:center;padding:24px;background:#162128b8;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.generation-overlay__card{width:min(460px,100%);display:grid;justify-items:center;border-top:4px solid var(--glm-green);padding:38px 34px;background:#fff;box-shadow:0 24px 70px #00000047;text-align:center}.generation-overlay__card h2{margin:10px 0 0;color:var(--glm-blue);font-family:Arial Black,Arial,sans-serif;font-size:1.75rem;letter-spacing:-.04em}.generation-overlay__card>p:last-child{max-width:350px;margin:12px 0 0;color:var(--muted);font-size:.82rem;line-height:1.5}.generation-spinner{width:40px;height:40px;margin-bottom:20px;border:4px solid var(--line);border-top-color:var(--glm-green);border-radius:50%;animation:glm-spin .8s linear infinite}.catalog-loading{min-height:100vh;display:grid;place-items:center;align-content:center;gap:18px;background:#fff;color:var(--glm-blue);font-size:.85rem;font-weight:700}.catalog-loading .brand-logo{width:150px;margin-bottom:8px}.catalog-loading .generation-spinner,.catalog-loading p{margin:0}@keyframes glm-spin{to{transform:rotate(360deg)}}.toast-stack{position:fixed;right:24px;bottom:24px;z-index:100;width:min(390px,calc(100vw - 32px));display:grid;gap:10px}.toast{position:relative;display:grid;grid-template-columns:3px 1fr 36px;align-items:center;gap:14px;overflow:hidden;border:1px solid var(--line);border-radius:3px;padding:13px 10px 13px 0;background:#fff;box-shadow:0 16px 44px #32444e29}.toast__signal{align-self:stretch;background:var(--glm-green)}.toast>div,.toast .icon-button{align-self:center}.toast--info .toast__signal{background:var(--glm-blue)}.toast--error .toast__signal{background:var(--danger)}.toast strong{display:block;margin-top:0;color:var(--text);font-size:.8rem}.toast p{margin:4px 0 0;color:var(--muted);font-size:.7rem;line-height:1.45}@media(max-width:1240px){:root{--sidebar-width: 214px}.sidebar__brand{padding:0 20px}.sidebar__brand .brand-logo{width:140px}.sidebar__account-copy{display:none}.directory-row{grid-template-columns:34px 44px minmax(190px,1fr) 112px 44px 80px}.directory-row__category{display:none}.editor-layout{grid-template-columns:minmax(0,1fr) 230px;gap:28px}}@media(max-width:1360px){.editor-layout{grid-template-columns:1fr}.app-preview{position:static}.preview-card{width:100%;min-height:260px}}@media(max-width:1040px){.page-content{padding-right:32px;padding-left:32px}.search-stage{gap:20px}.quick-grid{grid-template-columns:1fr 1fr}.directory-row{grid-template-columns:34px 44px minmax(160px,1fr) 108px 44px 44px}.directory-row__open span{display:none}.admin-workspace{grid-template-columns:250px minmax(0,1fr)}}@media(max-width:860px){:root{--mobile-header-height: 72px;--mobile-nav-height: 72px}.login-shell{grid-template-columns:1fr}.login-story{min-height:540px;border-right:0;border-bottom:1px solid var(--line)}.login-story__content{margin:auto 0 0;padding:72px 0 54px}.login-story__type{right:-.03em;bottom:-.3em;font-size:20rem}.login-panel{min-height:auto;padding-top:64px;padding-bottom:64px}.sidebar{display:none}.mobile-header{position:fixed;top:0;right:0;left:0;z-index:30;height:var(--mobile-header-height);display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line);padding:10px 22px;background:#fffffff5}.mobile-header:before{content:"";position:absolute;top:0;left:0;width:94px;height:3px;background:var(--glm-green)}.mobile-header .brand-logo{width:135px}.mobile-nav{position:fixed;right:0;bottom:0;left:0;z-index:30;min-height:var(--mobile-nav-height);display:flex;align-items:stretch;justify-content:center;border-top:1px solid var(--line);background:#fffffffa}.mobile-nav button{min-width:92px;min-height:66px;display:grid;place-items:center;align-content:center;gap:5px;border:0;border-top:3px solid transparent;background:transparent;color:var(--muted);font-size:.62rem;font-weight:700}.mobile-nav button.is-active{border-top-color:var(--glm-green);color:var(--glm-blue)}.page-content{margin-left:0;padding-top:calc(var(--mobile-header-height) + 34px);padding-bottom:calc(var(--mobile-nav-height) + 42px)}.filter-bar{align-items:flex-start;flex-direction:column}.category-filters{width:100%;overflow-x:auto;padding-bottom:3px}.directory-row{grid-template-columns:44px minmax(150px,1fr) 108px 44px 44px}.directory-row__number{display:none}.admin-bridge,.access-request-bridge{grid-template-columns:80px 1fr}.admin-bridge .secondary-button,.access-request-bridge .secondary-button{grid-column:2;justify-self:start}.admin-workspace{grid-template-columns:1fr}.admin-list{max-height:360px;border-right:0;border-bottom:1px solid var(--line)}.admin-list__items{max-height:210px}}@media(max-width:620px){.login-story{min-height:480px;padding:26px 22px 24px}.login-story:before{left:22px;height:90px}.login-story__topline{padding-left:12px}.login-story .brand-logo{width:160px}.login-story__edition{font-size:.58rem}.login-story__content{width:100%;padding:62px 0 42px}.login-story h1{font-size:clamp(3.25rem,15.5vw,5rem)}.login-story__lede{margin-top:26px;font-size:.95rem}.login-story__signal,.login-story__place{font-size:.54rem}.login-story__type{font-size:12rem}.login-panel{padding:48px 22px}.page-content{padding-right:18px;padding-left:18px}.page-header{padding-bottom:23px}.page-header h1{font-size:2.7rem}.page-header__aside,.admin-header__note{display:none}.search-stage{margin-top:26px;padding:26px 18px 22px}.search-stage__coordinate{opacity:.58}.hub-search{grid-template-columns:22px 1fr auto;min-height:58px;padding:0 12px}.hub-search input{min-width:0;font-size:.84rem}.hub-search kbd{display:none}.pagination{gap:4px}.pagination__pages{gap:3px}.pagination__arrow,.pagination__page{width:32px;height:32px}.quick-section,.directory-section{margin-top:48px}.section-heading{align-items:flex-start;flex-direction:column;gap:12px}.section-heading>p{text-align:left}.section-heading--directory{flex-direction:row;align-items:flex-end}.quick-grid{grid-template-columns:1fr}.quick-launch{min-height:330px;padding:20px}.quick-launch__copy{margin-top:28px}.directory-row{min-height:86px;grid-template-columns:44px minmax(0,1fr) 40px 38px;gap:9px}.directory-row__category,.directory-row .availability,.directory-row__status{display:none}.directory-row__copy p{max-width:100%}.directory-row .favorite-button,.directory-row__open{width:38px;height:38px;min-height:38px}.empty-state{grid-template-columns:1fr;gap:16px;padding:30px 18px}.empty-state__mark{font-size:6rem}.admin-bridge,.access-request-bridge{grid-template-columns:54px 1fr;gap:16px}.admin-bridge__number,.access-request-bridge__number{font-size:5rem}.admin-bridge h2,.access-request-bridge h2{font-size:1.65rem}.admin-bridge .secondary-button,.access-request-bridge .secondary-button{grid-column:1 / -1;width:100%}.access-request-dialog{padding:28px 20px 22px}.access-request-dialog__actions{flex-direction:column-reverse}.access-request-dialog__actions button{width:100%}.admin-page{padding-right:12px;padding-left:12px}.admin-workspace{margin-top:26px}.app-editor{padding:24px 16px 36px}.app-editor__heading{align-items:flex-start;flex-direction:column;gap:12px}.form-split{grid-template-columns:1fr}.icon-config{align-items:flex-start;flex-direction:column}.icon-dropzone{width:100%}.editor-actions{align-items:stretch;flex-direction:column}.editor-actions .danger-button{margin-left:0}.app-preview{grid-template-columns:1fr}.preview-card{width:100%}.confirm-dialog{padding:26px 20px}.confirm-dialog__actions{align-items:stretch;flex-direction:column}.toast-stack{right:16px;bottom:calc(var(--mobile-nav-height, 0px) + 16px);left:16px;width:auto}}@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,*:before,*:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}} diff --git a/dist/assets/index-CnXPZvfE.js b/dist/assets/index-CnXPZvfE.js new file mode 100644 index 0000000..7f9fc5b --- /dev/null +++ b/dist/assets/index-CnXPZvfE.js @@ -0,0 +1,179 @@ +(function(){const d=document.createElement("link").relList;if(d&&d.supports&&d.supports("modulepreload"))return;for(const O of document.querySelectorAll('link[rel="modulepreload"]'))o(O);new MutationObserver(O=>{for(const A of O)if(A.type==="childList")for(const C of A.addedNodes)C.tagName==="LINK"&&C.rel==="modulepreload"&&o(C)}).observe(document,{childList:!0,subtree:!0});function g(O){const A={};return O.integrity&&(A.integrity=O.integrity),O.referrerPolicy&&(A.referrerPolicy=O.referrerPolicy),O.crossOrigin==="use-credentials"?A.credentials="include":O.crossOrigin==="anonymous"?A.credentials="omit":A.credentials="same-origin",A}function o(O){if(O.ep)return;O.ep=!0;const A=g(O);fetch(O.href,A)}})();var Ss={exports:{}},Tn={};/** + * @license React + * react-jsx-runtime.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Qd;function Jy(){if(Qd)return Tn;Qd=1;var f=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function g(o,O,A){var C=null;if(A!==void 0&&(C=""+A),O.key!==void 0&&(C=""+O.key),"key"in O){A={};for(var Z in O)Z!=="key"&&(A[Z]=O[Z])}else A=O;return O=A.ref,{$$typeof:f,type:o,key:C,ref:O!==void 0?O:null,props:A}}return Tn.Fragment=d,Tn.jsx=g,Tn.jsxs=g,Tn}var wd;function ky(){return wd||(wd=1,Ss.exports=Jy()),Ss.exports}var c=ky(),_s={exports:{}},I={};/** + * @license React + * react.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Xd;function $y(){if(Xd)return I;Xd=1;var f=Symbol.for("react.transitional.element"),d=Symbol.for("react.portal"),g=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),A=Symbol.for("react.consumer"),C=Symbol.for("react.context"),Z=Symbol.for("react.forward_ref"),q=Symbol.for("react.suspense"),E=Symbol.for("react.memo"),Y=Symbol.for("react.lazy"),B=Symbol.for("react.activity"),$=Symbol.iterator;function de(r){return r===null||typeof r!="object"?null:(r=$&&r[$]||r["@@iterator"],typeof r=="function"?r:null)}var V={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},P=Object.assign,K={};function le(r,y,j){this.props=r,this.context=y,this.refs=K,this.updater=j||V}le.prototype.isReactComponent={},le.prototype.setState=function(r,y){if(typeof r!="object"&&typeof r!="function"&&r!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,r,y,"setState")},le.prototype.forceUpdate=function(r){this.updater.enqueueForceUpdate(this,r,"forceUpdate")};function Me(){}Me.prototype=le.prototype;function ge(r,y,j){this.props=r,this.context=y,this.refs=K,this.updater=j||V}var Ae=ge.prototype=new Me;Ae.constructor=ge,P(Ae,le.prototype),Ae.isPureReactComponent=!0;var Oe=Array.isArray;function ze(){}var F={H:null,A:null,T:null,S:null},k=Object.prototype.hasOwnProperty;function me(r,y,j){var M=j.ref;return{$$typeof:f,type:r,key:y,ref:M!==void 0?M:null,props:j}}function Ne(r,y){return me(r.type,y,r.props)}function he(r){return typeof r=="object"&&r!==null&&r.$$typeof===f}function je(r){var y={"=":"=0",":":"=2"};return"$"+r.replace(/[=:]/g,function(j){return y[j]})}var we=/\/+/g;function tt(r,y){return typeof r=="object"&&r!==null&&r.key!=null?je(""+r.key):y.toString(36)}function Ke(r){switch(r.status){case"fulfilled":return r.value;case"rejected":throw r.reason;default:switch(typeof r.status=="string"?r.then(ze,ze):(r.status="pending",r.then(function(y){r.status==="pending"&&(r.status="fulfilled",r.value=y)},function(y){r.status==="pending"&&(r.status="rejected",r.reason=y)})),r.status){case"fulfilled":return r.value;case"rejected":throw r.reason}}throw r}function z(r,y,j,M,G){var X=typeof r;(X==="undefined"||X==="boolean")&&(r=null);var ae=!1;if(r===null)ae=!0;else switch(X){case"bigint":case"string":case"number":ae=!0;break;case"object":switch(r.$$typeof){case f:case d:ae=!0;break;case Y:return ae=r._init,z(ae(r._payload),y,j,M,G)}}if(ae)return G=G(r),ae=M===""?"."+tt(r,0):M,Oe(G)?(j="",ae!=null&&(j=ae.replace(we,"$&/")+"/"),z(G,y,j,"",function(Pe){return Pe})):G!=null&&(he(G)&&(G=Ne(G,j+(G.key==null||r&&r.key===G.key?"":(""+G.key).replace(we,"$&/")+"/")+ae)),y.push(G)),1;ae=0;var Je=M===""?".":M+":";if(Oe(r))for(var _e=0;_e>>1,N=z[L];if(0>>1;LO(j,U))MO(G,j)?(z[L]=G,z[M]=U,L=M):(z[L]=j,z[y]=U,L=y);else if(MO(G,U))z[L]=G,z[M]=U,L=M;else break e}}return R}function O(z,R){var U=z.sortIndex-R.sortIndex;return U!==0?U:z.id-R.id}if(f.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var A=performance;f.unstable_now=function(){return A.now()}}else{var C=Date,Z=C.now();f.unstable_now=function(){return C.now()-Z}}var q=[],E=[],Y=1,B=null,$=3,de=!1,V=!1,P=!1,K=!1,le=typeof setTimeout=="function"?setTimeout:null,Me=typeof clearTimeout=="function"?clearTimeout:null,ge=typeof setImmediate<"u"?setImmediate:null;function Ae(z){for(var R=g(E);R!==null;){if(R.callback===null)o(E);else if(R.startTime<=z)o(E),R.sortIndex=R.expirationTime,d(q,R);else break;R=g(E)}}function Oe(z){if(P=!1,Ae(z),!V)if(g(q)!==null)V=!0,ze||(ze=!0,je());else{var R=g(E);R!==null&&Ke(Oe,R.startTime-z)}}var ze=!1,F=-1,k=5,me=-1;function Ne(){return K?!0:!(f.unstable_now()-mez&&Ne());){var L=B.callback;if(typeof L=="function"){B.callback=null,$=B.priorityLevel;var N=L(B.expirationTime<=z);if(z=f.unstable_now(),typeof N=="function"){B.callback=N,Ae(z),R=!0;break t}B===g(q)&&o(q),Ae(z)}else o(q);B=g(q)}if(B!==null)R=!0;else{var r=g(E);r!==null&&Ke(Oe,r.startTime-z),R=!1}}break e}finally{B=null,$=U,de=!1}R=void 0}}finally{R?je():ze=!1}}}var je;if(typeof ge=="function")je=function(){ge(he)};else if(typeof MessageChannel<"u"){var we=new MessageChannel,tt=we.port2;we.port1.onmessage=he,je=function(){tt.postMessage(null)}}else je=function(){le(he,0)};function Ke(z,R){F=le(function(){z(f.unstable_now())},R)}f.unstable_IdlePriority=5,f.unstable_ImmediatePriority=1,f.unstable_LowPriority=4,f.unstable_NormalPriority=3,f.unstable_Profiling=null,f.unstable_UserBlockingPriority=2,f.unstable_cancelCallback=function(z){z.callback=null},f.unstable_forceFrameRate=function(z){0>z||125L?(z.sortIndex=U,d(E,z),g(q)===null&&z===g(E)&&(P?(Me(F),F=-1):P=!0,Ke(Oe,U-L))):(z.sortIndex=N,d(q,z),V||de||(V=!0,ze||(ze=!0,je()))),z},f.unstable_shouldYield=Ne,f.unstable_wrapCallback=function(z){var R=$;return function(){var U=$;$=R;try{return z.apply(this,arguments)}finally{$=U}}}})(js)),js}var Kd;function Fy(){return Kd||(Kd=1,As.exports=Wy()),As.exports}var zs={exports:{}},et={};/** + * @license React + * react-dom.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Jd;function Iy(){if(Jd)return et;Jd=1;var f=qs();function d(q){var E="https://react.dev/errors/"+q;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(d){console.error(d)}}return f(),zs.exports=Iy(),zs.exports}/** + * @license React + * react-dom-client.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var $d;function ev(){if($d)return xn;$d=1;var f=Fy(),d=qs(),g=Py();function o(e){var t="https://react.dev/errors/"+e;if(1N||(e.current=L[N],L[N]=null,N--)}function j(e,t){N++,L[N]=e.current,e.current=t}var M=r(null),G=r(null),X=r(null),ae=r(null);function Je(e,t){switch(j(X,t),j(G,e),j(M,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?rd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=rd(t),e=od(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}y(M),j(M,e)}function _e(){y(M),y(G),y(X)}function Pe(e){e.memoizedState!==null&&j(ae,e);var t=M.current,l=od(t,e.type);t!==l&&(j(G,e),j(M,l))}function tl(e){G.current===e&&(y(M),y(G)),ae.current===e&&(y(ae),An._currentValue=U)}var li,Ls;function Tl(e){if(li===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);li=t&&t[1]||"",Ls=-1)":-1n||m[a]!==b[n]){var T=` +`+m[a].replace(" at new "," at ");return e.displayName&&T.includes("")&&(T=T.replace("",e.displayName)),T}while(1<=a&&0<=n);break}}}finally{ai=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Tl(l):""}function jm(e,t){switch(e.tag){case 26:case 27:case 5:return Tl(e.type);case 16:return Tl("Lazy");case 13:return e.child!==t&&t!==null?Tl("Suspense Fallback"):Tl("Suspense");case 19:return Tl("SuspenseList");case 0:case 15:return ni(e.type,!1);case 11:return ni(e.type.render,!1);case 1:return ni(e.type,!0);case 31:return Tl("Activity");default:return""}}function Gs(e){try{var t="",l=null;do t+=jm(e,l),l=e,e=e.return;while(e);return t}catch(a){return` +Error generating stack: `+a.message+` +`+a.stack}}var ui=Object.prototype.hasOwnProperty,ii=f.unstable_scheduleCallback,ci=f.unstable_cancelCallback,zm=f.unstable_shouldYield,Nm=f.unstable_requestPaint,rt=f.unstable_now,Tm=f.unstable_getCurrentPriorityLevel,Ys=f.unstable_ImmediatePriority,Qs=f.unstable_UserBlockingPriority,Cn=f.unstable_NormalPriority,xm=f.unstable_LowPriority,ws=f.unstable_IdlePriority,Om=f.log,Dm=f.unstable_setDisableYieldValue,Ra=null,ot=null;function ll(e){if(typeof Om=="function"&&Dm(e),ot&&typeof ot.setStrictMode=="function")try{ot.setStrictMode(Ra,e)}catch{}}var dt=Math.clz32?Math.clz32:Cm,Mm=Math.log,Um=Math.LN2;function Cm(e){return e>>>=0,e===0?32:31-(Mm(e)/Um|0)|0}var Rn=256,qn=262144,Hn=4194304;function xl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Bn(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var n=0,u=e.suspendedLanes,i=e.pingedLanes;e=e.warmLanes;var s=a&134217727;return s!==0?(a=s&~u,a!==0?n=xl(a):(i&=s,i!==0?n=xl(i):l||(l=s&~e,l!==0&&(n=xl(l))))):(s=a&~u,s!==0?n=xl(s):i!==0?n=xl(i):l||(l=a&~e,l!==0&&(n=xl(l)))),n===0?0:t!==0&&t!==n&&(t&u)===0&&(u=n&-n,l=t&-t,u>=l||u===32&&(l&4194048)!==0)?t:n}function qa(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Rm(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Xs(){var e=Hn;return Hn<<=1,(Hn&62914560)===0&&(Hn=4194304),e}function si(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function Ha(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function qm(e,t,l,a,n,u){var i=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var s=e.entanglements,m=e.expirationTimes,b=e.hiddenUpdates;for(l=i&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Qm=/[\n"\\]/g;function _t(e){return e.replace(Qm,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function hi(e,t,l,a,n,u,i,s){e.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?e.type=i:e.removeAttribute("type"),t!=null?i==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+St(t)):e.value!==""+St(t)&&(e.value=""+St(t)):i!=="submit"&&i!=="reset"||e.removeAttribute("value"),t!=null?yi(e,i,St(t)):l!=null?yi(e,i,St(l)):a!=null&&e.removeAttribute("value"),n==null&&u!=null&&(e.defaultChecked=!!u),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"?e.name=""+St(s):e.removeAttribute("name")}function lf(e,t,l,a,n,u,i,s){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||l!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){mi(e);return}l=l!=null?""+St(l):"",t=t!=null?""+St(t):l,s||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=s?e.checked:!!a,e.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(e.name=i),mi(e)}function yi(e,t,l){t==="number"&&Yn(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function ea(e,t,l,a){if(e=e.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Si=!1;if(Gt)try{var Ya={};Object.defineProperty(Ya,"passive",{get:function(){Si=!0}}),window.addEventListener("test",Ya,Ya),window.removeEventListener("test",Ya,Ya)}catch{Si=!1}var nl=null,_i=null,wn=null;function rf(){if(wn)return wn;var e,t=_i,l=t.length,a,n="value"in nl?nl.value:nl.textContent,u=n.length;for(e=0;e=Xa),vf=" ",gf=!1;function pf(e,t){switch(e){case"keyup":return yh.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function bf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var na=!1;function gh(e,t){switch(e){case"compositionend":return bf(t);case"keypress":return t.which!==32?null:(gf=!0,vf);case"textInput":return e=t.data,e===vf&&gf?null:e;default:return null}}function ph(e,t){if(na)return e==="compositionend"||!Ni&&pf(e,t)?(e=rf(),wn=_i=nl=null,na=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Tf(l)}}function Of(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Of(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Df(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Yn(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=Yn(e.document)}return t}function Oi(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var Nh=Gt&&"documentMode"in document&&11>=document.documentMode,ua=null,Di=null,Ja=null,Mi=!1;function Mf(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Mi||ua==null||ua!==Yn(a)||(a=ua,"selectionStart"in a&&Oi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Ja&&Ka(Ja,a)||(Ja=a,a=qu(Di,"onSelect"),0>=i,n-=i,Ct=1<<32-dt(t)+n|l<te?(ce=w,w=null):ce=w.sibling;var re=S(v,w,p[te],x);if(re===null){w===null&&(w=ce);break}e&&w&&re.alternate===null&&t(v,w),h=u(re,h,te),fe===null?J=re:fe.sibling=re,fe=re,w=ce}if(te===p.length)return l(v,w),se&&Qt(v,te),J;if(w===null){for(;tete?(ce=w,w=null):ce=w.sibling;var Nl=S(v,w,re.value,x);if(Nl===null){w===null&&(w=ce);break}e&&w&&Nl.alternate===null&&t(v,w),h=u(Nl,h,te),fe===null?J=Nl:fe.sibling=Nl,fe=Nl,w=ce}if(re.done)return l(v,w),se&&Qt(v,te),J;if(w===null){for(;!re.done;te++,re=p.next())re=D(v,re.value,x),re!==null&&(h=u(re,h,te),fe===null?J=re:fe.sibling=re,fe=re);return se&&Qt(v,te),J}for(w=a(w);!re.done;te++,re=p.next())re=_(w,v,te,re.value,x),re!==null&&(e&&re.alternate!==null&&w.delete(re.key===null?te:re.key),h=u(re,h,te),fe===null?J=re:fe.sibling=re,fe=re);return e&&w.forEach(function(Ky){return t(v,Ky)}),se&&Qt(v,te),J}function Se(v,h,p,x){if(typeof p=="object"&&p!==null&&p.type===P&&p.key===null&&(p=p.props.children),typeof p=="object"&&p!==null){switch(p.$$typeof){case de:e:{for(var J=p.key;h!==null;){if(h.key===J){if(J=p.type,J===P){if(h.tag===7){l(v,h.sibling),x=n(h,p.props.children),x.return=v,v=x;break e}}else if(h.elementType===J||typeof J=="object"&&J!==null&&J.$$typeof===k&&Gl(J)===h.type){l(v,h.sibling),x=n(h,p.props),Pa(x,p),x.return=v,v=x;break e}l(v,h);break}else t(v,h);h=h.sibling}p.type===P?(x=Rl(p.props.children,v.mode,x,p.key),x.return=v,v=x):(x=In(p.type,p.key,p.props,null,v.mode,x),Pa(x,p),x.return=v,v=x)}return i(v);case V:e:{for(J=p.key;h!==null;){if(h.key===J)if(h.tag===4&&h.stateNode.containerInfo===p.containerInfo&&h.stateNode.implementation===p.implementation){l(v,h.sibling),x=n(h,p.children||[]),x.return=v,v=x;break e}else{l(v,h);break}else t(v,h);h=h.sibling}x=Li(p,v.mode,x),x.return=v,v=x}return i(v);case k:return p=Gl(p),Se(v,h,p,x)}if(Ke(p))return Q(v,h,p,x);if(je(p)){if(J=je(p),typeof J!="function")throw Error(o(150));return p=J.call(p),W(v,h,p,x)}if(typeof p.then=="function")return Se(v,h,uu(p),x);if(p.$$typeof===ge)return Se(v,h,tu(v,p),x);iu(v,p)}return typeof p=="string"&&p!==""||typeof p=="number"||typeof p=="bigint"?(p=""+p,h!==null&&h.tag===6?(l(v,h.sibling),x=n(h,p),x.return=v,v=x):(l(v,h),x=Bi(p,v.mode,x),x.return=v,v=x),i(v)):l(v,h)}return function(v,h,p,x){try{Ia=0;var J=Se(v,h,p,x);return va=null,J}catch(w){if(w===ya||w===au)throw w;var fe=ht(29,w,null,v.mode);return fe.lanes=x,fe.return=v,fe}finally{}}}var Ql=er(!0),tr=er(!1),fl=!1;function Wi(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Fi(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function rl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function ol(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(oe&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=Fn(e),Lf(e,null,l),t}return Wn(e,a,t,l),Fn(e)}function en(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Vs(e,l)}}function Ii(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var i={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=i:u=u.next=i,l=l.next}while(l!==null);u===null?n=u=t:u=u.next=t}else n=u=t;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var Pi=!1;function tn(){if(Pi){var e=ha;if(e!==null)throw e}}function ln(e,t,l,a){Pi=!1;var n=e.updateQueue;fl=!1;var u=n.firstBaseUpdate,i=n.lastBaseUpdate,s=n.shared.pending;if(s!==null){n.shared.pending=null;var m=s,b=m.next;m.next=null,i===null?u=b:i.next=b,i=m;var T=e.alternate;T!==null&&(T=T.updateQueue,s=T.lastBaseUpdate,s!==i&&(s===null?T.firstBaseUpdate=b:s.next=b,T.lastBaseUpdate=m))}if(u!==null){var D=n.baseState;i=0,T=b=m=null,s=u;do{var S=s.lane&-536870913,_=S!==s.lane;if(_?(ie&S)===S:(a&S)===S){S!==0&&S===ma&&(Pi=!0),T!==null&&(T=T.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});e:{var Q=e,W=s;S=t;var Se=l;switch(W.tag){case 1:if(Q=W.payload,typeof Q=="function"){D=Q.call(Se,D,S);break e}D=Q;break e;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=W.payload,S=typeof Q=="function"?Q.call(Se,D,S):Q,S==null)break e;D=B({},D,S);break e;case 2:fl=!0}}S=s.callback,S!==null&&(e.flags|=64,_&&(e.flags|=8192),_=n.callbacks,_===null?n.callbacks=[S]:_.push(S))}else _={lane:S,tag:s.tag,payload:s.payload,callback:s.callback,next:null},T===null?(b=T=_,m=D):T=T.next=_,i|=S;if(s=s.next,s===null){if(s=n.shared.pending,s===null)break;_=s,s=_.next,_.next=null,n.lastBaseUpdate=_,n.shared.pending=null}}while(!0);T===null&&(m=D),n.baseState=m,n.firstBaseUpdate=b,n.lastBaseUpdate=T,u===null&&(n.shared.lanes=0),vl|=i,e.lanes=i,e.memoizedState=D}}function lr(e,t){if(typeof e!="function")throw Error(o(191,e));e.call(t)}function ar(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;eu?u:8;var i=z.T,s={};z.T=s,pc(e,!1,t,l);try{var m=n(),b=z.S;if(b!==null&&b(s,m),m!==null&&typeof m=="object"&&typeof m.then=="function"){var T=qh(m,a);un(e,t,T,bt(e))}else un(e,t,a,bt(e))}catch(D){un(e,t,{then:function(){},status:"rejected",reason:D},bt())}finally{R.p=u,i!==null&&s.types!==null&&(i.types=s.types),z.T=i}}function Qh(){}function vc(e,t,l,a){if(e.tag!==5)throw Error(o(476));var n=qr(e).queue;Rr(e,n,t,U,l===null?Qh:function(){return Hr(e),l(a)})}function qr(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:U,baseState:U,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Vt,lastRenderedState:U},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Vt,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Hr(e){var t=qr(e);t.next===null&&(t=e.alternate.memoizedState),un(e,t.next.queue,{},bt())}function gc(){return We(An)}function Br(){return He().memoizedState}function Lr(){return He().memoizedState}function wh(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=bt();e=rl(l);var a=ol(t,e,l);a!==null&&(ft(a,t,l),en(a,t,l)),t={cache:Ki()},e.payload=t;return}t=t.return}}function Xh(e,t,l){var a=bt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},vu(e)?Yr(t,l):(l=qi(e,t,l,a),l!==null&&(ft(l,e,a),Qr(l,t,a)))}function Gr(e,t,l){var a=bt();un(e,t,l,a)}function un(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(vu(e))Yr(t,n);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var i=t.lastRenderedState,s=u(i,l);if(n.hasEagerState=!0,n.eagerState=s,mt(s,i))return Wn(e,t,n,0),Ee===null&&$n(),!1}catch{}finally{}if(l=qi(e,t,n,a),l!==null)return ft(l,e,a),Qr(l,t,a),!0}return!1}function pc(e,t,l,a){if(a={lane:2,revertLane:Wc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},vu(e)){if(t)throw Error(o(479))}else t=qi(e,l,a,2),t!==null&&ft(t,e,2)}function vu(e){var t=e.alternate;return e===ee||t!==null&&t===ee}function Yr(e,t){pa=fu=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Qr(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Vs(e,l)}}var cn={readContext:We,use:du,useCallback:Ce,useContext:Ce,useEffect:Ce,useImperativeHandle:Ce,useLayoutEffect:Ce,useInsertionEffect:Ce,useMemo:Ce,useReducer:Ce,useRef:Ce,useState:Ce,useDebugValue:Ce,useDeferredValue:Ce,useTransition:Ce,useSyncExternalStore:Ce,useId:Ce,useHostTransitionStatus:Ce,useFormState:Ce,useActionState:Ce,useOptimistic:Ce,useMemoCache:Ce,useCacheRefresh:Ce};cn.useEffectEvent=Ce;var wr={readContext:We,use:du,useCallback:function(e,t){return lt().memoizedState=[e,t===void 0?null:t],e},useContext:We,useEffect:zr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,hu(4194308,4,Or.bind(null,t,e),l)},useLayoutEffect:function(e,t){return hu(4194308,4,e,t)},useInsertionEffect:function(e,t){hu(4,2,e,t)},useMemo:function(e,t){var l=lt();t=t===void 0?null:t;var a=e();if(wl){ll(!0);try{e()}finally{ll(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=lt();if(l!==void 0){var n=l(t);if(wl){ll(!0);try{l(t)}finally{ll(!1)}}}else n=t;return a.memoizedState=a.baseState=n,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},a.queue=e,e=e.dispatch=Xh.bind(null,ee,e),[a.memoizedState,e]},useRef:function(e){var t=lt();return e={current:e},t.memoizedState=e},useState:function(e){e=oc(e);var t=e.queue,l=Gr.bind(null,ee,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:hc,useDeferredValue:function(e,t){var l=lt();return yc(l,e,t)},useTransition:function(){var e=oc(!1);return e=Rr.bind(null,ee,e.queue,!0,!1),lt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=ee,n=lt();if(se){if(l===void 0)throw Error(o(407));l=l()}else{if(l=t(),Ee===null)throw Error(o(349));(ie&127)!==0||fr(a,t,l)}n.memoizedState=l;var u={value:l,getSnapshot:t};return n.queue=u,zr(or.bind(null,a,u,e),[e]),a.flags|=2048,Sa(9,{destroy:void 0},rr.bind(null,a,u,l,t),null),l},useId:function(){var e=lt(),t=Ee.identifierPrefix;if(se){var l=Rt,a=Ct;l=(a&~(1<<32-dt(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=ru++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?i.createElement(n,{is:a.is}):i.createElement(n)}}u[ke]=t,u[at]=a;e:for(i=t.child;i!==null;){if(i.tag===5||i.tag===6)u.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===t)break e;for(;i.sibling===null;){if(i.return===null||i.return===t)break e;i=i.return}i.sibling.return=i.return,i=i.sibling}t.stateNode=u;e:switch(Ie(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&Jt(t)}}return xe(t),Uc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&Jt(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(o(166));if(e=X.current,oa(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=$e,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[ke]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||sd(e.nodeValue,l)),e||cl(t,!0)}else e=Hu(e).createTextNode(a),e[ke]=t,t.stateNode=e}return xe(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=oa(t),l!==null){if(e===null){if(!a)throw Error(o(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(o(557));e[ke]=t}else ql(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;xe(t),e=!1}else l=wi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(vt(t),t):(vt(t),null);if((t.flags&128)!==0)throw Error(o(558))}return xe(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=oa(t),a!==null&&a.dehydrated!==null){if(e===null){if(!n)throw Error(o(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(o(317));n[ke]=t}else ql(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;xe(t),n=!1}else n=wi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(vt(t),t):(vt(t),null)}return vt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),_u(t,t.updateQueue),xe(t),null);case 4:return _e(),e===null&&es(t.stateNode.containerInfo),xe(t),null;case 10:return Xt(t.type),xe(t),null;case 19:if(y(qe),a=t.memoizedState,a===null)return xe(t),null;if(n=(t.flags&128)!==0,u=a.rendering,u===null)if(n)fn(a,!1);else{if(Re!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=su(e),u!==null){for(t.flags|=128,fn(a,!1),e=u.updateQueue,t.updateQueue=e,_u(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Gf(l,e),l=l.sibling;return j(qe,qe.current&1|2),se&&Qt(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&rt()>Nu&&(t.flags|=128,n=!0,fn(a,!1),t.lanes=4194304)}else{if(!n)if(e=su(u),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,_u(t,e),fn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!se)return xe(t),null}else 2*rt()-a.renderingStartTime>Nu&&l!==536870912&&(t.flags|=128,n=!0,fn(a,!1),t.lanes=4194304);a.isBackwards?(u.sibling=t.child,t.child=u):(e=a.last,e!==null?e.sibling=u:t.child=u,a.last=u)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=rt(),e.sibling=null,l=qe.current,j(qe,n?l&1|2:l&1),se&&Qt(t,a.treeForkCount),e):(xe(t),null);case 22:case 23:return vt(t),tc(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(xe(t),t.subtreeFlags&6&&(t.flags|=8192)):xe(t),l=t.updateQueue,l!==null&&_u(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&y(Ll),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),Xt(Be),xe(t),null;case 25:return null;case 30:return null}throw Error(o(156,t.tag))}function kh(e,t){switch(Yi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Xt(Be),_e(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return tl(t),null;case 31:if(t.memoizedState!==null){if(vt(t),t.alternate===null)throw Error(o(340));ql()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(vt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(o(340));ql()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return y(qe),null;case 4:return _e(),null;case 10:return Xt(t.type),null;case 22:case 23:return vt(t),tc(),e!==null&&y(Ll),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Xt(Be),null;case 25:return null;default:return null}}function mo(e,t){switch(Yi(t),t.tag){case 3:Xt(Be),_e();break;case 26:case 27:case 5:tl(t);break;case 4:_e();break;case 31:t.memoizedState!==null&&vt(t);break;case 13:vt(t);break;case 19:y(qe);break;case 10:Xt(t.type);break;case 22:case 23:vt(t),tc(),e!==null&&y(Ll);break;case 24:Xt(Be)}}function rn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&e)===e){a=void 0;var u=l.create,i=l.inst;a=u(),i.destroy=a}l=l.next}while(l!==n)}}catch(s){ve(t,t.return,s)}}function hl(e,t,l){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&e)===e){var i=a.inst,s=i.destroy;if(s!==void 0){i.destroy=void 0,n=t;var m=l,b=s;try{b()}catch(T){ve(n,m,T)}}}a=a.next}while(a!==u)}}catch(T){ve(t,t.return,T)}}function ho(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{ar(t,l)}catch(a){ve(e,e.return,a)}}}function yo(e,t,l){l.props=Xl(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){ve(e,t,a)}}function on(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(n){ve(e,t,n)}}function qt(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){ve(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){ve(e,t,n)}else l.current=null}function vo(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){ve(e,e.return,n)}}function Cc(e,t,l){try{var a=e.stateNode;vy(a,e.type,l,t),a[at]=t}catch(n){ve(e,e.return,n)}}function go(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&_l(e.type)||e.tag===4}function Rc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||go(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&_l(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function qc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=Lt));else if(a!==4&&(a===27&&_l(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(qc(e,t,l),e=e.sibling;e!==null;)qc(e,t,l),e=e.sibling}function Eu(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&_l(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Eu(e,t,l),e=e.sibling;e!==null;)Eu(e,t,l),e=e.sibling}function po(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);Ie(t,a,l),t[ke]=e,t[at]=l}catch(u){ve(e,e.return,u)}}var kt=!1,Ye=!1,Hc=!1,bo=typeof WeakSet=="function"?WeakSet:Set,Ze=null;function $h(e,t){if(e=e.containerInfo,as=Xu,e=Df(e),Oi(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,u=a.focusNode;a=a.focusOffset;try{l.nodeType,u.nodeType}catch{l=null;break e}var i=0,s=-1,m=-1,b=0,T=0,D=e,S=null;t:for(;;){for(var _;D!==l||n!==0&&D.nodeType!==3||(s=i+n),D!==u||a!==0&&D.nodeType!==3||(m=i+a),D.nodeType===3&&(i+=D.nodeValue.length),(_=D.firstChild)!==null;)S=D,D=_;for(;;){if(D===e)break t;if(S===l&&++b===n&&(s=i),S===u&&++T===a&&(m=i),(_=D.nextSibling)!==null)break;D=S,S=D.parentNode}D=_}l=s===-1||m===-1?null:{start:s,end:m}}else l=null}l=l||{start:0,end:0}}else l=null;for(ns={focusedElem:e,selectionRange:l},Xu=!1,Ze=t;Ze!==null;)if(t=Ze,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Ze=e;else for(;Ze!==null;){switch(t=Ze,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),Ie(u,a,l),u[ke]=e,Xe(u),a=u;break e;case"link":var i=zd("link","href",n).get(a+(l.href||""));if(i){for(var s=0;sSe&&(i=Se,Se=W,W=i);var v=xf(s,W),h=xf(s,Se);if(v&&h&&(_.rangeCount!==1||_.anchorNode!==v.node||_.anchorOffset!==v.offset||_.focusNode!==h.node||_.focusOffset!==h.offset)){var p=D.createRange();p.setStart(v.node,v.offset),_.removeAllRanges(),W>Se?(_.addRange(p),_.extend(h.node,h.offset)):(p.setEnd(h.node,h.offset),_.addRange(p))}}}}for(D=[],_=s;_=_.parentNode;)_.nodeType===1&&D.push({element:_,left:_.scrollLeft,top:_.scrollTop});for(typeof s.focus=="function"&&s.focus(),s=0;sl?32:l,z.T=null,l=Xc,Xc=null;var u=pl,i=Pt;if(Qe=0,za=pl=null,Pt=0,(oe&6)!==0)throw Error(o(331));var s=oe;if(oe|=4,Do(u.current),To(u,u.current,i,l),oe=s,gn(0,!1),ot&&typeof ot.onPostCommitFiberRoot=="function")try{ot.onPostCommitFiberRoot(Ra,u)}catch{}return!0}finally{R.p=n,z.T=a,ko(e,t)}}function Wo(e,t,l){t=At(l,t),t=Ec(e.stateNode,t,2),e=ol(e,t,2),e!==null&&(Ha(e,2),Ht(e))}function ve(e,t,l){if(e.tag===3)Wo(e,e,l);else for(;t!==null;){if(t.tag===3){Wo(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(gl===null||!gl.has(a))){e=At(l,e),l=Wr(2),a=ol(t,l,2),a!==null&&(Fr(l,a,t,e),Ha(a,2),Ht(a));break}}t=t.return}}function Jc(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Ih;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(l)||(Gc=!0,n.add(l),e=ay.bind(null,e,t,l),t.then(e,e))}function ay(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,Ee===e&&(ie&l)===l&&(Re===4||Re===3&&(ie&62914560)===ie&&300>rt()-zu?(oe&2)===0&&Na(e,0):Yc|=l,ja===ie&&(ja=0)),Ht(e)}function Fo(e,t){t===0&&(t=Xs()),e=Cl(e,t),e!==null&&(Ha(e,t),Ht(e))}function ny(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),Fo(e,l)}function uy(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,n=e.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(o(314))}a!==null&&a.delete(t),Fo(e,l)}function iy(e,t){return ii(e,t)}var Uu=null,xa=null,kc=!1,Cu=!1,$c=!1,Sl=0;function Ht(e){e!==xa&&e.next===null&&(xa===null?Uu=xa=e:xa=xa.next=e),Cu=!0,kc||(kc=!0,sy())}function gn(e,t){if(!$c&&Cu){$c=!0;do for(var l=!1,a=Uu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var i=a.suspendedLanes,s=a.pingedLanes;u=(1<<31-dt(42|e)+1)-1,u&=n&~(i&~s),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,td(a,u))}else u=ie,u=Bn(a,a===Ee?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||qa(a,u)||(l=!0,td(a,u));a=a.next}while(l);$c=!1}}function cy(){Io()}function Io(){Cu=kc=!1;var e=0;Sl!==0&&py()&&(e=Sl);for(var t=rt(),l=null,a=Uu;a!==null;){var n=a.next,u=Po(a,t);u===0?(a.next=null,l===null?Uu=n:l.next=n,n===null&&(xa=l)):(l=a,(e!==0||(u&3)!==0)&&(Cu=!0)),a=n}Qe!==0&&Qe!==5||gn(e),Sl!==0&&(Sl=0)}function Po(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,u=e.pendingLanes&-62914561;0s)break;var T=m.transferSize,D=m.initiatorType;T&&fd(D)&&(m=m.responseEnd,i+=T*(m"u"?null:document;function _d(e,t,l){var a=Oa;if(a&&typeof t=="string"&&t){var n=_t(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),Sd.has(n)||(Sd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),Ie(t,"link",e),Xe(t),a.head.appendChild(t)))}}function Ty(e){el.D(e),_d("dns-prefetch",e,null)}function xy(e,t){el.C(e,t),_d("preconnect",e,t)}function Oy(e,t,l){el.L(e,t,l);var a=Oa;if(a&&e&&t){var n='link[rel="preload"][as="'+_t(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+_t(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+_t(l.imageSizes)+'"]')):n+='[href="'+_t(e)+'"]';var u=n;switch(t){case"style":u=Da(e);break;case"script":u=Ma(e)}Ot.has(u)||(e=B({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),Ot.set(u,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(_n(u))||t==="script"&&a.querySelector(En(u))||(t=a.createElement("link"),Ie(t,"link",e),Xe(t),a.head.appendChild(t)))}}function Dy(e,t){el.m(e,t);var l=Oa;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+_t(a)+'"][href="'+_t(e)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ma(e)}if(!Ot.has(u)&&(e=B({rel:"modulepreload",href:e},t),Ot.set(u,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(En(u)))return}a=l.createElement("link"),Ie(a,"link",e),Xe(a),l.head.appendChild(a)}}}function My(e,t,l){el.S(e,t,l);var a=Oa;if(a&&e){var n=Il(a).hoistableStyles,u=Da(e);t=t||"default";var i=n.get(u);if(!i){var s={loading:0,preload:null};if(i=a.querySelector(_n(u)))s.loading=5;else{e=B({rel:"stylesheet",href:e,"data-precedence":t},l),(l=Ot.get(u))&&os(e,l);var m=i=a.createElement("link");Xe(m),Ie(m,"link",e),m._p=new Promise(function(b,T){m.onload=b,m.onerror=T}),m.addEventListener("load",function(){s.loading|=1}),m.addEventListener("error",function(){s.loading|=2}),s.loading|=4,Lu(i,t,a)}i={type:"stylesheet",instance:i,count:1,state:s},n.set(u,i)}}}function Uy(e,t){el.X(e,t);var l=Oa;if(l&&e){var a=Il(l).hoistableScripts,n=Ma(e),u=a.get(n);u||(u=l.querySelector(En(n)),u||(e=B({src:e,async:!0},t),(t=Ot.get(n))&&ds(e,t),u=l.createElement("script"),Xe(u),Ie(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Cy(e,t){el.M(e,t);var l=Oa;if(l&&e){var a=Il(l).hoistableScripts,n=Ma(e),u=a.get(n);u||(u=l.querySelector(En(n)),u||(e=B({src:e,async:!0,type:"module"},t),(t=Ot.get(n))&&ds(e,t),u=l.createElement("script"),Xe(u),Ie(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Ed(e,t,l,a){var n=(n=X.current)?Bu(n):null;if(!n)throw Error(o(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=Da(l.href),l=Il(n).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=Da(l.href);var u=Il(n).hoistableStyles,i=u.get(e);if(i||(n=n.ownerDocument||n,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,i),(u=n.querySelector(_n(e)))&&!u._p&&(i.instance=u,i.state.loading=5),Ot.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Ot.set(e,l),u||Ry(n,e,l,i.state))),t&&a===null)throw Error(o(528,""));return i}if(t&&a!==null)throw Error(o(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ma(l),l=Il(n).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,e))}}function Da(e){return'href="'+_t(e)+'"'}function _n(e){return'link[rel="stylesheet"]['+e+"]"}function Ad(e){return B({},e,{"data-precedence":e.precedence,precedence:null})}function Ry(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Ie(t,"link",l),Xe(t),e.head.appendChild(t))}function Ma(e){return'[src="'+_t(e)+'"]'}function En(e){return"script[async]"+e}function jd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+_t(l.href)+'"]');if(a)return t.instance=a,Xe(a),a;var n=B({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),Xe(a),Ie(a,"style",n),Lu(a,l.precedence,e),t.instance=a;case"stylesheet":n=Da(l.href);var u=e.querySelector(_n(n));if(u)return t.state.loading|=4,t.instance=u,Xe(u),u;a=Ad(l),(n=Ot.get(n))&&os(a,n),u=(e.ownerDocument||e).createElement("link"),Xe(u);var i=u;return i._p=new Promise(function(s,m){i.onload=s,i.onerror=m}),Ie(u,"link",a),t.state.loading|=4,Lu(u,l.precedence,e),t.instance=u;case"script":return u=Ma(l.src),(n=e.querySelector(En(u)))?(t.instance=n,Xe(n),n):(a=l,(n=Ot.get(u))&&(a=B({},l),ds(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),Xe(n),Ie(n,"link",a),e.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(o(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Lu(a,l.precedence,e));return t.instance}function Lu(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,i=0;i title"):null)}function qy(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return e=t.disabled,typeof t.precedence=="string"&&e==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Td(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function Hy(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=Da(a.href),u=t.querySelector(_n(n));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Yu.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=u,Xe(u);return}u=t.ownerDocument||t,a=Ad(a),(n=Ot.get(n))&&os(a,n),u=u.createElement("link"),Xe(u);var i=u;i._p=new Promise(function(s,m){i.onload=s,i.onerror=m}),Ie(u,"link",a),l.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=Yu.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var ms=0;function By(e,t){return e.stylesheets&&e.count===0&&wu(e,e.stylesheets),0ms?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Yu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)wu(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Qu=null;function wu(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Qu=new Map,t.forEach(Ly,e),Qu=null,Yu.call(e))}function Ly(e,t){if(!(t.state.loading&4)){var l=Qu.get(e);if(l)var a=l.get(null);else{l=new Map,Qu.set(e,l);for(var n=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(d){console.error(d)}}return f(),Es.exports=ev(),Es.exports}var lv=tv();/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const im=(...f)=>f.filter((d,g,o)=>!!d&&d.trim()!==""&&o.indexOf(d)===g).join(" ").trim();/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const av=f=>f.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const nv=f=>f.replace(/^([A-Z])|[\s-_]+(\w)/g,(d,g,o)=>o?o.toUpperCase():g.toLowerCase());/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Fd=f=>{const d=nv(f);return d.charAt(0).toUpperCase()+d.slice(1)};/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */var uv={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const iv=f=>{for(const d in f)if(d.startsWith("aria-")||d==="role"||d==="title")return!0;return!1};/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const cv=H.forwardRef(({color:f="currentColor",size:d=24,strokeWidth:g=2,absoluteStrokeWidth:o,className:O="",children:A,iconNode:C,...Z},q)=>H.createElement("svg",{ref:q,...uv,width:d,height:d,stroke:f,strokeWidth:o?Number(g)*24/Number(d):g,className:im("lucide",O),...!A&&!iv(Z)&&{"aria-hidden":"true"},...Z},[...C.map(([E,Y])=>H.createElement(E,Y)),...Array.isArray(A)?A:[A]]));/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ve=(f,d)=>{const g=H.forwardRef(({className:o,...O},A)=>H.createElement(cv,{ref:A,iconNode:d,className:im(`lucide-${av(Fd(f))}`,`lucide-${f}`,o),...O}));return g.displayName=Fd(f),g};/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const sv=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],fv=Ve("arrow-left",sv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const rv=[["path",{d:"M7 7h10v10",key:"1tivn9"}],["path",{d:"M7 17 17 7",key:"1vkiza"}]],Un=Ve("arrow-up-right",rv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const ov=[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]],dv=Ve("chevron-left",ov);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const mv=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],cm=Ve("chevron-right",mv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const hv=[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"r6nss1"}]],sm=Ve("house",hv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const yv=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],vv=Ve("image",yv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const gv=[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2",key:"8i5ue5"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2",key:"1b9ql8"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12",key:"1jonct"}]],fm=Ve("link-2",gv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const pv=[["circle",{cx:"12",cy:"16",r:"1",key:"1au0dj"}],["rect",{x:"3",y:"10",width:"18",height:"12",rx:"2",key:"6s8ecr"}],["path",{d:"M7 10V7a5 5 0 0 1 10 0v3",key:"1pqi11"}]],bv=Ve("lock-keyhole",pv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Sv=[["path",{d:"m16 17 5-5-5-5",key:"1bji2h"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}]],rm=Ve("log-out",Sv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const _v=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],Id=Ve("plus",_v);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ev=[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]],Av=Ve("save",Ev);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const jv=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],Ds=Ve("search",jv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const zv=[["path",{d:"M10 5H3",key:"1qgfaw"}],["path",{d:"M12 19H3",key:"yhmn1j"}],["path",{d:"M14 3v4",key:"1sua03"}],["path",{d:"M16 17v4",key:"1q0r14"}],["path",{d:"M21 12h-9",key:"1o4lsq"}],["path",{d:"M21 19h-5",key:"1rlt1p"}],["path",{d:"M21 5h-7",key:"1oszz2"}],["path",{d:"M8 10v4",key:"tgpxqk"}],["path",{d:"M8 12H3",key:"a7s4jb"}]],om=Ve("sliders-horizontal",zv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Nv=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],Tv=Ve("sparkles",Nv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const xv=[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]],Hs=Ve("star",xv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Ov=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],Iu=Ve("trash-2",Ov);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Dv=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],Mv=Ve("upload",Dv);/** + * @license lucide-react v0.575.0 - ISC + * + * This source code is licensed under the ISC license. + * See the LICENSE file in the root directory of this source tree. + */const Uv=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],kl=Ve("x",Uv),Cv="2026-07-16T12:00:00.000Z",dm=["Administración","Recursos Humanos","CDC"],Rv=[];function qv(){return{schemaVersion:1,apps:Rv.map(f=>({...f,keywords:[...f.keywords]})),favoritesByUser:{},recentByUser:{},updatedAt:Cv}}const On="glm-hub:state:v1";function Hv(f){if(!f||typeof f!="object")return!1;const d=f;return typeof d.id=="string"&&typeof d.name=="string"&&typeof d.description=="string"&&typeof d.category=="string"&&Array.isArray(d.keywords)&&typeof d.url=="string"&&typeof d.mark=="string"&&typeof d.accent=="string"&&typeof d.iconDataUrl=="string"&&(d.visibility==="published"||d.visibility==="hidden")}function Bv(f){if(!f||typeof f!="object")return!1;const d=f;return d.schemaVersion===1&&Array.isArray(d.apps)&&d.apps.every(Hv)&&!!d.favoritesByUser&&typeof d.favoritesByUser=="object"&&!!d.recentByUser&&typeof d.recentByUser=="object"}function Pd(f,d){return Object.fromEntries(Object.entries(f).map(([g,o])=>[g,o.filter(O=>d.has(O))]))}function Lv(f){switch(f){case"Administración":case"Recursos Humanos":case"CDC":return f;case"Recursos":return"Recursos Humanos";case"Clientes":case"Creatividad":return"CDC";case"Operaciones":case"Analítica":default:return"Administración"}}function Gv(f){let d=!1;const g=f.apps.map(o=>{const O=Lv(o.category);return O===o.category?o:(d=!0,{...o,category:O})});return d?{...f,apps:g,updatedAt:new Date().toISOString()}:f}function Yv(f){const d=f.apps.filter(o=>!!o.iconDataUrl.trim());if(d.length===f.apps.length)return f;const g=new Set(d.map(o=>o.id));return{...f,apps:d,favoritesByUser:Pd(f.favoritesByUser,g),recentByUser:Pd(f.recentByUser,g),updatedAt:new Date().toISOString()}}function Qv(){const f=qv();try{const d=localStorage.getItem(On);if(!d)return localStorage.setItem(On,JSON.stringify(f)),{data:f,warning:""};const g=JSON.parse(d);if(!Bv(g))return localStorage.setItem(`${On}:backup`,d),localStorage.setItem(On,JSON.stringify(f)),{data:f,warning:"Los datos locales no eran válidos. Restauramos el catálogo inicial."};const o=Gv(g),O=Yv(o);return O!==g&&localStorage.setItem(On,JSON.stringify(O)),{data:O,warning:""}}catch{return{data:f,warning:"No pudimos leer los datos guardados. Estás viendo el catálogo inicial."}}}function Ca(f){return f.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toLocaleLowerCase("es-DO").trim()}function Jl(f){if(!f.trim())return null;try{const d=new URL(f.trim()),g=d.protocol==="http:"&&(d.hostname==="localhost"||d.hostname==="127.0.0.1");return d.protocol!=="https:"&&!g||d.username||d.password?null:d.toString()}catch{return null}}const mm="https://dbit.digitalcompass.agency".trim(),hm="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE".trim(),ym=globalThis.supabase;if(!mm||!hm)throw new Error("Faltan VITE_SUPABASE_URL o VITE_SUPABASE_ANON_KEY en el archivo .env.");if(!ym)throw new Error("No se pudo cargar la librería de Supabase.");const Ue=ym.createClient(mm,hm,{auth:{autoRefreshToken:!0,persistSession:!0,detectSessionInUrl:!0,flowType:"pkce"}}),Mn="glm_hub_apps",Ms="glm_hub_favorites",vm="glm_hub_recent_apps",Pu="glm-hub-icons",em="glm-hub:supabase-catalog-migrated:v1";function gm(f){return{id:f.id,name:f.name,description:f.description,category:f.category,keywords:[],url:f.url??"",mark:"",accent:"#4F758B",iconDataUrl:f.icon_url,visibility:f.visibility,createdAt:f.created_at,updatedAt:f.updated_at}}function wv(f){const d=/^data:(image\/(?:png|jpeg|webp));base64,([a-zA-Z0-9+/=]+)$/.exec(f);if(!d)throw new Error("El ícono no tiene un formato válido.");const g=d[1],o=atob(d[2]),O=new Uint8Array(o.length);for(let A=0;A[o.app_id,o.has_access===!0]))}async function Bs(){const{data:f,error:d}=await Ue.from(Mn).select("id,name,description,category,url,icon_url,visibility,created_at,updated_at").order("name",{ascending:!0});if(d)throw new Error(`No se pudo cargar el catálogo compartido: ${d.message}`);return(f??[]).map(gm)}async function Kv(f){const{data:d,error:g}=await Ue.from(Ms).select("app_id,created_at").eq("user_id",f).order("created_at",{ascending:!1});if(g)throw new Error(`No se pudieron cargar los favoritos: ${g.message}`);return(d??[]).map(o=>o.app_id)}async function Jv(f){const{data:d,error:g}=await Ue.from(vm).select("app_id,last_opened_at").eq("user_id",f).order("last_opened_at",{ascending:!1}).limit(30);if(g)throw new Error(`No se pudieron cargar los accesos recientes: ${g.message}`);return(d??[]).map(o=>o.app_id)}async function kv(f){const[d,g,o]=await Promise.all([Bs(),Kv(f),Jv(f)]);return{schemaVersion:1,apps:d,favoritesByUser:{[f]:g},recentByUser:{[f]:o},updatedAt:new Date().toISOString()}}async function pm(f,d,g){const o=(d==null?void 0:d.id)??crypto.randomUUID(),O=await Zv(o,f.iconDataUrl),A={name:f.name,description:f.description,category:f.category,url:f.url||null,icon_url:O,visibility:f.visibility,updated_by:g};let C;if(d?C=await Ue.from(Mn).update(A).eq("id",o).select("id,name,description,category,url,icon_url,visibility,created_at,updated_at").single():C=await Ue.from(Mn).insert({id:o,...A,created_by:g}).select("id,name,description,category,url,icon_url,visibility,created_at,updated_at").single(),C.error)throw O!==f.iconDataUrl&&await Us(O),new Error(`No se pudo guardar la aplicación: ${C.error.message}`);return d&&d.iconDataUrl!==O&&await Us(d.iconDataUrl),gm(C.data)}async function $v(f){const{error:d}=await Ue.from(Mn).delete().eq("id",f.id);if(d)throw new Error(`No se pudo eliminar la aplicación: ${d.message}`);await Us(f.iconDataUrl)}async function Wv(f,d,g){if(g){const{error:O}=await Ue.from(Ms).upsert({user_id:f,app_id:d},{onConflict:"user_id,app_id"});if(O)throw new Error(`No se pudo guardar el favorito: ${O.message}`);return}const{error:o}=await Ue.from(Ms).delete().eq("user_id",f).eq("app_id",d);if(o)throw new Error(`No se pudo quitar el favorito: ${o.message}`)}async function Fv(f,d){const{error:g}=await Ue.from(vm).upsert({user_id:f,app_id:d,last_opened_at:new Date().toISOString()},{onConflict:"user_id,app_id"});if(g)throw new Error(`No se pudo registrar el acceso reciente: ${g.message}`)}async function Iv(f,d){if(f.role!=="admin"||d.length===0||localStorage.getItem(em)==="completed")return 0;const g=await Bs(),o=new Set(g.map(C=>C.name.trim().toLocaleLowerCase("es-DO"))),O=d.filter(C=>{const Z=C.name.trim().toLocaleLowerCase("es-DO");return!!C.iconDataUrl.trim()&&!o.has(Z)});let A=0;for(const C of O)await pm({name:C.name,description:C.description,category:C.category,url:C.url,iconDataUrl:C.iconDataUrl,visibility:C.visibility},null,f.id),o.add(C.name.trim().toLocaleLowerCase("es-DO")),A+=1;return localStorage.setItem(em,"completed"),A}function Pv(f){const d=Ue.channel("glm-hub-apps-shared").on("postgres_changes",{event:"*",schema:"public",table:Mn},()=>f()).subscribe();return()=>{Ue.removeChannel(d)}}const Cs=new Intl.Collator("es-DO",{sensitivity:"base"}),e0="@gomezleemarketing.com",tm="https://agenteit.digitalcompass.agency/webhook/glm-hub-generar-icono".trim()??"",lm="https://agenteit.digitalcompass.agency/webhook/glm-hub-solicitar-acceso".trim()??"";function Ns(f=""){return`/${f}`}function t0(){return new URL("/",window.location.origin).toString()}function l0(f,d){var C,Z;const g=f.user.user_metadata??{},o=g.full_name??g.name,A=(((C=f.user.email)==null?void 0:C.trim().toLocaleLowerCase("en-US"))??"").split("@")[0]||"Usuario GLM";return((Z=d==null?void 0:d.full_name)==null?void 0:Z.trim())||(typeof o=="string"?o.trim():"")||A}function a0(f){const d=f.user.user_metadata??{},g=d.avatar_url??d.picture;if(typeof g!="string"||!g.trim())return"";try{const o=new URL(g.trim());return o.protocol==="https:"?o.toString():""}catch{return""}}async function n0(f){var C;const d=((C=f.user.email)==null?void 0:C.trim().toLocaleLowerCase("en-US"))??"";if(!d.endsWith(e0))return{session:null,error:"Debes continuar con una cuenta corporativa @gomezleemarketing.com."};const{data:g,error:o}=await Ue.from("glm_hub_authorized_users").select("email, full_name, role, is_active").eq("email",d).limit(1),A=(g??[])[0]??null;return o?(console.error("No se pudo validar el perfil de acceso:",o),{session:null,error:"No pudimos completar el inicio de sesión. Intenta nuevamente."}):A&&!A.is_active?{session:null,error:"Tu acceso al GLM Hub está deshabilitado. Contacta a IT Support."}:{session:{user:{id:f.user.id,name:l0(f,A),email:d,role:(A==null?void 0:A.role)==="admin"?"admin":"member",avatarUrl:a0(f)},expiresAt:(f.expires_at??Math.floor(Date.now()/1e3)+3600)*1e3},error:""}}function bm(f){const d=f.trim().split(/\s+/).filter(Boolean);if(d.length===0)return"GL";if(d.length===1)return d[0].slice(0,2).toLocaleUpperCase("es-DO");const g=d.length>=4?d.length-2:d.length-1;return`${d[0][0]}${d[g][0]}`.toLocaleUpperCase("es-DO")}function u0(){const f=new Date().getHours();return f<12?"Buenos días":f<19?"Buenas tardes":"Buenas noches"}function am(f){return f&&f[0].toLocaleUpperCase("es-DO")+f.slice(1)}function nm(f){const d=new Intl.DateTimeFormat("es-DO",{weekday:"long",day:"numeric",month:"long",year:"numeric"}).formatToParts(f),g=o=>{var O;return((O=d.find(A=>A.type===o))==null?void 0:O.value)??""};return`${am(g("weekday"))} ${g("day")} de ${am(g("month"))} de ${g("year")}`}function i0(){const[f,d]=H.useState(()=>nm(new Date));return H.useEffect(()=>{const g=()=>d(nm(new Date));g();const o=window.setInterval(g,6e4);return()=>window.clearInterval(o)},[]),f}function Wu(){return{name:"",description:"",category:"Administración",url:"",iconDataUrl:"",visibility:"published"}}function Dn(f){return{name:f.name,description:f.description,category:f.category,url:f.url,iconDataUrl:f.iconDataUrl,visibility:f.visibility}}async function Sm(f,d=!0){if(!new Set(["image/png","image/jpeg","image/webp"]).has(f.type))throw new Error("Usa un ícono en formato PNG, JPG o WebP.");if(d&&f.size>1024*1024)throw new Error("El ícono debe pesar menos de 1 MB.");const o=await createImageBitmap(f);if(o.width>4096||o.height>4096)throw o.close(),new Error("El ícono no puede superar 4096 × 4096 px.");const O=document.createElement("canvas");O.width=192,O.height=192;const A=O.getContext("2d");if(!A)throw o.close(),new Error("Este navegador no pudo procesar el ícono.");const C=Math.min(192/o.width,192/o.height),Z=o.width*C,q=o.height*C,E=(192-Z)/2,Y=(192-q)/2;return A.clearRect(0,0,192,192),A.drawImage(o,E,Y,Z,q),o.close(),O.toDataURL("image/webp",.9)}async function c0(f){if(!f.startsWith("data:image/"))throw new Error("La IA no devolvió una imagen válida.");const g=await(await fetch(f)).blob();return _m(g)}async function _m(f){const d=f.type||"image/png";if(!d.startsWith("image/"))throw new Error("El flujo de IA no devolvió un archivo de imagen.");const g=d==="image/jpeg"?"jpg":d.split("/")[1]||"png",o=new File([f],`icono-generado.${g}`,{type:d});return Sm(o,!1)}function ei({compact:f=!1}){return c.jsx("img",{className:f?"brand-logo brand-logo--compact":"brand-logo",src:"/glm-logo.png",alt:"GomezLee Marketing",width:"350",height:"109"})}function ti({app:f,size:d="regular",showPlaceholder:g=!1}){const[o,O]=H.useState(!1),A=!!f.iconDataUrl&&!o;return c.jsx("span",{className:`app-mark app-mark--${d}`,"aria-hidden":"true",children:A?c.jsx("img",{src:f.iconDataUrl,alt:"",onError:()=>O(!0)}):g?c.jsx(vv,{className:"app-mark__placeholder",size:36,strokeWidth:1.5}):null})}function Em({user:f,label:d}){const[g,o]=H.useState(!1),O=!!f.avatarUrl&&!g;return c.jsx("span",{className:"avatar","aria-label":d,"aria-hidden":d?void 0:!0,children:O?c.jsx("img",{src:f.avatarUrl,alt:"",referrerPolicy:"no-referrer",onError:()=>o(!0)}):bm(f.name)})}function Ts({messages:f,onDismiss:d}){return c.jsx("div",{className:"toast-stack","aria-live":"polite","aria-relevant":"additions",children:f.map(g=>c.jsxs("div",{className:`toast toast--${g.kind}`,children:[c.jsx("span",{className:"toast__signal","aria-hidden":"true"}),c.jsxs("div",{children:[c.jsx("strong",{children:g.title}),g.detail?c.jsx("p",{children:g.detail}):null]}),c.jsx("button",{type:"button",className:"icon-button icon-button--quiet","aria-label":"Cerrar mensaje",onClick:()=>d(g.id),children:c.jsx(kl,{size:18,"aria-hidden":"true"})})]},g.id))})}function s0({onLogin:f,error:d,disabled:g=!1}){const[o,O]=H.useState(!1),A=async()=>{O(!0),await f(),O(!1)};return c.jsxs("main",{className:"login-shell",children:[c.jsxs("section",{className:"login-story","aria-labelledby":"login-headline",children:[c.jsx("div",{className:"login-story__topline",children:c.jsx(ei,{})}),c.jsxs("div",{className:"login-story__content",children:[c.jsx("p",{className:"eyebrow",children:"ACCESO INTERNO"}),c.jsxs("h1",{id:"login-headline",children:["Todo el trabajo",c.jsx("span",{children:"de GLM, a un clic."})]}),c.jsx("p",{className:"login-story__lede",children:"Tu punto de partida para abrir herramientas, encontrar recursos y mantener el día en movimiento."})]}),c.jsx("div",{className:"login-story__type","aria-hidden":"true",children:"GLM"})]}),c.jsx("section",{className:"login-panel","aria-label":"Inicio de sesión",children:c.jsxs("div",{className:"login-panel__inner",children:[c.jsxs("div",{className:"login-panel__heading",children:[c.jsx("p",{className:"section-kicker",children:"GLM HUB"}),c.jsx("h2",{children:"Entra a tu espacio."})]}),c.jsxs("div",{className:"login-form",children:[d?c.jsx("p",{className:"form-error",id:"login-error",role:"alert",children:d}):null,c.jsxs("button",{className:"primary-button primary-button--full",type:"button",disabled:g||o,onClick:()=>void A(),children:[c.jsx(bv,{size:18,"aria-hidden":"true"}),o?"Conectando…":"Continuar con Google",o?null:c.jsx(Un,{size:18,"aria-hidden":"true"})]})]})]})})]})}function f0({user:f,view:d,onNavigate:g,onLogout:o}){return c.jsxs("aside",{className:"sidebar",children:[c.jsx("div",{className:"sidebar__brand",children:c.jsx(ei,{compact:!0})}),c.jsxs("nav",{className:"sidebar__nav","aria-label":"Navegación principal",children:[c.jsxs("button",{type:"button",className:d==="hub"?"is-active":"",onClick:()=>g("hub"),"aria-current":d==="hub"?"page":void 0,children:[c.jsx(sm,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Aplicaciones"})]}),f.role==="admin"?c.jsxs("button",{type:"button",className:d==="admin"?"is-active":"",onClick:()=>g("admin"),"aria-current":d==="admin"?"page":void 0,children:[c.jsx(om,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Administrar"})]}):null]}),c.jsxs("div",{className:"sidebar__account",children:[c.jsx(Em,{user:f}),c.jsxs("span",{className:"sidebar__account-copy",children:[c.jsx("strong",{children:f.name}),c.jsx("small",{children:f.role==="admin"?"Administrador":"Usuario"})]}),c.jsx("button",{type:"button",className:"icon-button","aria-label":"Cerrar sesión",onClick:o,children:c.jsx(rm,{size:18,"aria-hidden":"true"})})]})]})}function r0({user:f}){return c.jsxs("header",{className:"mobile-header",children:[c.jsx(ei,{compact:!0}),c.jsx(Em,{user:f,label:`Sesión de ${f.name}`})]})}function o0({user:f,view:d,onNavigate:g,onLogout:o}){return c.jsxs("nav",{className:"mobile-nav","aria-label":"Navegación móvil",children:[c.jsxs("button",{type:"button",className:d==="hub"?"is-active":"",onClick:()=>g("hub"),children:[c.jsx(sm,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Inicio"})]}),f.role==="admin"?c.jsxs("button",{type:"button",className:d==="admin"?"is-active":"",onClick:()=>g("admin"),children:[c.jsx(om,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Administrar"})]}):null,c.jsxs("button",{type:"button",onClick:o,children:[c.jsx(rm,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Salir"})]})]})}function Am({hasAccess:f}){const d=f===null?"Verificando acceso":f?"Disponible":"Sin acceso",g=f===null?"access-indicator--checking":f?"access-indicator--granted":"access-indicator--denied";return c.jsxs("span",{className:`access-indicator ${g}`,"aria-label":d,children:[c.jsx("span",{"aria-hidden":"true"}),d]})}function d0({app:f,isFavorite:d,hasAccess:g,onActivate:o,onFavorite:O}){const A=!!Jl(f.url);return c.jsxs("article",{className:"quick-launch",children:[c.jsxs("div",{className:"quick-launch__top",children:[c.jsx(ti,{app:f,size:"regular"}),c.jsx("button",{type:"button",className:`favorite-button ${d?"is-favorite":""}`,onClick:()=>O(f.id),"aria-label":d?`Quitar ${f.name} de favoritos`:`Agregar ${f.name} a favoritos`,"aria-pressed":d,children:c.jsx(Hs,{size:18,fill:d?"currentColor":"none","aria-hidden":"true"})})]}),c.jsxs("div",{className:"quick-launch__copy",children:[c.jsxs("div",{className:"quick-launch__meta",children:[c.jsx("span",{className:"quick-launch__category",children:f.category}),c.jsx(Am,{hasAccess:g})]}),c.jsx("h3",{children:f.name}),c.jsx("p",{children:f.description})]}),c.jsxs("button",{type:"button",className:"quick-launch__action",onClick:()=>o(f),children:[c.jsx("span",{children:A?"Abrir aplicación":"Enlace pendiente"}),A?c.jsx(Un,{size:18,"aria-hidden":"true"}):c.jsx(fm,{size:17,"aria-hidden":"true"})]})]})}function m0({app:f,index:d,isFavorite:g,hasAccess:o,onActivate:O,onFavorite:A}){const C=!!Jl(f.url);return c.jsxs("article",{className:"directory-row",children:[c.jsx("span",{className:"directory-row__number","aria-hidden":"true",children:String(d+1).padStart(2,"0")}),c.jsx(ti,{app:f,size:"small"}),c.jsxs("div",{className:"directory-row__copy",children:[c.jsx("h3",{children:f.name}),c.jsx("p",{children:f.description})]}),c.jsx("span",{className:"directory-row__category",children:f.category}),c.jsx("span",{className:"directory-row__status",children:c.jsx(Am,{hasAccess:o})}),c.jsx("button",{type:"button",className:`favorite-button ${g?"is-favorite":""}`,onClick:()=>A(f.id),"aria-label":g?`Quitar ${f.name} de favoritos`:`Agregar ${f.name} a favoritos`,"aria-pressed":g,children:c.jsx(Hs,{size:18,fill:g?"currentColor":"none","aria-hidden":"true"})}),c.jsxs("button",{type:"button",className:"directory-row__open",onClick:()=>O(f),children:[c.jsx("span",{children:C?"Abrir":"Ver estado"}),C?c.jsx(Un,{size:17,"aria-hidden":"true"}):c.jsx(cm,{size:17,"aria-hidden":"true"})]})]})}function h0({search:f,favoritesOnly:d,onClear:g}){return c.jsxs("div",{className:"empty-state",children:[c.jsx("span",{className:"empty-state__mark","aria-hidden":"true",children:"0"}),c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"SIN RESULTADOS"}),c.jsx("h3",{children:d?"Aún no tienes favoritos aquí.":`No encontramos “${f||"esa aplicación"}”.`}),c.jsx("p",{children:"Prueba otro término, cambia la categoría o vuelve a ver todo el directorio."}),c.jsx("button",{type:"button",className:"text-button",onClick:g,children:"Limpiar filtros"})]})]})}function y0({apps:f,onSubmit:d}){const g=H.useRef(null),[o,O]=H.useState("Todas"),[A,C]=H.useState(""),[Z,q]=H.useState(!1),E=H.useMemo(()=>[...f].filter(V=>V.visibility==="published").sort((V,P)=>Cs.compare(V.name,P.name)),[f]),Y=H.useMemo(()=>o==="Todas"?E:E.filter(V=>V.category===o),[o,E]);H.useEffect(()=>{A&&!Y.some(V=>V.id===A)&&C("")},[A,Y]),H.useEffect(()=>{if(!Z)return;const V=P=>{P.preventDefault(),P.returnValue=""};return window.addEventListener("beforeunload",V),()=>window.removeEventListener("beforeunload",V)},[Z]);const B=()=>{var V;O("Todas"),C(""),(V=g.current)==null||V.showModal()},$=()=>{var V;Z||(V=g.current)==null||V.close()},de=async V=>{var K;V.preventDefault();const P=E.find(le=>le.id===A);if(!(!P||Z)){q(!0);try{await d(P)&&((K=g.current)==null||K.close(),O("Todas"),C(""))}finally{q(!1)}}};return c.jsxs("section",{className:"access-request-bridge","aria-label":"Solicitud de acceso a aplicaciones",children:[c.jsx("div",{className:"access-request-bridge__number","aria-hidden":"true",children:"?"}),c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"SOLICITUD DE ACCESO"}),c.jsx("h2",{children:"¿No tienes acceso a una aplicación?"}),c.jsx("p",{children:"Selecciona el portal que necesitas y envía la solicitud al equipo responsable."})]}),c.jsxs("button",{type:"button",className:"secondary-button",onClick:B,children:["Solicitar acceso aquí",c.jsx(Un,{size:18,"aria-hidden":"true"})]}),c.jsxs("dialog",{className:"access-request-dialog",ref:g,onCancel:V=>{Z&&V.preventDefault()},children:[c.jsx("button",{type:"button",className:"access-request-dialog__close",onClick:$,"aria-label":"Cerrar",children:c.jsx(kl,{size:19,"aria-hidden":"true"})}),c.jsx("p",{className:"section-kicker",children:"GLM HUB"}),c.jsx("h2",{children:"Solicitar acceso"}),c.jsx("p",{className:"access-request-dialog__intro",children:"Elige el área y la aplicación. El catálogo se actualiza automáticamente con los portales publicados."}),c.jsxs("form",{onSubmit:V=>void de(V),children:[c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"access-request-area",children:["Área",c.jsx(Kl,{})]}),c.jsxs("select",{id:"access-request-area",value:o,onChange:V=>O(V.target.value),disabled:Z,required:!0,children:[c.jsx("option",{value:"Todas",children:"Todas"}),c.jsx("option",{value:"Administración",children:"Administración"}),c.jsx("option",{value:"Recursos Humanos",children:"Recursos Humanos"}),c.jsx("option",{value:"CDC",children:"CDC"})]})]}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"access-request-app",children:["Aplicación",c.jsx(Kl,{})]}),c.jsxs("select",{id:"access-request-app",value:A,onChange:V=>C(V.target.value),disabled:Z||Y.length===0,required:!0,children:[c.jsx("option",{value:"",children:Y.length===0?"No hay aplicaciones publicadas en esta área":"Selecciona una aplicación"}),Y.map(V=>c.jsx("option",{value:V.id,children:V.name},V.id))]})]}),c.jsxs("div",{className:"access-request-dialog__actions",children:[c.jsx("button",{type:"button",className:"secondary-button secondary-button--quiet",onClick:$,disabled:Z,children:"Cancelar"}),c.jsx("button",{type:"submit",className:"primary-button",disabled:!A||Z,children:Z?"Enviando…":"Enviar solicitud"})]})]})]}),Z?c.jsx("div",{className:"generation-overlay",role:"dialog","aria-modal":"true","aria-labelledby":"access-request-loading-title",children:c.jsxs("div",{className:"generation-overlay__card",children:[c.jsx("span",{className:"generation-spinner","aria-hidden":"true"}),c.jsx("p",{className:"section-kicker",children:"GLM HUB"}),c.jsx("h2",{id:"access-request-loading-title",children:"Enviando la solicitud…"}),c.jsx("p",{children:"Estamos registrando la solicitud y enviando el correo a las personas responsables."})]})}):null]})}function v0(f,d,g=!1){return d<=(g?5:7)?Array.from({length:d},(O,A)=>A+1):g?f<=3?[1,2,3,"ellipsis-end",d]:f>=d-2?[1,"ellipsis-start",d-2,d-1,d]:[1,"ellipsis-start",f,"ellipsis-end",d]:f<=4?[1,2,3,4,5,"ellipsis-end",d]:f>=d-3?[1,"ellipsis-start",d-4,d-3,d-2,d-1,d]:[1,"ellipsis-start",f-1,f,f+1,"ellipsis-end",d]}function Rs({currentPage:f,totalPages:d,onPageChange:g,compact:o=!1,label:O}){if(d<=1)return null;const A=v0(f,d,o);return c.jsxs("nav",{className:`pagination ${o?"pagination--compact":""}`,"aria-label":O,children:[c.jsx("button",{type:"button",className:"pagination__arrow",disabled:f<=1,onClick:()=>g(f-1),"aria-label":"Página anterior",children:c.jsx(dv,{size:16,"aria-hidden":"true"})}),c.jsx("div",{className:"pagination__pages",children:A.map(C=>typeof C=="number"?c.jsx("button",{type:"button",className:`pagination__page ${C===f?"is-active":""}`,onClick:()=>g(C),"aria-label":`Ir a la página ${C}`,"aria-current":C===f?"page":void 0,children:C},C):c.jsx("span",{className:"pagination__ellipsis","aria-hidden":"true",children:"…"},C))}),c.jsx("button",{type:"button",className:"pagination__arrow",disabled:f>=d,onClick:()=>g(f+1),"aria-label":"Página siguiente",children:c.jsx(cm,{size:16,"aria-hidden":"true"})})]})}const Fu=10,xs=6,Os=12;function g0({user:f,data:d,accessByApp:g,accessReady:o,storageWarning:O,onActivate:A,onFavorite:C,onAdmin:Z,onRequestAccess:q}){const[E,Y]=H.useState({Todas:"",Administración:"","Recursos Humanos":"",CDC:""}),[B,$]=H.useState("Todas"),[de,V]=H.useState(!1),[P,K]=H.useState(1),[le,Me]=H.useState(1),ge=E[B]??"",Ae=r=>{Y(y=>({...y,[B]:r}))},Oe=H.useDeferredValue(ge),ze=i0(),F=f.role==="admin",k=d.favoritesByUser[f.id]??[],me=d.recentByUser[f.id]??[],Ne=H.useMemo(()=>new Set(k),[k]),he=H.useMemo(()=>[...d.apps.filter(r=>r.visibility==="published"&&!!r.iconDataUrl.trim())].sort((r,y)=>Cs.compare(r.name,y.name)),[d.apps]),je=H.useMemo(()=>{const r=Ca(Oe);return he.filter(y=>B!=="Todas"&&y.category!==B||de&&!Ne.has(y.id)?!1:r?Ca(y.name).includes(r):!0).sort((y,j)=>Number(Ne.has(j.id))-Number(Ne.has(y.id))||Cs.compare(y.name,j.name))},[B,Oe,Ne,de,he]),we=Math.max(1,Math.ceil(je.length/Fu));H.useEffect(()=>{K(1)},[ge,B,de]),H.useEffect(()=>{P>we&&K(we)},[P,we]);const tt=H.useMemo(()=>{const r=(P-1)*Fu;return je.slice(r,r+Fu)},[P,je]),Ke=r=>{K(Math.min(Math.max(r,1),we)),window.requestAnimationFrame(()=>{var y;(y=document.getElementById("directory-title"))==null||y.scrollIntoView({behavior:"smooth",block:"start"})})},z=H.useMemo(()=>{const r=new Map(he.map(G=>[G.id,G])),y=[],j=new Set,M=G=>{const X=r.get(G);!X||j.has(G)||(y.push(X),j.add(G))};if(k.forEach(M),y.length<3){for(const G of me)if(M(G),y.length>=3)break}if(y.length<3){for(const G of he)if(M(G.id),y.length>=3)break}return y},[k,he,me]),R=Math.max(1,Math.ceil(z.length/xs)),U=H.useMemo(()=>{const r=(le-1)*xs;return z.slice(r,r+xs)},[z,le]);H.useEffect(()=>{le>R&&Me(R)},[le,R]),H.useEffect(()=>{Me(1)},[d.favoritesByUser,d.recentByUser,f.id]);const L=r=>{Me(Math.min(Math.max(r,1),R)),window.requestAnimationFrame(()=>{var y;(y=document.getElementById("quick-title"))==null||y.scrollIntoView({behavior:"smooth",block:"start"})})},N=()=>{Y({Todas:"",Administración:"","Recursos Humanos":"",CDC:""}),$("Todas"),V(!1)};return c.jsxs("main",{className:"page-content hub-page",children:[c.jsxs("header",{className:"page-header",children:[c.jsxs("div",{children:[c.jsxs("p",{className:"page-header__meta",children:[u0(),", ",f.name]}),c.jsx("h1",{children:"Tu mesa de trabajo."})]}),c.jsx("div",{className:"page-header__aside",children:c.jsx("span",{children:ze})})]}),O?c.jsx("div",{className:"inline-alert",role:"status",children:O}):null,c.jsxs("section",{className:"search-stage","aria-labelledby":"search-title",children:[c.jsx("div",{className:"search-stage__copy",children:c.jsx("h2",{id:"search-title",children:"¿Qué necesitas abrir?"})}),c.jsxs("div",{className:"hub-search",children:[c.jsx(Ds,{size:21,"aria-hidden":"true"}),c.jsx("label",{className:"sr-only",htmlFor:"hub-search-input",children:"Buscar por nombre de proyecto"}),c.jsx("input",{id:"hub-search-input",type:"search",value:ge,onChange:r=>Ae(r.target.value),placeholder:"Buscar por nombre de proyecto…"}),ge?c.jsx("button",{type:"button",onClick:()=>Ae(""),"aria-label":"Limpiar búsqueda",children:c.jsx(kl,{size:18,"aria-hidden":"true"})}):null]})]}),c.jsxs("section",{className:"quick-section","aria-labelledby":"quick-title",children:[c.jsxs("div",{className:"section-heading",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"FIJADAS PARA TI"}),c.jsx("h2",{id:"quick-title",children:"Acceso rápido"})]}),c.jsx("p",{children:"Abre lo que más usas sin detener el ritmo."})]}),c.jsx("div",{className:"quick-grid",children:U.map(r=>c.jsx(d0,{app:r,isFavorite:Ne.has(r.id),hasAccess:o?g[r.id]===!0:null,onActivate:A,onFavorite:C},r.id))}),c.jsx(Rs,{currentPage:le,totalPages:R,onPageChange:L,compact:R>5,label:"Paginación de acceso rápido"})]}),c.jsxs("section",{className:"directory-section","aria-labelledby":"directory-title",children:[c.jsxs("div",{className:"section-heading section-heading--directory",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"DIRECTORIO GLM"}),c.jsx("h2",{id:"directory-title",children:"Todas las aplicaciones"})]}),c.jsxs("div",{className:"directory-count","aria-live":"polite",children:[c.jsx("strong",{children:je.length}),c.jsx("span",{children:je.length===1?"resultado":"resultados"})]})]}),c.jsxs("div",{className:"filter-bar","aria-label":"Filtros del directorio",children:[c.jsx("div",{className:"category-filters",children:["Todas",...dm].map(r=>c.jsx("button",{type:"button",className:B===r?"is-active":"",onClick:()=>$(r),"aria-pressed":B===r,children:r},r))}),c.jsxs("div",{className:"filter-bar__search",children:[c.jsx(Ds,{size:16,"aria-hidden":"true"}),c.jsx("label",{className:"sr-only",htmlFor:"directory-search-input",children:`Buscar por nombre de proyecto en ${B}`}),c.jsx("input",{id:"directory-search-input",type:"search",value:ge,onChange:r=>Ae(r.target.value),placeholder:B==="Todas"?"Buscar por nombre de proyecto…":`Buscar en ${B}…`}),ge?c.jsx("button",{type:"button",onClick:()=>Ae(""),"aria-label":"Limpiar búsqueda",children:c.jsx(kl,{size:15,"aria-hidden":"true"})}):null]}),c.jsxs("button",{type:"button",className:`favorites-filter ${de?"is-active":""}`,onClick:()=>V(r=>!r),"aria-pressed":de,children:[c.jsx(Hs,{size:17,fill:de?"currentColor":"none","aria-hidden":"true"}),"Solo favoritos"]})]}),je.length>0?c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"directory-list",children:tt.map((r,y)=>c.jsx(m0,{app:r,index:(P-1)*Fu+y,isFavorite:Ne.has(r.id),hasAccess:o?g[r.id]===!0:null,onActivate:A,onFavorite:C},r.id))}),c.jsx(Rs,{currentPage:P,totalPages:we,onPageChange:Ke,compact:we>5,label:"Paginación de aplicaciones"})]}):c.jsx(h0,{search:ge,favoritesOnly:de,onClear:N})]}),F?c.jsxs("section",{className:"admin-bridge","aria-label":"Acceso al panel de administración",children:[c.jsx("div",{className:"admin-bridge__number","aria-hidden":"true",children:"+"}),c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"CONTROL DEL CATÁLOGO"}),c.jsx("h2",{children:"¿Falta una herramienta?"}),c.jsx("p",{children:"Adjunta su ícono, pega el enlace y publícala para todo el equipo."})]}),c.jsxs("button",{type:"button",className:"secondary-button",onClick:Z,children:["Administrar aplicaciones",c.jsx(Un,{size:18,"aria-hidden":"true"})]})]}):c.jsx(y0,{apps:he,onSubmit:q})]})}function p0({apps:f,selectedId:d,onSelect:g,onDelete:o}){const[O,A]=H.useState(""),[C,Z]=H.useState(1),[q,E]=H.useState(null),Y=H.useRef(null),B=H.useMemo(()=>{const K=Ca(O);return K?f.filter(le=>Ca(`${le.name} ${le.category}`).includes(K)):f},[f,O]),$=Math.max(1,Math.ceil(B.length/Os));H.useEffect(()=>{Z(1)},[O]),H.useEffect(()=>{C>$&&Z($)},[C,$]);const de=H.useMemo(()=>{const K=(C-1)*Os;return B.slice(K,K+Os)},[B,C]),V=(K,le)=>{var Me;K.stopPropagation(),E(le),(Me=Y.current)==null||Me.showModal()},P=async()=>{var K;q&&await o(q.id)&&((K=Y.current)==null||K.close(),E(null))};return c.jsxs("aside",{className:"admin-list","aria-label":"Aplicaciones configuradas",children:[c.jsxs("div",{className:"admin-list__top",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"CATÁLOGO"}),c.jsxs("h2",{children:[f.length," ",f.length===1?"aplicación":"aplicaciones"]})]}),c.jsx("button",{type:"button",className:"icon-button icon-button--accent",onClick:()=>g(null),"aria-label":"Crear aplicación",children:c.jsx(Id,{size:20,"aria-hidden":"true"})})]}),c.jsxs("div",{className:"admin-list__search",children:[c.jsx(Ds,{size:17,"aria-hidden":"true"}),c.jsx("label",{htmlFor:"admin-search",className:"sr-only",children:"Buscar en el catálogo"}),c.jsx("input",{id:"admin-search",type:"search",value:O,onChange:K=>A(K.target.value),placeholder:"Buscar…"}),O?c.jsx("button",{type:"button",onClick:()=>A(""),"aria-label":"Limpiar búsqueda",children:c.jsx(kl,{size:15,"aria-hidden":"true"})}):null]}),c.jsxs("div",{className:"admin-list__items",children:[C===1?c.jsxs("button",{type:"button",className:`admin-list__new ${d===null?"is-active":""}`,onClick:()=>g(null),children:[c.jsx("span",{className:"admin-list__new-icon",children:c.jsx(Id,{size:18,"aria-hidden":"true"})}),c.jsxs("span",{className:"admin-list__item-info",children:[c.jsx("strong",{children:"Nueva aplicación"}),c.jsx("small",{children:"Crear y publicar"})]})]}):null,de.map(K=>c.jsxs("div",{className:`admin-list__item-row ${d===K.id?"is-active":""}`,onClick:()=>g(K.id),role:"button",tabIndex:0,onKeyDown:le=>{(le.key==="Enter"||le.key===" ")&&g(K.id)},children:[c.jsx(ti,{app:K,size:"small"}),c.jsxs("span",{className:"admin-list__item-info",children:[c.jsx("strong",{children:K.name}),c.jsx("small",{children:K.category})]}),c.jsxs("div",{className:"admin-list__item-actions",children:[c.jsx("span",{className:`mini-status ${K.visibility==="hidden"?"is-hidden":""}`,children:K.visibility==="hidden"?"Oculta":Jl(K.url)?"Lista":"Pendiente"}),c.jsx("button",{type:"button",className:"admin-list__delete-icon",onClick:le=>V(le,K),title:`Eliminar ${K.name}`,"aria-label":`Eliminar ${K.name}`,children:c.jsx(Iu,{size:15,"aria-hidden":"true"})})]})]},K.id))]}),c.jsx(Rs,{currentPage:C,totalPages:$,onPageChange:Z,compact:!0,label:"Paginación del catálogo de administración"}),c.jsxs("dialog",{className:"confirm-dialog",ref:Y,children:[c.jsx("button",{type:"button",className:"confirm-dialog__close",onClick:()=>{var K;return(K=Y.current)==null?void 0:K.close()},"aria-label":"Cerrar",children:c.jsx(kl,{size:19,"aria-hidden":"true"})}),c.jsx("span",{className:"confirm-dialog__icon",children:c.jsx(Iu,{size:22,"aria-hidden":"true"})}),c.jsx("p",{className:"section-kicker",children:"ACCIÓN PERMANENTE"}),c.jsxs("h2",{children:["Eliminar ",q==null?void 0:q.name]}),c.jsx("p",{children:"El portal y sus accesos se eliminarán permanentemente. Esta acción no se puede deshacer."}),c.jsxs("div",{className:"confirm-dialog__actions",children:[c.jsx("button",{type:"button",className:"secondary-button",onClick:()=>{var K;return(K=Y.current)==null?void 0:K.close()},children:"Conservar"}),c.jsx("button",{type:"button",className:"danger-button danger-button--solid",onClick:P,children:"Sí, eliminar"})]})]})]})}function Kl(){return c.jsxs(c.Fragment,{children:[c.jsx("span",{className:"required-mark","aria-hidden":"true",children:"*"}),c.jsx("span",{className:"sr-only",children:" obligatorio"})]})}function b0({app:f,allApps:d,onSave:g,onDelete:o,onCancel:O}){const[A,C]=H.useState(()=>f?Dn(f):Wu()),[Z,q]=H.useState(()=>JSON.stringify(f?Dn(f):Wu())),[E,Y]=H.useState({}),[B,$]=H.useState(""),[de,V]=H.useState(!1),[P,K]=H.useState(!1),[le,Me]=H.useState(!1),[ge,Ae]=H.useState(!1),Oe=H.useRef(null),ze=H.useRef(null),F=JSON.stringify(A)!==Z,k=de||P||le,me=A.name.trim().length>=2&&!!A.description.trim();H.useEffect(()=>{const N=f?Dn(f):Wu();C(N),q(JSON.stringify(N)),Y({}),$(""),window.requestAnimationFrame(()=>{var r;return(r=ze.current)==null?void 0:r.focus()})},[f]),H.useEffect(()=>{if(!F&&!P)return;const N=r=>r.preventDefault();return window.addEventListener("beforeunload",N),()=>window.removeEventListener("beforeunload",N)},[P,F]),H.useEffect(()=>{if(!P)return;const N=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=N}},[P]);const Ne={id:(f==null?void 0:f.id)??"preview",name:A.name||"Nombre de la aplicación",description:A.description||"Una descripción breve ayuda al equipo a reconocerla.",category:A.category,keywords:[],url:A.url,mark:bm(A.name||"GLM"),accent:(f==null?void 0:f.accent)??"#4F758B",iconDataUrl:A.iconDataUrl,visibility:A.visibility,createdAt:(f==null?void 0:f.createdAt)??new Date().toISOString(),updatedAt:new Date().toISOString()},he=(N,r)=>{C(y=>({...y,[N]:r})),Y(y=>({...y,[N]:""}))},je=async N=>{if(!(!N||P)){$(""),V(!0);try{const r=await Sm(N);he("iconDataUrl",r)}catch(r){$(r instanceof Error?r.message:"No pudimos procesar el ícono.")}finally{V(!1)}}},we=N=>{var r;je((r=N.target.files)==null?void 0:r[0]),N.target.value=""},tt=N=>{var r;N.preventDefault(),Ae(!1),je((r=N.dataTransfer.files)==null?void 0:r[0])},Ke=async()=>{var G;const N=A.name.trim(),r=A.description.trim(),y={};if(N.length<2&&(y.name="Completa el nombre antes de generar el ícono."),r||(y.description="Completa la descripción antes de generar el ícono."),Object.keys(y).length>0){Y(X=>({...X,...y}));return}if(!tm){$("Falta configurar VITE_ICON_GENERATOR_WEBHOOK_URL en el archivo .env.");return}$(""),K(!0);const j=new AbortController,M=window.setTimeout(()=>j.abort(),18e4);try{const{data:{session:X}}=await Ue.auth.getSession();if(!(X!=null&&X.access_token))throw new Error("La sesión venció. Inicia sesión nuevamente.");const ae=await fetch(tm,{method:"POST",mode:"cors",cache:"no-store",credentials:"omit",signal:j.signal,headers:{Accept:"image/*, application/json;q=0.9, text/plain;q=0.8","Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify({accessToken:X.access_token,name:N,description:r})}),Je=((G=ae.headers.get("content-type"))==null?void 0:G.toLocaleLowerCase("en-US"))??"";if(ae.ok&&Je.startsWith("image/")){const tl=await _m(await ae.blob());he("iconDataUrl",tl);return}const _e=await ae.text();let Pe=null;if(_e)try{Pe=JSON.parse(_e)}catch{Pe=null}if(ae.ok&&(Pe!=null&&Pe.ok)&&Pe.imageDataUrl){const tl=await c0(Pe.imageDataUrl);he("iconDataUrl",tl);return}throw new Error((Pe==null?void 0:Pe.error)||(_e&&_e.length<500?_e:"")||`El flujo no pudo generar el ícono (HTTP ${ae.status}).`)}catch(X){X instanceof DOMException&&X.name==="AbortError"?$("La generación tardó más de 3 minutos y fue cancelada. Intenta nuevamente."):X instanceof TypeError&&/failed to fetch/i.test(X.message)?$("No se pudo conectar con el webhook de n8n. Verifica que el workflow esté activo y publicado."):$(X instanceof Error?X.message:"No pudimos generar el ícono con IA.")}finally{window.clearTimeout(M),K(!1)}},z=()=>{const N={},r=A.name.trim(),y=A.description.trim();(r.length<2||r.length>60)&&(N.name="Escribe un nombre de 2 a 60 caracteres."),y||(N.description="Añade una descripción breve."),y.length>180&&(N.description="La descripción no puede superar 180 caracteres."),A.iconDataUrl||(N.iconDataUrl="Adjunta o genera un ícono antes de publicar la aplicación."),A.url.trim()&&!Jl(A.url)&&(N.url="Usa una URL https:// válida, sin credenciales embebidas.");const j=Ca(r);return d.some(G=>G.id!==(f==null?void 0:f.id)&&Ca(G.name)===j)&&(N.name="Ya existe una aplicación con ese nombre."),Y(N),Object.keys(N).length===0},R=async N=>{if(N.preventDefault(),k||!z()){window.requestAnimationFrame(()=>{var r,y;return(y=(r=document.querySelector(".field-error"))==null?void 0:r.focus)==null?void 0:y.call(r)});return}Me(!0);try{const r=await g({...A,name:A.name.trim(),description:A.description.trim(),url:A.url.trim()},(f==null?void 0:f.id)??null);if(r){const y=Dn(r);C(y),q(JSON.stringify(y))}}finally{Me(!1)}},U=()=>{if(!P&&(!F||window.confirm("Hay cambios sin guardar. ¿Quieres descartarlos?"))){const N=f?Dn(f):Wu();C(N),q(JSON.stringify(N)),Y({}),$(""),O()}},L=async()=>{var N;!f||k||await o(f.id)&&((N=Oe.current)==null||N.close(),O())};return c.jsxs("section",{className:"app-editor","aria-labelledby":"editor-title","aria-busy":k,children:[c.jsxs("div",{className:"app-editor__heading",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:f?"EDITAR APLICACIÓN":"NUEVA APLICACIÓN"}),c.jsx("h2",{id:"editor-title",children:f?f.name:"Configura el nuevo acceso"})]}),F?c.jsxs("span",{className:"dirty-state is-dirty",children:[c.jsx("span",{"aria-hidden":"true"}),"Cambios sin guardar"]}):null]}),c.jsxs("div",{className:"editor-layout",children:[c.jsxs("form",{className:"editor-form",onSubmit:R,noValidate:!0,children:[c.jsxs("section",{className:"editor-form__section","aria-labelledby":"identity-section-title",children:[c.jsx("h3",{className:"editor-form__section-title",id:"identity-section-title",children:"Identidad"}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-name",children:["Nombre de la aplicación",f?null:c.jsx(Kl,{})]}),c.jsx("input",{ref:ze,id:"app-name",value:A.name,onChange:N=>he("name",N.target.value),placeholder:"Ej. Media Planner",maxLength:60,"aria-invalid":!!E.name,"aria-describedby":E.name?"app-name-error":void 0,disabled:k,required:!0}),c.jsxs("div",{className:"field-meta",children:[E.name?c.jsx("span",{id:"app-name-error",className:"field-error",role:"alert",tabIndex:-1,children:E.name}):c.jsx("span",{children:"Como el equipo la reconoce."}),c.jsxs("span",{children:[A.name.length,"/60"]})]})]}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-description",children:["Descripción breve",f?null:c.jsx(Kl,{})]}),c.jsx("textarea",{id:"app-description",value:A.description,onChange:N=>he("description",N.target.value),placeholder:"Explica qué resuelve en una sola frase.",maxLength:180,rows:3,"aria-invalid":!!E.description,"aria-describedby":E.description?"app-description-error":void 0,disabled:k,required:!0}),c.jsxs("div",{className:`field-meta ${E.description?"":"field-meta--counter-only"}`,children:[E.description?c.jsx("span",{id:"app-description-error",className:"field-error",role:"alert",tabIndex:-1,children:E.description}):null,c.jsxs("span",{children:[A.description.length,"/180"]})]})]}),c.jsxs("div",{className:"form-split",children:[c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-category",children:["Categoría",f?null:c.jsx(Kl,{})]}),c.jsx("select",{id:"app-category",value:A.category,onChange:N=>he("category",N.target.value),disabled:k,required:!0,children:dm.map(N=>c.jsx("option",{children:N},N))})]}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-visibility",children:["Visibilidad",f?null:c.jsx(Kl,{})]}),c.jsxs("select",{id:"app-visibility",value:A.visibility,onChange:N=>he("visibility",N.target.value),disabled:k,required:!0,children:[c.jsx("option",{value:"published",children:"Publicada"}),c.jsx("option",{value:"hidden",children:"Oculta"})]})]})]})]}),c.jsxs("section",{className:"editor-form__section","aria-labelledby":"icon-section-title",children:[c.jsxs("h3",{className:"editor-form__section-title",id:"icon-section-title",children:["Ícono",f?null:c.jsx(Kl,{})]}),c.jsxs("div",{className:"icon-config",children:[c.jsxs("label",{className:`icon-dropzone ${ge?"is-dragging":""}`,onDragEnter:N=>{N.preventDefault(),k||Ae(!0)},onDragOver:N=>N.preventDefault(),onDragLeave:()=>Ae(!1),onDrop:tt,children:[c.jsx("input",{type:"file",accept:"image/png,image/jpeg,image/webp",onChange:we,disabled:k}),c.jsx("span",{className:"icon-dropzone__symbol",children:c.jsx(Mv,{size:20,"aria-hidden":"true"})}),c.jsxs("span",{children:[c.jsx("strong",{children:de?"Procesando…":"Adjuntar ícono"}),c.jsx("small",{children:"PNG, JPG o WebP · máximo 1 MB"})]})]}),A.iconDataUrl?c.jsx("button",{type:"button",className:"text-button text-button--danger",disabled:k,onClick:()=>he("iconDataUrl",""),children:"Quitar ícono"}):null]}),c.jsx("div",{className:"ai-icon-actions",children:c.jsxs("button",{type:"button",className:"secondary-button ai-icon-button",onClick:()=>void Ke(),disabled:!me||k,title:me?void 0:"Completa el nombre y la descripción breve.",children:[c.jsx(Tv,{size:18,"aria-hidden":"true"}),"Generar ícono con IA"]})}),B?c.jsx("p",{className:"field-error field-error--standalone",role:"alert",children:B}):null,E.iconDataUrl?c.jsx("p",{className:"field-error field-error--standalone",role:"alert",tabIndex:-1,children:E.iconDataUrl}):null]}),c.jsxs("section",{className:"editor-form__section","aria-labelledby":"destination-section-title",children:[c.jsx("h3",{className:"editor-form__section-title",id:"destination-section-title",children:"Destino"}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-url",children:["Enlace de la aplicación ",c.jsx("span",{children:"Opcional"})]}),c.jsxs("div",{className:"url-field",children:[c.jsx(fm,{size:18,"aria-hidden":"true"}),c.jsx("input",{id:"app-url",type:"url",value:A.url,onChange:N=>he("url",N.target.value),placeholder:"https://aplicacion.com","aria-invalid":!!E.url,"aria-describedby":E.url?"app-url-error":"app-url-help",disabled:k})]}),E.url?c.jsx("span",{id:"app-url-error",className:"field-error",role:"alert",tabIndex:-1,children:E.url}):c.jsx("span",{id:"app-url-help",className:"field-help",children:"Si lo dejas vacío, aparecerá como “Enlace pendiente”."})]})]}),c.jsxs("div",{className:"editor-actions",children:[c.jsxs("button",{type:"submit",className:"primary-button",disabled:k,children:[c.jsx(Av,{size:18,"aria-hidden":"true"}),le?"Guardando…":f?"Guardar cambios":"Publicar aplicación"]}),c.jsx("button",{type:"button",className:"secondary-button secondary-button--quiet",disabled:k,onClick:U,children:"Cancelar"}),f?c.jsxs("button",{type:"button",className:"danger-button",disabled:k,onClick:()=>{var N;return(N=Oe.current)==null?void 0:N.showModal()},children:[c.jsx(Iu,{size:17,"aria-hidden":"true"}),"Eliminar"]}):null]})]}),c.jsxs("aside",{className:"app-preview","aria-label":"Vista previa de la aplicación",children:[c.jsxs("div",{className:"app-preview__label",children:[c.jsx("span",{children:"VISTA PREVIA"}),c.jsx("span",{className:"app-preview__rule"})]}),c.jsxs("div",{className:"preview-card",children:[c.jsx(ti,{app:Ne,size:"large",showPlaceholder:!f&&!A.iconDataUrl}),c.jsx("span",{className:"quick-launch__category",children:Ne.category}),c.jsx("h3",{children:Ne.name}),c.jsx("p",{children:Ne.description}),c.jsxs("span",{className:`availability ${Jl(Ne.url)?"availability--ready":"availability--pending"}`,children:[c.jsx("span",{"aria-hidden":"true"}),Jl(Ne.url)?"Lista para abrir":"Enlace pendiente"]})]}),c.jsx("p",{className:"app-preview__note",children:"Así aparecerá en el Hub para el equipo."})]})]}),c.jsxs("dialog",{className:"confirm-dialog",ref:Oe,children:[c.jsx("button",{type:"button",className:"confirm-dialog__close",onClick:()=>{var N;return(N=Oe.current)==null?void 0:N.close()},"aria-label":"Cerrar",children:c.jsx(kl,{size:19,"aria-hidden":"true"})}),c.jsx("span",{className:"confirm-dialog__icon",children:c.jsx(Iu,{size:22,"aria-hidden":"true"})}),c.jsx("p",{className:"section-kicker",children:"ACCIÓN PERMANENTE"}),c.jsxs("h2",{children:["Eliminar ",f==null?void 0:f.name]}),c.jsx("p",{children:"La aplicación se quitará del catálogo compartido para todo el equipo. Esta acción no se puede deshacer."}),c.jsxs("div",{className:"confirm-dialog__actions",children:[c.jsx("button",{type:"button",className:"secondary-button",onClick:()=>{var N;return(N=Oe.current)==null?void 0:N.close()},children:"Conservar"}),c.jsx("button",{type:"button",className:"danger-button danger-button--solid",onClick:()=>void L(),children:"Sí, eliminar"})]})]}),P?c.jsx("div",{className:"generation-overlay",role:"dialog","aria-modal":"true","aria-labelledby":"generation-title",children:c.jsxs("div",{className:"generation-overlay__card",children:[c.jsx("span",{className:"generation-spinner","aria-hidden":"true"}),c.jsx("p",{className:"section-kicker",children:"GEMINI"}),c.jsx("h2",{id:"generation-title",children:"Generando el ícono…"}),c.jsx("p",{children:"Estamos creando una propuesta a partir del nombre y la descripción de la aplicación."})]})}):null]})}function S0({data:f,onSave:d,onDelete:g,onBack:o}){const[O,A]=H.useState(null),C=O?f.apps.find(E=>E.id===O)??null:null,Z=async(E,Y)=>{const B=await d(E,Y);return B&&A(B.id),B},q=async E=>{const Y=await g(E);return Y&&A(null),Y};return c.jsxs("main",{className:"page-content admin-page",children:[c.jsx("header",{className:"page-header admin-header",children:c.jsxs("div",{children:[c.jsxs("button",{type:"button",className:"back-button",onClick:o,children:[c.jsx(fv,{size:17,"aria-hidden":"true"}),"Volver al Hub"]}),c.jsx("p",{className:"page-header__meta",children:"PANEL DE ADMINISTRACIÓN"}),c.jsx("h1",{children:"Controla el catálogo."})]})}),c.jsxs("div",{className:"admin-workspace",children:[c.jsx(p0,{apps:f.apps,selectedId:O,onSelect:A,onDelete:q}),c.jsx(b0,{app:C,allApps:f.apps,onSave:Z,onDelete:q,onCancel:()=>A(null)})]})]})}function _0(){return c.jsxs("div",{className:"catalog-loading",role:"status","aria-live":"polite",children:[c.jsx(ei,{compact:!0}),c.jsx("span",{className:"generation-spinner","aria-hidden":"true"}),c.jsx("p",{children:"Cargando aplicaciones…"})]})}function E0(){const[f]=H.useState(()=>Qv()),[d,g]=H.useState({schemaVersion:1,apps:[],favoritesByUser:{},recentByUser:{},updatedAt:new Date().toISOString()}),[o,O]=H.useState(null),[A,C]=H.useState(()=>"hub"),[Z,q]=H.useState([]),[E,Y]=H.useState(!1),[B,$]=H.useState(!1),[de,V]=H.useState(""),[P,K]=H.useState({}),[le,Me]=H.useState(!1),[ge,Ae]=H.useState(""),Oe=H.useRef(0),ze=H.useRef(null),F=H.useCallback(U=>{q(L=>L.filter(N=>N.id!==U))},[]),k=H.useCallback((U,L,N)=>{const r=crypto.randomUUID();q(y=>[...y.slice(-2),{id:r,kind:U,title:L,detail:N}]),window.setTimeout(()=>{q(y=>y.filter(j=>j.id!==r))},5200)},[]);H.useEffect(()=>{let U=!0;const L=y=>{const j=(y.expires_at??Math.floor(Date.now()/1e3)+3600)*1e3;O(M=>!M||M.user.id!==y.user.id||M.expiresAt===j?M:{...M,expiresAt:j})},N=async y=>{const j=++Oe.current;if(!y){if(!U||j!==Oe.current)return;ze.current=null,O(null),$(!1),Y(!0);return}if(ze.current===y.user.id){if(!U||j!==Oe.current)return;L(y),Y(!0);return}const M=await n0(y);if(!U||j!==Oe.current)return;if(!M.session){ze.current=null,O(null),Ae(M.error),$(!1),Y(!0),await Ue.auth.signOut({scope:"local"});return}const G=M.session;ze.current=G.user.id,Ae(""),O(G),Y(!0),window.location.hash!=="#hub"&&window.location.hash!=="#admin"&&window.history.replaceState(null,"",Ns("#hub"))};Ue.auth.getSession().then(({data:{session:y}})=>{N(y)});const{data:{subscription:r}}=Ue.auth.onAuthStateChange((y,j)=>{if(y!=="INITIAL_SESSION"){if(y==="TOKEN_REFRESHED"&&j&&ze.current===j.user.id){L(j);return}window.setTimeout(()=>{N(j)},0)}});return()=>{U=!1,r.unsubscribe()}},[]);const me=(o==null?void 0:o.user)??null;H.useEffect(()=>{if(!me)return;let U=!0,L=!1;const N=async()=>{if(!L){L=!0;try{const j=await Bs();if(!U)return;g(M=>({...M,apps:j,updatedAt:new Date().toISOString()}))}catch(j){console.error("No se pudo refrescar el catálogo compartido:",j)}finally{L=!1}}};(async()=>{$(!1),V("");try{const j=await Iv(me,f.data.apps),M=await kv(me.id);if(!U)return;g(M),$(!0),j>0&&k("success","Catálogo compartido activado",`${j} ${j===1?"aplicación fue migrada":"aplicaciones fueron migradas"} a Supabase.`)}catch(j){if(!U)return;const M=j instanceof Error?j.message:"No se pudo cargar el catálogo compartido.";V(M),$(!0),k("error","No se pudo cargar el catálogo",M)}})();const y=Pv(()=>void N());return()=>{U=!1,y()}},[me==null?void 0:me.id,me==null?void 0:me.role,f.data.apps,k]),H.useEffect(()=>{if(!me){K({}),Me(!1);return}let U=!0,L=!1;const N=async()=>{if(!L){L=!0;try{const j=await Vv();if(!U)return;K(j),Me(!0)}catch(j){console.warn("No se pudo verificar el acceso a las aplicaciones:",j),U&&Me(!1)}finally{L=!1}}};N();const r=window.setInterval(()=>void N(),6e4),y=()=>void N();return window.addEventListener("focus",y),()=>{U=!1,window.clearInterval(r),window.removeEventListener("focus",y)}},[me==null?void 0:me.id]),H.useEffect(()=>{const U=()=>{const L=window.location.hash==="#admin"?"admin":"hub";if(L==="admin"&&(o==null?void 0:o.user.role)!=="admin"){C("hub"),window.history.replaceState(null,"","#hub");return}C(L)};return U(),window.addEventListener("hashchange",U),()=>window.removeEventListener("hashchange",U)},[o==null?void 0:o.user.role]);const Ne=U=>{if(U==="admin"&&(o==null?void 0:o.user.role)!=="admin"){k("error","Acceso restringido","Necesitas permisos de administrador para abrir este panel.");return}C(U),window.history.replaceState(null,"",Ns(U==="admin"?"#admin":"#hub")),window.scrollTo({top:0,behavior:"smooth"})},he=async U=>{if(!o)return;const L=o.user.id,N=d.favoritesByUser[L]??[],r=N.includes(U),y=r?N.filter(j=>j!==U):[U,...N];g(j=>({...j,favoritesByUser:{...j.favoritesByUser,[L]:y},updatedAt:new Date().toISOString()}));try{await Wv(L,U,!r),k("success",r?"Quitada de favoritos":"Agregada a favoritos")}catch(j){g(M=>({...M,favoritesByUser:{...M.favoritesByUser,[L]:N}})),k("error","No se actualizó el favorito",j instanceof Error?j.message:void 0)}},je=U=>{if(!o)return;const L=Jl(U.url);if(!L){k("info","Enlace pendiente",`${U.name} todavía no tiene un enlace configurado.`);return}const N=window.open(L,"_blank","noopener,noreferrer");N&&(N.opener=null);const r=o.user.id,y=d.recentByUser[r]??[],j=[U.id,...y.filter(M=>M!==U.id)].slice(0,30);g(M=>({...M,recentByUser:{...M.recentByUser,[r]:j},updatedAt:new Date().toISOString()})),Fv(r,U.id).catch(M=>console.warn("No se guardó el acceso reciente:",M))},we=async(U,L)=>{if(!o||o.user.role!=="admin")return null;const N=L?d.apps.find(r=>r.id===L)??null:null;try{const r=await pm(U,N,o.user.id);return g(y=>({...y,apps:N?y.apps.map(j=>j.id===r.id?r:j):[r,...y.apps],updatedAt:new Date().toISOString()})),k("success",N?"Cambios guardados":"Aplicación publicada",`${r.name} ya está disponible en el catálogo compartido.`),r}catch(r){return k("error","No se guardó la aplicación",r instanceof Error?r.message:void 0),null}},tt=async U=>{if(!o||o.user.role!=="admin")return!1;const L=d.apps.find(N=>N.id===U);if(!L)return!1;try{await $v(L);const N=r=>Object.fromEntries(Object.entries(r).map(([y,j])=>[y,j.filter(M=>M!==U)]));return g(r=>({...r,apps:r.apps.filter(y=>y.id!==U),favoritesByUser:N(r.favoritesByUser),recentByUser:N(r.recentByUser),updatedAt:new Date().toISOString()})),k("success","Aplicación eliminada",`${L.name} salió del catálogo compartido.`),!0}catch(N){return k("error","No se eliminó la aplicación",N instanceof Error?N.message:void 0),!1}},Ke=async U=>{if(!o||o.user.role==="admin")return!1;if(!lm)return k("error","No se pudo enviar la solicitud","La función de solicitudes no está disponible en este momento."),!1;const L=new AbortController,N=window.setTimeout(()=>L.abort(),12e4);try{const{data:{session:r}}=await Ue.auth.getSession();if(!(r!=null&&r.access_token))throw new Error("La sesión venció. Cierra sesión e inicia nuevamente.");const y=await fetch(lm,{method:"POST",mode:"cors",cache:"no-store",credentials:"omit",signal:L.signal,headers:{Accept:"application/json, text/plain;q=0.9","Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify({accessToken:r.access_token,appId:U.id})}),j=await y.text();let M=null;if(j)try{M=JSON.parse(j)}catch{M=null}if(!y.ok||!(M!=null&&M.ok)){const G=String((M==null?void 0:M.error)||"").toLowerCase();let X="No pudimos enviar la solicitud en este momento. Intenta nuevamente.";throw G.includes("pendiente")?X="Ya tienes una solicitud pendiente para esta aplicación.":G.includes("sesión")||y.status===401?X="Tu sesión venció. Cierra sesión e inicia nuevamente.":G.includes("ya no está publicada")||G.includes("no está disponible")?X="La aplicación seleccionada ya no está disponible.":(G.includes("no está autorizado")||y.status===403)&&(X="Tu cuenta no está habilitada para enviar esta solicitud."),console.error("Error interno al enviar la solicitud de acceso",{status:y.status,responseText:j}),new Error(X)}return k("success","Solicitud enviada",M.message||`La solicitud para ${U.name} fue enviada correctamente.`),!0}catch(r){return r instanceof DOMException&&r.name==="AbortError"?k("error","La solicitud tardó demasiado","Intenta nuevamente en unos minutos."):r instanceof TypeError&&/failed to fetch/i.test(r.message)?(console.error("No se pudo contactar el servicio de solicitudes",r),k("error","No se pudo enviar la solicitud","Intenta nuevamente en unos minutos.")):k("error","No se pudo enviar la solicitud",r instanceof Error?r.message:"Intenta nuevamente en unos minutos."),!1}finally{window.clearTimeout(N)}},z=async()=>{Ae("");const{error:U}=await Ue.auth.signInWithOAuth({provider:"google",options:{redirectTo:t0(),queryParams:{hd:"gomezleemarketing.com",prompt:"select_account"}}});U&&(console.error("No se pudo iniciar el acceso con Google:",U),Ae("No pudimos abrir el acceso con Google. Intenta nuevamente."))},R=async()=>{const{error:U}=await Ue.auth.signOut();if(U){k("error","No se pudo cerrar la sesión",U.message);return}O(null),$(!1),K({}),Me(!1),C("hub"),window.history.replaceState(null,"",Ns())};return!E||!o?c.jsxs(c.Fragment,{children:[c.jsx(s0,{onLogin:z,error:ge,disabled:!E}),c.jsx(Ts,{messages:Z,onDismiss:F})]}):B?c.jsxs("div",{className:"app-shell",children:[c.jsx(f0,{user:o.user,view:A,onNavigate:Ne,onLogout:R}),c.jsx(r0,{user:o.user}),A==="admin"&&o.user.role==="admin"?c.jsx(S0,{data:d,onSave:we,onDelete:tt,onBack:()=>Ne("hub")}):c.jsx(g0,{user:o.user,data:d,accessByApp:P,accessReady:le,storageWarning:de,onActivate:je,onFavorite:U=>void he(U),onAdmin:()=>Ne("admin"),onRequestAccess:Ke}),c.jsx(o0,{user:o.user,view:A,onNavigate:Ne,onLogout:R}),c.jsx(Ts,{messages:Z,onDismiss:F})]}):c.jsxs(c.Fragment,{children:[c.jsx(_0,{}),c.jsx(Ts,{messages:Z,onDismiss:F})]})}const um="https://dbit.digitalcompass.agency/storage/v1/object/public/public-assets/GLM.png?v=glm-hub-20260722-v3";function A0(){document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]').forEach(g=>{g.remove()});const f=document.createElement("link");f.rel="icon",f.type="image/png",f.sizes="512x512",f.href=um,document.head.appendChild(f);const d=document.createElement("link");d.rel="shortcut icon",d.type="image/png",d.href=um,document.head.appendChild(d)}A0();lv.createRoot(document.getElementById("root")).render(c.jsx(H.StrictMode,{children:c.jsx(E0,{})})); diff --git a/dist/assets/index-Kd6NFVcJ.js b/dist/assets/index-Kd6NFVcJ.js deleted file mode 100644 index 6fcdb6a..0000000 --- a/dist/assets/index-Kd6NFVcJ.js +++ /dev/null @@ -1,179 +0,0 @@ -(function(){const d=document.createElement("link").relList;if(d&&d.supports&&d.supports("modulepreload"))return;for(const O of document.querySelectorAll('link[rel="modulepreload"]'))r(O);new MutationObserver(O=>{for(const z of O)if(z.type==="childList")for(const U of z.addedNodes)U.tagName==="LINK"&&U.rel==="modulepreload"&&r(U)}).observe(document,{childList:!0,subtree:!0});function v(O){const z={};return O.integrity&&(z.integrity=O.integrity),O.referrerPolicy&&(z.referrerPolicy=O.referrerPolicy),O.crossOrigin==="use-credentials"?z.credentials="include":O.crossOrigin==="anonymous"?z.credentials="omit":z.credentials="same-origin",z}function r(O){if(O.ep)return;O.ep=!0;const z=v(O);fetch(O.href,z)}})();var Ss={exports:{}},Tn={};/** - * @license React - * react-jsx-runtime.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Qd;function Ky(){if(Qd)return Tn;Qd=1;var f=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function v(r,O,z){var U=null;if(z!==void 0&&(U=""+z),O.key!==void 0&&(U=""+O.key),"key"in O){z={};for(var V in O)V!=="key"&&(z[V]=O[V])}else z=O;return O=z.ref,{$$typeof:f,type:r,key:U,ref:O!==void 0?O:null,props:z}}return Tn.Fragment=d,Tn.jsx=v,Tn.jsxs=v,Tn}var Xd;function Jy(){return Xd||(Xd=1,Ss.exports=Ky()),Ss.exports}var c=Jy(),_s={exports:{}},P={};/** - * @license React - * react.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var wd;function ky(){if(wd)return P;wd=1;var f=Symbol.for("react.transitional.element"),d=Symbol.for("react.portal"),v=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),O=Symbol.for("react.profiler"),z=Symbol.for("react.consumer"),U=Symbol.for("react.context"),V=Symbol.for("react.forward_ref"),q=Symbol.for("react.suspense"),E=Symbol.for("react.memo"),G=Symbol.for("react.lazy"),B=Symbol.for("react.activity"),J=Symbol.iterator;function ye(o){return o===null||typeof o!="object"?null:(o=J&&o[J]||o["@@iterator"],typeof o=="function"?o:null)}var w={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},ee=Object.assign,Z={};function te(o,A,R){this.props=o,this.context=A,this.refs=Z,this.updater=R||w}te.prototype.isReactComponent={},te.prototype.setState=function(o,A){if(typeof o!="object"&&typeof o!="function"&&o!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,o,A,"setState")},te.prototype.forceUpdate=function(o){this.updater.enqueueForceUpdate(this,o,"forceUpdate")};function Ne(){}Ne.prototype=te.prototype;function Te(o,A,R){this.props=o,this.context=A,this.refs=Z,this.updater=R||w}var se=Te.prototype=new Ne;se.constructor=Te,ee(se,te.prototype),se.isPureReactComponent=!0;var pe=Array.isArray;function Ae(){}var I={H:null,A:null,T:null,S:null},ne=Object.prototype.hasOwnProperty;function Me(o,A,R){var L=R.ref;return{$$typeof:f,type:o,key:A,ref:L!==void 0?L:null,props:R}}function Ue(o,A){return Me(o.type,A,o.props)}function ve(o){return typeof o=="object"&&o!==null&&o.$$typeof===f}function He(o){var A={"=":"=0",":":"=2"};return"$"+o.replace(/[=:]/g,function(R){return A[R]})}var lt=/\/+/g;function Y(o,A){return typeof o=="object"&&o!==null&&o.key!=null?He(""+o.key):A.toString(36)}function k(o){switch(o.status){case"fulfilled":return o.value;case"rejected":throw o.reason;default:switch(typeof o.status=="string"?o.then(Ae,Ae):(o.status="pending",o.then(function(A){o.status==="pending"&&(o.status="fulfilled",o.value=A)},function(A){o.status==="pending"&&(o.status="rejected",o.reason=A)})),o.status){case"fulfilled":return o.value;case"rejected":throw o.reason}}throw o}function S(o,A,R,L,F){var $=typeof o;($==="undefined"||$==="boolean")&&(o=null);var ue=!1;if(o===null)ue=!0;else switch($){case"bigint":case"string":case"number":ue=!0;break;case"object":switch(o.$$typeof){case f:case d:ue=!0;break;case G:return ue=o._init,S(ue(o._payload),A,R,L,F)}}if(ue)return F=F(o),ue=L===""?"."+Y(o,0):L,pe(F)?(R="",ue!=null&&(R=ue.replace(lt,"$&/")+"/"),S(F,A,R,"",function(Pe){return Pe})):F!=null&&(ve(F)&&(F=Ue(F,R+(F.key==null||o&&o.key===F.key?"":(""+F.key).replace(lt,"$&/")+"/")+ue)),A.push(F)),1;ue=0;var Je=L===""?".":L+":";if(pe(o))for(var je=0;je>>1,b=S[D];if(0>>1;DO(R,C))LO(F,R)?(S[D]=F,S[L]=C,D=L):(S[D]=R,S[A]=C,D=A);else if(LO(F,C))S[D]=F,S[L]=C,D=L;else break e}}return T}function O(S,T){var C=S.sortIndex-T.sortIndex;return C!==0?C:S.id-T.id}if(f.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var z=performance;f.unstable_now=function(){return z.now()}}else{var U=Date,V=U.now();f.unstable_now=function(){return U.now()-V}}var q=[],E=[],G=1,B=null,J=3,ye=!1,w=!1,ee=!1,Z=!1,te=typeof setTimeout=="function"?setTimeout:null,Ne=typeof clearTimeout=="function"?clearTimeout:null,Te=typeof setImmediate<"u"?setImmediate:null;function se(S){for(var T=v(E);T!==null;){if(T.callback===null)r(E);else if(T.startTime<=S)r(E),T.sortIndex=T.expirationTime,d(q,T);else break;T=v(E)}}function pe(S){if(ee=!1,se(S),!w)if(v(q)!==null)w=!0,Ae||(Ae=!0,He());else{var T=v(E);T!==null&&k(pe,T.startTime-S)}}var Ae=!1,I=-1,ne=5,Me=-1;function Ue(){return Z?!0:!(f.unstable_now()-MeS&&Ue());){var D=B.callback;if(typeof D=="function"){B.callback=null,J=B.priorityLevel;var b=D(B.expirationTime<=S);if(S=f.unstable_now(),typeof b=="function"){B.callback=b,se(S),T=!0;break t}B===v(q)&&r(q),se(S)}else r(q);B=v(q)}if(B!==null)T=!0;else{var o=v(E);o!==null&&k(pe,o.startTime-S),T=!1}}break e}finally{B=null,J=C,ye=!1}T=void 0}}finally{T?He():Ae=!1}}}var He;if(typeof Te=="function")He=function(){Te(ve)};else if(typeof MessageChannel<"u"){var lt=new MessageChannel,Y=lt.port2;lt.port1.onmessage=ve,He=function(){Y.postMessage(null)}}else He=function(){te(ve,0)};function k(S,T){I=te(function(){S(f.unstable_now())},T)}f.unstable_IdlePriority=5,f.unstable_ImmediatePriority=1,f.unstable_LowPriority=4,f.unstable_NormalPriority=3,f.unstable_Profiling=null,f.unstable_UserBlockingPriority=2,f.unstable_cancelCallback=function(S){S.callback=null},f.unstable_forceFrameRate=function(S){0>S||125D?(S.sortIndex=C,d(E,S),v(q)===null&&S===v(E)&&(ee?(Ne(I),I=-1):ee=!0,k(pe,C-D))):(S.sortIndex=b,d(q,S),w||ye||(w=!0,Ae||(Ae=!0,He()))),S},f.unstable_shouldYield=Ue,f.unstable_wrapCallback=function(S){var T=J;return function(){var C=J;J=T;try{return S.apply(this,arguments)}finally{J=C}}}})(js)),js}var Kd;function Wy(){return Kd||(Kd=1,As.exports=$y()),As.exports}var zs={exports:{}},et={};/** - * @license React - * react-dom.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Jd;function Fy(){if(Jd)return et;Jd=1;var f=qs();function d(q){var E="https://react.dev/errors/"+q;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(d){console.error(d)}}return f(),zs.exports=Fy(),zs.exports}/** - * @license React - * react-dom-client.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var $d;function Py(){if($d)return xn;$d=1;var f=Wy(),d=qs(),v=Iy();function r(e){var t="https://react.dev/errors/"+e;if(1b||(e.current=D[b],D[b]=null,b--)}function R(e,t){b++,D[b]=e.current,e.current=t}var L=o(null),F=o(null),$=o(null),ue=o(null);function Je(e,t){switch(R($,t),R(F,e),R(L,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?rd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=rd(t),e=od(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}A(L),R(L,e)}function je(){A(L),A(F),A($)}function Pe(e){e.memoizedState!==null&&R(ue,e);var t=L.current,l=od(t,e.type);t!==l&&(R(F,e),R(L,l))}function tl(e){F.current===e&&(A(L),A(F)),ue.current===e&&(A(ue),An._currentValue=C)}var li,Ls;function Tl(e){if(li===void 0)try{throw Error()}catch(l){var t=l.stack.trim().match(/\n( *(at )?)/);li=t&&t[1]||"",Ls=-1)":-1n||m[a]!==p[n]){var N=` -`+m[a].replace(" at new "," at ");return e.displayName&&N.includes("")&&(N=N.replace("",e.displayName)),N}while(1<=a&&0<=n);break}}}finally{ai=!1,Error.prepareStackTrace=l}return(l=e?e.displayName||e.name:"")?Tl(l):""}function Am(e,t){switch(e.tag){case 26:case 27:case 5:return Tl(e.type);case 16:return Tl("Lazy");case 13:return e.child!==t&&t!==null?Tl("Suspense Fallback"):Tl("Suspense");case 19:return Tl("SuspenseList");case 0:case 15:return ni(e.type,!1);case 11:return ni(e.type.render,!1);case 1:return ni(e.type,!0);case 31:return Tl("Activity");default:return""}}function Gs(e){try{var t="",l=null;do t+=Am(e,l),l=e,e=e.return;while(e);return t}catch(a){return` -Error generating stack: `+a.message+` -`+a.stack}}var ui=Object.prototype.hasOwnProperty,ii=f.unstable_scheduleCallback,ci=f.unstable_cancelCallback,jm=f.unstable_shouldYield,zm=f.unstable_requestPaint,rt=f.unstable_now,Nm=f.unstable_getCurrentPriorityLevel,Ys=f.unstable_ImmediatePriority,Qs=f.unstable_UserBlockingPriority,Cn=f.unstable_NormalPriority,Tm=f.unstable_LowPriority,Xs=f.unstable_IdlePriority,xm=f.log,Om=f.unstable_setDisableYieldValue,Ra=null,ot=null;function ll(e){if(typeof xm=="function"&&Om(e),ot&&typeof ot.setStrictMode=="function")try{ot.setStrictMode(Ra,e)}catch{}}var dt=Math.clz32?Math.clz32:Um,Dm=Math.log,Mm=Math.LN2;function Um(e){return e>>>=0,e===0?32:31-(Dm(e)/Mm|0)|0}var Rn=256,qn=262144,Hn=4194304;function xl(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Bn(e,t,l){var a=e.pendingLanes;if(a===0)return 0;var n=0,u=e.suspendedLanes,i=e.pingedLanes;e=e.warmLanes;var s=a&134217727;return s!==0?(a=s&~u,a!==0?n=xl(a):(i&=s,i!==0?n=xl(i):l||(l=s&~e,l!==0&&(n=xl(l))))):(s=a&~u,s!==0?n=xl(s):i!==0?n=xl(i):l||(l=a&~e,l!==0&&(n=xl(l)))),n===0?0:t!==0&&t!==n&&(t&u)===0&&(u=n&-n,l=t&-t,u>=l||u===32&&(l&4194048)!==0)?t:n}function qa(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Cm(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ws(){var e=Hn;return Hn<<=1,(Hn&62914560)===0&&(Hn=4194304),e}function si(e){for(var t=[],l=0;31>l;l++)t.push(e);return t}function Ha(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Rm(e,t,l,a,n,u){var i=e.pendingLanes;e.pendingLanes=l,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=l,e.entangledLanes&=l,e.errorRecoveryDisabledLanes&=l,e.shellSuspendCounter=0;var s=e.entanglements,m=e.expirationTimes,p=e.hiddenUpdates;for(l=i&~l;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var Ym=/[\n"\\]/g;function _t(e){return e.replace(Ym,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function hi(e,t,l,a,n,u,i,s){e.name="",i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"?e.type=i:e.removeAttribute("type"),t!=null?i==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+St(t)):e.value!==""+St(t)&&(e.value=""+St(t)):i!=="submit"&&i!=="reset"||e.removeAttribute("value"),t!=null?yi(e,i,St(t)):l!=null?yi(e,i,St(l)):a!=null&&e.removeAttribute("value"),n==null&&u!=null&&(e.defaultChecked=!!u),n!=null&&(e.checked=n&&typeof n!="function"&&typeof n!="symbol"),s!=null&&typeof s!="function"&&typeof s!="symbol"&&typeof s!="boolean"?e.name=""+St(s):e.removeAttribute("name")}function lf(e,t,l,a,n,u,i,s){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||l!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){mi(e);return}l=l!=null?""+St(l):"",t=t!=null?""+St(t):l,s||t===e.value||(e.value=t),e.defaultValue=t}a=a??n,a=typeof a!="function"&&typeof a!="symbol"&&!!a,e.checked=s?e.checked:!!a,e.defaultChecked=!!a,i!=null&&typeof i!="function"&&typeof i!="symbol"&&typeof i!="boolean"&&(e.name=i),mi(e)}function yi(e,t,l){t==="number"&&Yn(e.ownerDocument)===e||e.defaultValue===""+l||(e.defaultValue=""+l)}function ea(e,t,l,a){if(e=e.options,t){t={};for(var n=0;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Si=!1;if(Gt)try{var Ya={};Object.defineProperty(Ya,"passive",{get:function(){Si=!0}}),window.addEventListener("test",Ya,Ya),window.removeEventListener("test",Ya,Ya)}catch{Si=!1}var nl=null,_i=null,Xn=null;function rf(){if(Xn)return Xn;var e,t=_i,l=t.length,a,n="value"in nl?nl.value:nl.textContent,u=n.length;for(e=0;e=wa),vf=" ",gf=!1;function bf(e,t){switch(e){case"keyup":return hh.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function pf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var na=!1;function vh(e,t){switch(e){case"compositionend":return pf(t);case"keypress":return t.which!==32?null:(gf=!0,vf);case"textInput":return e=t.data,e===vf&&gf?null:e;default:return null}}function gh(e,t){if(na)return e==="compositionend"||!Ni&&bf(e,t)?(e=rf(),Xn=_i=nl=null,na=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:l,offset:t-e};e=a}e:{for(;l;){if(l.nextSibling){l=l.nextSibling;break e}l=l.parentNode}l=void 0}l=Tf(l)}}function Of(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Of(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Df(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Yn(e.document);t instanceof e.HTMLIFrameElement;){try{var l=typeof t.contentWindow.location.href=="string"}catch{l=!1}if(l)e=t.contentWindow;else break;t=Yn(e.document)}return t}function Oi(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var zh=Gt&&"documentMode"in document&&11>=document.documentMode,ua=null,Di=null,Ja=null,Mi=!1;function Mf(e,t,l){var a=l.window===l?l.document:l.nodeType===9?l:l.ownerDocument;Mi||ua==null||ua!==Yn(a)||(a=ua,"selectionStart"in a&&Oi(a)?a={start:a.selectionStart,end:a.selectionEnd}:(a=(a.ownerDocument&&a.ownerDocument.defaultView||window).getSelection(),a={anchorNode:a.anchorNode,anchorOffset:a.anchorOffset,focusNode:a.focusNode,focusOffset:a.focusOffset}),Ja&&Ka(Ja,a)||(Ja=a,a=qu(Di,"onSelect"),0>=i,n-=i,Ct=1<<32-dt(t)+n|l<ae?(re=X,X=null):re=X.sibling;var me=_(y,X,g[ae],x);if(me===null){X===null&&(X=re);break}e&&X&&me.alternate===null&&t(y,X),h=u(me,h,ae),de===null?K=me:de.sibling=me,de=me,X=re}if(ae===g.length)return l(y,X),oe&&Qt(y,ae),K;if(X===null){for(;aeae?(re=X,X=null):re=X.sibling;var Nl=_(y,X,me.value,x);if(Nl===null){X===null&&(X=re);break}e&&X&&Nl.alternate===null&&t(y,X),h=u(Nl,h,ae),de===null?K=Nl:de.sibling=Nl,de=Nl,X=re}if(me.done)return l(y,X),oe&&Qt(y,ae),K;if(X===null){for(;!me.done;ae++,me=g.next())me=M(y,me.value,x),me!==null&&(h=u(me,h,ae),de===null?K=me:de.sibling=me,de=me);return oe&&Qt(y,ae),K}for(X=a(X);!me.done;ae++,me=g.next())me=j(X,y,ae,me.value,x),me!==null&&(e&&me.alternate!==null&&X.delete(me.key===null?ae:me.key),h=u(me,h,ae),de===null?K=me:de.sibling=me,de=me);return e&&X.forEach(function(Vy){return t(y,Vy)}),oe&&Qt(y,ae),K}function Ee(y,h,g,x){if(typeof g=="object"&&g!==null&&g.type===ee&&g.key===null&&(g=g.props.children),typeof g=="object"&&g!==null){switch(g.$$typeof){case ye:e:{for(var K=g.key;h!==null;){if(h.key===K){if(K=g.type,K===ee){if(h.tag===7){l(y,h.sibling),x=n(h,g.props.children),x.return=y,y=x;break e}}else if(h.elementType===K||typeof K=="object"&&K!==null&&K.$$typeof===ne&&Gl(K)===h.type){l(y,h.sibling),x=n(h,g.props),Pa(x,g),x.return=y,y=x;break e}l(y,h);break}else t(y,h);h=h.sibling}g.type===ee?(x=Rl(g.props.children,y.mode,x,g.key),x.return=y,y=x):(x=In(g.type,g.key,g.props,null,y.mode,x),Pa(x,g),x.return=y,y=x)}return i(y);case w:e:{for(K=g.key;h!==null;){if(h.key===K)if(h.tag===4&&h.stateNode.containerInfo===g.containerInfo&&h.stateNode.implementation===g.implementation){l(y,h.sibling),x=n(h,g.children||[]),x.return=y,y=x;break e}else{l(y,h);break}else t(y,h);h=h.sibling}x=Li(g,y.mode,x),x.return=y,y=x}return i(y);case ne:return g=Gl(g),Ee(y,h,g,x)}if(k(g))return Q(y,h,g,x);if(He(g)){if(K=He(g),typeof K!="function")throw Error(r(150));return g=K.call(g),W(y,h,g,x)}if(typeof g.then=="function")return Ee(y,h,uu(g),x);if(g.$$typeof===Te)return Ee(y,h,tu(y,g),x);iu(y,g)}return typeof g=="string"&&g!==""||typeof g=="number"||typeof g=="bigint"?(g=""+g,h!==null&&h.tag===6?(l(y,h.sibling),x=n(h,g),x.return=y,y=x):(l(y,h),x=Bi(g,y.mode,x),x.return=y,y=x),i(y)):l(y,h)}return function(y,h,g,x){try{Ia=0;var K=Ee(y,h,g,x);return va=null,K}catch(X){if(X===ya||X===au)throw X;var de=ht(29,X,null,y.mode);return de.lanes=x,de.return=y,de}finally{}}}var Ql=er(!0),tr=er(!1),fl=!1;function Wi(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Fi(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function rl(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function ol(e,t,l){var a=e.updateQueue;if(a===null)return null;if(a=a.shared,(he&2)!==0){var n=a.pending;return n===null?t.next=t:(t.next=n.next,n.next=t),a.pending=t,t=Fn(e),Lf(e,null,l),t}return Wn(e,a,t,l),Fn(e)}function en(e,t,l){if(t=t.updateQueue,t!==null&&(t=t.shared,(l&4194048)!==0)){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Vs(e,l)}}function Ii(e,t){var l=e.updateQueue,a=e.alternate;if(a!==null&&(a=a.updateQueue,l===a)){var n=null,u=null;if(l=l.firstBaseUpdate,l!==null){do{var i={lane:l.lane,tag:l.tag,payload:l.payload,callback:null,next:null};u===null?n=u=i:u=u.next=i,l=l.next}while(l!==null);u===null?n=u=t:u=u.next=t}else n=u=t;l={baseState:a.baseState,firstBaseUpdate:n,lastBaseUpdate:u,shared:a.shared,callbacks:a.callbacks},e.updateQueue=l;return}e=l.lastBaseUpdate,e===null?l.firstBaseUpdate=t:e.next=t,l.lastBaseUpdate=t}var Pi=!1;function tn(){if(Pi){var e=ha;if(e!==null)throw e}}function ln(e,t,l,a){Pi=!1;var n=e.updateQueue;fl=!1;var u=n.firstBaseUpdate,i=n.lastBaseUpdate,s=n.shared.pending;if(s!==null){n.shared.pending=null;var m=s,p=m.next;m.next=null,i===null?u=p:i.next=p,i=m;var N=e.alternate;N!==null&&(N=N.updateQueue,s=N.lastBaseUpdate,s!==i&&(s===null?N.firstBaseUpdate=p:s.next=p,N.lastBaseUpdate=m))}if(u!==null){var M=n.baseState;i=0,N=p=m=null,s=u;do{var _=s.lane&-536870913,j=_!==s.lane;if(j?(fe&_)===_:(a&_)===_){_!==0&&_===ma&&(Pi=!0),N!==null&&(N=N.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});e:{var Q=e,W=s;_=t;var Ee=l;switch(W.tag){case 1:if(Q=W.payload,typeof Q=="function"){M=Q.call(Ee,M,_);break e}M=Q;break e;case 3:Q.flags=Q.flags&-65537|128;case 0:if(Q=W.payload,_=typeof Q=="function"?Q.call(Ee,M,_):Q,_==null)break e;M=B({},M,_);break e;case 2:fl=!0}}_=s.callback,_!==null&&(e.flags|=64,j&&(e.flags|=8192),j=n.callbacks,j===null?n.callbacks=[_]:j.push(_))}else j={lane:_,tag:s.tag,payload:s.payload,callback:s.callback,next:null},N===null?(p=N=j,m=M):N=N.next=j,i|=_;if(s=s.next,s===null){if(s=n.shared.pending,s===null)break;j=s,s=j.next,j.next=null,n.lastBaseUpdate=j,n.shared.pending=null}}while(!0);N===null&&(m=M),n.baseState=m,n.firstBaseUpdate=p,n.lastBaseUpdate=N,u===null&&(n.shared.lanes=0),vl|=i,e.lanes=i,e.memoizedState=M}}function lr(e,t){if(typeof e!="function")throw Error(r(191,e));e.call(t)}function ar(e,t){var l=e.callbacks;if(l!==null)for(e.callbacks=null,e=0;eu?u:8;var i=S.T,s={};S.T=s,bc(e,!1,t,l);try{var m=n(),p=S.S;if(p!==null&&p(s,m),m!==null&&typeof m=="object"&&typeof m.then=="function"){var N=Rh(m,a);un(e,t,N,pt(e))}else un(e,t,a,pt(e))}catch(M){un(e,t,{then:function(){},status:"rejected",reason:M},pt())}finally{T.p=u,i!==null&&s.types!==null&&(i.types=s.types),S.T=i}}function Yh(){}function vc(e,t,l,a){if(e.tag!==5)throw Error(r(476));var n=qr(e).queue;Rr(e,n,t,C,l===null?Yh:function(){return Hr(e),l(a)})}function qr(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:C,baseState:C,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Vt,lastRenderedState:C},next:null};var l={};return t.next={memoizedState:l,baseState:l,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Vt,lastRenderedState:l},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Hr(e){var t=qr(e);t.next===null&&(t=e.alternate.memoizedState),un(e,t.next.queue,{},pt())}function gc(){return We(An)}function Br(){return Le().memoizedState}function Lr(){return Le().memoizedState}function Qh(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var l=pt();e=rl(l);var a=ol(t,e,l);a!==null&&(ft(a,t,l),en(a,t,l)),t={cache:Ki()},e.payload=t;return}t=t.return}}function Xh(e,t,l){var a=pt();l={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null},vu(e)?Yr(t,l):(l=qi(e,t,l,a),l!==null&&(ft(l,e,a),Qr(l,t,a)))}function Gr(e,t,l){var a=pt();un(e,t,l,a)}function un(e,t,l,a){var n={lane:a,revertLane:0,gesture:null,action:l,hasEagerState:!1,eagerState:null,next:null};if(vu(e))Yr(t,n);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var i=t.lastRenderedState,s=u(i,l);if(n.hasEagerState=!0,n.eagerState=s,mt(s,i))return Wn(e,t,n,0),ze===null&&$n(),!1}catch{}finally{}if(l=qi(e,t,n,a),l!==null)return ft(l,e,a),Qr(l,t,a),!0}return!1}function bc(e,t,l,a){if(a={lane:2,revertLane:Wc(),gesture:null,action:a,hasEagerState:!1,eagerState:null,next:null},vu(e)){if(t)throw Error(r(479))}else t=qi(e,l,a,2),t!==null&&ft(t,e,2)}function vu(e){var t=e.alternate;return e===le||t!==null&&t===le}function Yr(e,t){ba=fu=!0;var l=e.pending;l===null?t.next=t:(t.next=l.next,l.next=t),e.pending=t}function Qr(e,t,l){if((l&4194048)!==0){var a=t.lanes;a&=e.pendingLanes,l|=a,t.lanes=l,Vs(e,l)}}var cn={readContext:We,use:du,useCallback:Ce,useContext:Ce,useEffect:Ce,useImperativeHandle:Ce,useLayoutEffect:Ce,useInsertionEffect:Ce,useMemo:Ce,useReducer:Ce,useRef:Ce,useState:Ce,useDebugValue:Ce,useDeferredValue:Ce,useTransition:Ce,useSyncExternalStore:Ce,useId:Ce,useHostTransitionStatus:Ce,useFormState:Ce,useActionState:Ce,useOptimistic:Ce,useMemoCache:Ce,useCacheRefresh:Ce};cn.useEffectEvent=Ce;var Xr={readContext:We,use:du,useCallback:function(e,t){return tt().memoizedState=[e,t===void 0?null:t],e},useContext:We,useEffect:zr,useImperativeHandle:function(e,t,l){l=l!=null?l.concat([e]):null,hu(4194308,4,Or.bind(null,t,e),l)},useLayoutEffect:function(e,t){return hu(4194308,4,e,t)},useInsertionEffect:function(e,t){hu(4,2,e,t)},useMemo:function(e,t){var l=tt();t=t===void 0?null:t;var a=e();if(Xl){ll(!0);try{e()}finally{ll(!1)}}return l.memoizedState=[a,t],a},useReducer:function(e,t,l){var a=tt();if(l!==void 0){var n=l(t);if(Xl){ll(!0);try{l(t)}finally{ll(!1)}}}else n=t;return a.memoizedState=a.baseState=n,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},a.queue=e,e=e.dispatch=Xh.bind(null,le,e),[a.memoizedState,e]},useRef:function(e){var t=tt();return e={current:e},t.memoizedState=e},useState:function(e){e=oc(e);var t=e.queue,l=Gr.bind(null,le,t);return t.dispatch=l,[e.memoizedState,l]},useDebugValue:hc,useDeferredValue:function(e,t){var l=tt();return yc(l,e,t)},useTransition:function(){var e=oc(!1);return e=Rr.bind(null,le,e.queue,!0,!1),tt().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,l){var a=le,n=tt();if(oe){if(l===void 0)throw Error(r(407));l=l()}else{if(l=t(),ze===null)throw Error(r(349));(fe&127)!==0||fr(a,t,l)}n.memoizedState=l;var u={value:l,getSnapshot:t};return n.queue=u,zr(or.bind(null,a,u,e),[e]),a.flags|=2048,Sa(9,{destroy:void 0},rr.bind(null,a,u,l,t),null),l},useId:function(){var e=tt(),t=ze.identifierPrefix;if(oe){var l=Rt,a=Ct;l=(a&~(1<<32-dt(a)-1)).toString(32)+l,t="_"+t+"R_"+l,l=ru++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof a.is=="string"?i.createElement("select",{is:a.is}):i.createElement("select"),a.multiple?u.multiple=!0:a.size&&(u.size=a.size);break;default:u=typeof a.is=="string"?i.createElement(n,{is:a.is}):i.createElement(n)}}u[ke]=t,u[at]=a;e:for(i=t.child;i!==null;){if(i.tag===5||i.tag===6)u.appendChild(i.stateNode);else if(i.tag!==4&&i.tag!==27&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===t)break e;for(;i.sibling===null;){if(i.return===null||i.return===t)break e;i=i.return}i.sibling.return=i.return,i=i.sibling}t.stateNode=u;e:switch(Ie(u,n,a),n){case"button":case"input":case"select":case"textarea":a=!!a.autoFocus;break e;case"img":a=!0;break e;default:a=!1}a&&Jt(t)}}return Oe(t),Uc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,l),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==a&&Jt(t);else{if(typeof a!="string"&&t.stateNode===null)throw Error(r(166));if(e=$.current,oa(t)){if(e=t.stateNode,l=t.memoizedProps,a=null,n=$e,n!==null)switch(n.tag){case 27:case 5:a=n.memoizedProps}e[ke]=t,e=!!(e.nodeValue===l||a!==null&&a.suppressHydrationWarning===!0||sd(e.nodeValue,l)),e||cl(t,!0)}else e=Hu(e).createTextNode(a),e[ke]=t,t.stateNode=e}return Oe(t),null;case 31:if(l=t.memoizedState,e===null||e.memoizedState!==null){if(a=oa(t),l!==null){if(e===null){if(!a)throw Error(r(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(r(557));e[ke]=t}else ql(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Oe(t),e=!1}else l=Xi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=l),e=!0;if(!e)return t.flags&256?(vt(t),t):(vt(t),null);if((t.flags&128)!==0)throw Error(r(558))}return Oe(t),null;case 13:if(a=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(n=oa(t),a!==null&&a.dehydrated!==null){if(e===null){if(!n)throw Error(r(318));if(n=t.memoizedState,n=n!==null?n.dehydrated:null,!n)throw Error(r(317));n[ke]=t}else ql(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Oe(t),n=!1}else n=Xi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),n=!0;if(!n)return t.flags&256?(vt(t),t):(vt(t),null)}return vt(t),(t.flags&128)!==0?(t.lanes=l,t):(l=a!==null,e=e!==null&&e.memoizedState!==null,l&&(a=t.child,n=null,a.alternate!==null&&a.alternate.memoizedState!==null&&a.alternate.memoizedState.cachePool!==null&&(n=a.alternate.memoizedState.cachePool.pool),u=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(u=a.memoizedState.cachePool.pool),u!==n&&(a.flags|=2048)),l!==e&&l&&(t.child.flags|=8192),_u(t,t.updateQueue),Oe(t),null);case 4:return je(),e===null&&es(t.stateNode.containerInfo),Oe(t),null;case 10:return wt(t.type),Oe(t),null;case 19:if(A(Be),a=t.memoizedState,a===null)return Oe(t),null;if(n=(t.flags&128)!==0,u=a.rendering,u===null)if(n)fn(a,!1);else{if(Re!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=su(e),u!==null){for(t.flags|=128,fn(a,!1),e=u.updateQueue,t.updateQueue=e,_u(t,e),t.subtreeFlags=0,e=l,l=t.child;l!==null;)Gf(l,e),l=l.sibling;return R(Be,Be.current&1|2),oe&&Qt(t,a.treeForkCount),t.child}e=e.sibling}a.tail!==null&&rt()>Nu&&(t.flags|=128,n=!0,fn(a,!1),t.lanes=4194304)}else{if(!n)if(e=su(u),e!==null){if(t.flags|=128,n=!0,e=e.updateQueue,t.updateQueue=e,_u(t,e),fn(a,!0),a.tail===null&&a.tailMode==="hidden"&&!u.alternate&&!oe)return Oe(t),null}else 2*rt()-a.renderingStartTime>Nu&&l!==536870912&&(t.flags|=128,n=!0,fn(a,!1),t.lanes=4194304);a.isBackwards?(u.sibling=t.child,t.child=u):(e=a.last,e!==null?e.sibling=u:t.child=u,a.last=u)}return a.tail!==null?(e=a.tail,a.rendering=e,a.tail=e.sibling,a.renderingStartTime=rt(),e.sibling=null,l=Be.current,R(Be,n?l&1|2:l&1),oe&&Qt(t,a.treeForkCount),e):(Oe(t),null);case 22:case 23:return vt(t),tc(),a=t.memoizedState!==null,e!==null?e.memoizedState!==null!==a&&(t.flags|=8192):a&&(t.flags|=8192),a?(l&536870912)!==0&&(t.flags&128)===0&&(Oe(t),t.subtreeFlags&6&&(t.flags|=8192)):Oe(t),l=t.updateQueue,l!==null&&_u(t,l.retryQueue),l=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(l=e.memoizedState.cachePool.pool),a=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(a=t.memoizedState.cachePool.pool),a!==l&&(t.flags|=2048),e!==null&&A(Ll),null;case 24:return l=null,e!==null&&(l=e.memoizedState.cache),t.memoizedState.cache!==l&&(t.flags|=2048),wt(Ge),Oe(t),null;case 25:return null;case 30:return null}throw Error(r(156,t.tag))}function Jh(e,t){switch(Yi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return wt(Ge),je(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return tl(t),null;case 31:if(t.memoizedState!==null){if(vt(t),t.alternate===null)throw Error(r(340));ql()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(vt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(r(340));ql()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return A(Be),null;case 4:return je(),null;case 10:return wt(t.type),null;case 22:case 23:return vt(t),tc(),e!==null&&A(Ll),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return wt(Ge),null;case 25:return null;default:return null}}function mo(e,t){switch(Yi(t),t.tag){case 3:wt(Ge),je();break;case 26:case 27:case 5:tl(t);break;case 4:je();break;case 31:t.memoizedState!==null&&vt(t);break;case 13:vt(t);break;case 19:A(Be);break;case 10:wt(t.type);break;case 22:case 23:vt(t),tc(),e!==null&&A(Ll);break;case 24:wt(Ge)}}function rn(e,t){try{var l=t.updateQueue,a=l!==null?l.lastEffect:null;if(a!==null){var n=a.next;l=n;do{if((l.tag&e)===e){a=void 0;var u=l.create,i=l.inst;a=u(),i.destroy=a}l=l.next}while(l!==n)}}catch(s){be(t,t.return,s)}}function hl(e,t,l){try{var a=t.updateQueue,n=a!==null?a.lastEffect:null;if(n!==null){var u=n.next;a=u;do{if((a.tag&e)===e){var i=a.inst,s=i.destroy;if(s!==void 0){i.destroy=void 0,n=t;var m=l,p=s;try{p()}catch(N){be(n,m,N)}}}a=a.next}while(a!==u)}}catch(N){be(t,t.return,N)}}function ho(e){var t=e.updateQueue;if(t!==null){var l=e.stateNode;try{ar(t,l)}catch(a){be(e,e.return,a)}}}function yo(e,t,l){l.props=wl(e.type,e.memoizedProps),l.state=e.memoizedState;try{l.componentWillUnmount()}catch(a){be(e,t,a)}}function on(e,t){try{var l=e.ref;if(l!==null){switch(e.tag){case 26:case 27:case 5:var a=e.stateNode;break;case 30:a=e.stateNode;break;default:a=e.stateNode}typeof l=="function"?e.refCleanup=l(a):l.current=a}}catch(n){be(e,t,n)}}function qt(e,t){var l=e.ref,a=e.refCleanup;if(l!==null)if(typeof a=="function")try{a()}catch(n){be(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof l=="function")try{l(null)}catch(n){be(e,t,n)}else l.current=null}function vo(e){var t=e.type,l=e.memoizedProps,a=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":l.autoFocus&&a.focus();break e;case"img":l.src?a.src=l.src:l.srcSet&&(a.srcset=l.srcSet)}}catch(n){be(e,e.return,n)}}function Cc(e,t,l){try{var a=e.stateNode;yy(a,e.type,l,t),a[at]=t}catch(n){be(e,e.return,n)}}function go(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&_l(e.type)||e.tag===4}function Rc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||go(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&_l(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function qc(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?(l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l).insertBefore(e,t):(t=l.nodeType===9?l.body:l.nodeName==="HTML"?l.ownerDocument.body:l,t.appendChild(e),l=l._reactRootContainer,l!=null||t.onclick!==null||(t.onclick=Lt));else if(a!==4&&(a===27&&_l(e.type)&&(l=e.stateNode,t=null),e=e.child,e!==null))for(qc(e,t,l),e=e.sibling;e!==null;)qc(e,t,l),e=e.sibling}function Eu(e,t,l){var a=e.tag;if(a===5||a===6)e=e.stateNode,t?l.insertBefore(e,t):l.appendChild(e);else if(a!==4&&(a===27&&_l(e.type)&&(l=e.stateNode),e=e.child,e!==null))for(Eu(e,t,l),e=e.sibling;e!==null;)Eu(e,t,l),e=e.sibling}function bo(e){var t=e.stateNode,l=e.memoizedProps;try{for(var a=e.type,n=t.attributes;n.length;)t.removeAttributeNode(n[0]);Ie(t,a,l),t[ke]=e,t[at]=l}catch(u){be(e,e.return,u)}}var kt=!1,Xe=!1,Hc=!1,po=typeof WeakSet=="function"?WeakSet:Set,Ve=null;function kh(e,t){if(e=e.containerInfo,as=wu,e=Df(e),Oi(e)){if("selectionStart"in e)var l={start:e.selectionStart,end:e.selectionEnd};else e:{l=(l=e.ownerDocument)&&l.defaultView||window;var a=l.getSelection&&l.getSelection();if(a&&a.rangeCount!==0){l=a.anchorNode;var n=a.anchorOffset,u=a.focusNode;a=a.focusOffset;try{l.nodeType,u.nodeType}catch{l=null;break e}var i=0,s=-1,m=-1,p=0,N=0,M=e,_=null;t:for(;;){for(var j;M!==l||n!==0&&M.nodeType!==3||(s=i+n),M!==u||a!==0&&M.nodeType!==3||(m=i+a),M.nodeType===3&&(i+=M.nodeValue.length),(j=M.firstChild)!==null;)_=M,M=j;for(;;){if(M===e)break t;if(_===l&&++p===n&&(s=i),_===u&&++N===a&&(m=i),(j=M.nextSibling)!==null)break;M=_,_=M.parentNode}M=j}l=s===-1||m===-1?null:{start:s,end:m}}else l=null}l=l||{start:0,end:0}}else l=null;for(ns={focusedElem:e,selectionRange:l},wu=!1,Ve=t;Ve!==null;)if(t=Ve,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Ve=e;else for(;Ve!==null;){switch(t=Ve,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(l=0;l title"))),Ie(u,a,l),u[ke]=e,Ze(u),a=u;break e;case"link":var i=zd("link","href",n).get(a+(l.href||""));if(i){for(var s=0;sEe&&(i=Ee,Ee=W,W=i);var y=xf(s,W),h=xf(s,Ee);if(y&&h&&(j.rangeCount!==1||j.anchorNode!==y.node||j.anchorOffset!==y.offset||j.focusNode!==h.node||j.focusOffset!==h.offset)){var g=M.createRange();g.setStart(y.node,y.offset),j.removeAllRanges(),W>Ee?(j.addRange(g),j.extend(h.node,h.offset)):(g.setEnd(h.node,h.offset),j.addRange(g))}}}}for(M=[],j=s;j=j.parentNode;)j.nodeType===1&&M.push({element:j,left:j.scrollLeft,top:j.scrollTop});for(typeof s.focus=="function"&&s.focus(),s=0;sl?32:l,S.T=null,l=wc,wc=null;var u=bl,i=Pt;if(we=0,za=bl=null,Pt=0,(he&6)!==0)throw Error(r(331));var s=he;if(he|=4,Do(u.current),To(u,u.current,i,l),he=s,gn(0,!1),ot&&typeof ot.onPostCommitFiberRoot=="function")try{ot.onPostCommitFiberRoot(Ra,u)}catch{}return!0}finally{T.p=n,S.T=a,ko(e,t)}}function Wo(e,t,l){t=At(l,t),t=Ec(e.stateNode,t,2),e=ol(e,t,2),e!==null&&(Ha(e,2),Ht(e))}function be(e,t,l){if(e.tag===3)Wo(e,e,l);else for(;t!==null;){if(t.tag===3){Wo(t,e,l);break}else if(t.tag===1){var a=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof a.componentDidCatch=="function"&&(gl===null||!gl.has(a))){e=At(l,e),l=Wr(2),a=ol(t,l,2),a!==null&&(Fr(l,a,t,e),Ha(a,2),Ht(a));break}}t=t.return}}function Jc(e,t,l){var a=e.pingCache;if(a===null){a=e.pingCache=new Fh;var n=new Set;a.set(t,n)}else n=a.get(t),n===void 0&&(n=new Set,a.set(t,n));n.has(l)||(Gc=!0,n.add(l),e=ly.bind(null,e,t,l),t.then(e,e))}function ly(e,t,l){var a=e.pingCache;a!==null&&a.delete(t),e.pingedLanes|=e.suspendedLanes&l,e.warmLanes&=~l,ze===e&&(fe&l)===l&&(Re===4||Re===3&&(fe&62914560)===fe&&300>rt()-zu?(he&2)===0&&Na(e,0):Yc|=l,ja===fe&&(ja=0)),Ht(e)}function Fo(e,t){t===0&&(t=ws()),e=Cl(e,t),e!==null&&(Ha(e,t),Ht(e))}function ay(e){var t=e.memoizedState,l=0;t!==null&&(l=t.retryLane),Fo(e,l)}function ny(e,t){var l=0;switch(e.tag){case 31:case 13:var a=e.stateNode,n=e.memoizedState;n!==null&&(l=n.retryLane);break;case 19:a=e.stateNode;break;case 22:a=e.stateNode._retryCache;break;default:throw Error(r(314))}a!==null&&a.delete(t),Fo(e,l)}function uy(e,t){return ii(e,t)}var Uu=null,xa=null,kc=!1,Cu=!1,$c=!1,Sl=0;function Ht(e){e!==xa&&e.next===null&&(xa===null?Uu=xa=e:xa=xa.next=e),Cu=!0,kc||(kc=!0,cy())}function gn(e,t){if(!$c&&Cu){$c=!0;do for(var l=!1,a=Uu;a!==null;){if(e!==0){var n=a.pendingLanes;if(n===0)var u=0;else{var i=a.suspendedLanes,s=a.pingedLanes;u=(1<<31-dt(42|e)+1)-1,u&=n&~(i&~s),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(l=!0,td(a,u))}else u=fe,u=Bn(a,a===ze?u:0,a.cancelPendingCommit!==null||a.timeoutHandle!==-1),(u&3)===0||qa(a,u)||(l=!0,td(a,u));a=a.next}while(l);$c=!1}}function iy(){Io()}function Io(){Cu=kc=!1;var e=0;Sl!==0&&gy()&&(e=Sl);for(var t=rt(),l=null,a=Uu;a!==null;){var n=a.next,u=Po(a,t);u===0?(a.next=null,l===null?Uu=n:l.next=n,n===null&&(xa=l)):(l=a,(e!==0||(u&3)!==0)&&(Cu=!0)),a=n}we!==0&&we!==5||gn(e),Sl!==0&&(Sl=0)}function Po(e,t){for(var l=e.suspendedLanes,a=e.pingedLanes,n=e.expirationTimes,u=e.pendingLanes&-62914561;0s)break;var N=m.transferSize,M=m.initiatorType;N&&fd(M)&&(m=m.responseEnd,i+=N*(m"u"?null:document;function _d(e,t,l){var a=Oa;if(a&&typeof t=="string"&&t){var n=_t(t);n='link[rel="'+e+'"][href="'+n+'"]',typeof l=="string"&&(n+='[crossorigin="'+l+'"]'),Sd.has(n)||(Sd.add(n),e={rel:e,crossOrigin:l,href:t},a.querySelector(n)===null&&(t=a.createElement("link"),Ie(t,"link",e),Ze(t),a.head.appendChild(t)))}}function Ny(e){el.D(e),_d("dns-prefetch",e,null)}function Ty(e,t){el.C(e,t),_d("preconnect",e,t)}function xy(e,t,l){el.L(e,t,l);var a=Oa;if(a&&e&&t){var n='link[rel="preload"][as="'+_t(t)+'"]';t==="image"&&l&&l.imageSrcSet?(n+='[imagesrcset="'+_t(l.imageSrcSet)+'"]',typeof l.imageSizes=="string"&&(n+='[imagesizes="'+_t(l.imageSizes)+'"]')):n+='[href="'+_t(e)+'"]';var u=n;switch(t){case"style":u=Da(e);break;case"script":u=Ma(e)}Ot.has(u)||(e=B({rel:"preload",href:t==="image"&&l&&l.imageSrcSet?void 0:e,as:t},l),Ot.set(u,e),a.querySelector(n)!==null||t==="style"&&a.querySelector(_n(u))||t==="script"&&a.querySelector(En(u))||(t=a.createElement("link"),Ie(t,"link",e),Ze(t),a.head.appendChild(t)))}}function Oy(e,t){el.m(e,t);var l=Oa;if(l&&e){var a=t&&typeof t.as=="string"?t.as:"script",n='link[rel="modulepreload"][as="'+_t(a)+'"][href="'+_t(e)+'"]',u=n;switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ma(e)}if(!Ot.has(u)&&(e=B({rel:"modulepreload",href:e},t),Ot.set(u,e),l.querySelector(n)===null)){switch(a){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(l.querySelector(En(u)))return}a=l.createElement("link"),Ie(a,"link",e),Ze(a),l.head.appendChild(a)}}}function Dy(e,t,l){el.S(e,t,l);var a=Oa;if(a&&e){var n=Il(a).hoistableStyles,u=Da(e);t=t||"default";var i=n.get(u);if(!i){var s={loading:0,preload:null};if(i=a.querySelector(_n(u)))s.loading=5;else{e=B({rel:"stylesheet",href:e,"data-precedence":t},l),(l=Ot.get(u))&&os(e,l);var m=i=a.createElement("link");Ze(m),Ie(m,"link",e),m._p=new Promise(function(p,N){m.onload=p,m.onerror=N}),m.addEventListener("load",function(){s.loading|=1}),m.addEventListener("error",function(){s.loading|=2}),s.loading|=4,Lu(i,t,a)}i={type:"stylesheet",instance:i,count:1,state:s},n.set(u,i)}}}function My(e,t){el.X(e,t);var l=Oa;if(l&&e){var a=Il(l).hoistableScripts,n=Ma(e),u=a.get(n);u||(u=l.querySelector(En(n)),u||(e=B({src:e,async:!0},t),(t=Ot.get(n))&&ds(e,t),u=l.createElement("script"),Ze(u),Ie(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Uy(e,t){el.M(e,t);var l=Oa;if(l&&e){var a=Il(l).hoistableScripts,n=Ma(e),u=a.get(n);u||(u=l.querySelector(En(n)),u||(e=B({src:e,async:!0,type:"module"},t),(t=Ot.get(n))&&ds(e,t),u=l.createElement("script"),Ze(u),Ie(u,"link",e),l.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},a.set(n,u))}}function Ed(e,t,l,a){var n=(n=$.current)?Bu(n):null;if(!n)throw Error(r(446));switch(e){case"meta":case"title":return null;case"style":return typeof l.precedence=="string"&&typeof l.href=="string"?(t=Da(l.href),l=Il(n).hoistableStyles,a=l.get(t),a||(a={type:"style",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};case"link":if(l.rel==="stylesheet"&&typeof l.href=="string"&&typeof l.precedence=="string"){e=Da(l.href);var u=Il(n).hoistableStyles,i=u.get(e);if(i||(n=n.ownerDocument||n,i={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,i),(u=n.querySelector(_n(e)))&&!u._p&&(i.instance=u,i.state.loading=5),Ot.has(e)||(l={rel:"preload",as:"style",href:l.href,crossOrigin:l.crossOrigin,integrity:l.integrity,media:l.media,hrefLang:l.hrefLang,referrerPolicy:l.referrerPolicy},Ot.set(e,l),u||Cy(n,e,l,i.state))),t&&a===null)throw Error(r(528,""));return i}if(t&&a!==null)throw Error(r(529,""));return null;case"script":return t=l.async,l=l.src,typeof l=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ma(l),l=Il(n).hoistableScripts,a=l.get(t),a||(a={type:"script",instance:null,count:0,state:null},l.set(t,a)),a):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,e))}}function Da(e){return'href="'+_t(e)+'"'}function _n(e){return'link[rel="stylesheet"]['+e+"]"}function Ad(e){return B({},e,{"data-precedence":e.precedence,precedence:null})}function Cy(e,t,l,a){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?a.loading=1:(t=e.createElement("link"),a.preload=t,t.addEventListener("load",function(){return a.loading|=1}),t.addEventListener("error",function(){return a.loading|=2}),Ie(t,"link",l),Ze(t),e.head.appendChild(t))}function Ma(e){return'[src="'+_t(e)+'"]'}function En(e){return"script[async]"+e}function jd(e,t,l){if(t.count++,t.instance===null)switch(t.type){case"style":var a=e.querySelector('style[data-href~="'+_t(l.href)+'"]');if(a)return t.instance=a,Ze(a),a;var n=B({},l,{"data-href":l.href,"data-precedence":l.precedence,href:null,precedence:null});return a=(e.ownerDocument||e).createElement("style"),Ze(a),Ie(a,"style",n),Lu(a,l.precedence,e),t.instance=a;case"stylesheet":n=Da(l.href);var u=e.querySelector(_n(n));if(u)return t.state.loading|=4,t.instance=u,Ze(u),u;a=Ad(l),(n=Ot.get(n))&&os(a,n),u=(e.ownerDocument||e).createElement("link"),Ze(u);var i=u;return i._p=new Promise(function(s,m){i.onload=s,i.onerror=m}),Ie(u,"link",a),t.state.loading|=4,Lu(u,l.precedence,e),t.instance=u;case"script":return u=Ma(l.src),(n=e.querySelector(En(u)))?(t.instance=n,Ze(n),n):(a=l,(n=Ot.get(u))&&(a=B({},l),ds(a,n)),e=e.ownerDocument||e,n=e.createElement("script"),Ze(n),Ie(n,"link",a),e.head.appendChild(n),t.instance=n);case"void":return null;default:throw Error(r(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(a=t.instance,t.state.loading|=4,Lu(a,l.precedence,e));return t.instance}function Lu(e,t,l){for(var a=l.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),n=a.length?a[a.length-1]:null,u=n,i=0;i title"):null)}function Ry(e,t,l){if(l===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return e=t.disabled,typeof t.precedence=="string"&&e==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function Td(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function qy(e,t,l,a){if(l.type==="stylesheet"&&(typeof a.media!="string"||matchMedia(a.media).matches!==!1)&&(l.state.loading&4)===0){if(l.instance===null){var n=Da(a.href),u=t.querySelector(_n(n));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=Yu.bind(e),t.then(e,e)),l.state.loading|=4,l.instance=u,Ze(u);return}u=t.ownerDocument||t,a=Ad(a),(n=Ot.get(n))&&os(a,n),u=u.createElement("link"),Ze(u);var i=u;i._p=new Promise(function(s,m){i.onload=s,i.onerror=m}),Ie(u,"link",a),l.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(l,t),(t=l.state.preload)&&(l.state.loading&3)===0&&(e.count++,l=Yu.bind(e),t.addEventListener("load",l),t.addEventListener("error",l))}}var ms=0;function Hy(e,t){return e.stylesheets&&e.count===0&&Xu(e,e.stylesheets),0ms?50:800)+t);return e.unsuspend=l,function(){e.unsuspend=null,clearTimeout(a),clearTimeout(n)}}:null}function Yu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xu(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Qu=null;function Xu(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Qu=new Map,t.forEach(By,e),Qu=null,Yu.call(e))}function By(e,t){if(!(t.state.loading&4)){var l=Qu.get(e);if(l)var a=l.get(null);else{l=new Map,Qu.set(e,l);for(var n=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(f)}catch(d){console.error(d)}}return f(),Es.exports=Py(),Es.exports}var tv=ev();/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const im=(...f)=>f.filter((d,v,r)=>!!d&&d.trim()!==""&&r.indexOf(d)===v).join(" ").trim();/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const lv=f=>f.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const av=f=>f.replace(/^([A-Z])|[\s-_]+(\w)/g,(d,v,r)=>r?r.toUpperCase():v.toLowerCase());/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Fd=f=>{const d=av(f);return d.charAt(0).toUpperCase()+d.slice(1)};/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */var nv={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const uv=f=>{for(const d in f)if(d.startsWith("aria-")||d==="role"||d==="title")return!0;return!1};/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const iv=H.forwardRef(({color:f="currentColor",size:d=24,strokeWidth:v=2,absoluteStrokeWidth:r,className:O="",children:z,iconNode:U,...V},q)=>H.createElement("svg",{ref:q,...nv,width:d,height:d,stroke:f,strokeWidth:r?Number(v)*24/Number(d):v,className:im("lucide",O),...!z&&!uv(V)&&{"aria-hidden":"true"},...V},[...U.map(([E,G])=>H.createElement(E,G)),...Array.isArray(z)?z:[z]]));/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Ke=(f,d)=>{const v=H.forwardRef(({className:r,...O},z)=>H.createElement(iv,{ref:z,iconNode:d,className:im(`lucide-${lv(Fd(f))}`,`lucide-${f}`,r),...O}));return v.displayName=Fd(f),v};/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const cv=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],sv=Ke("arrow-left",cv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const fv=[["path",{d:"M7 7h10v10",key:"1tivn9"}],["path",{d:"M7 17 17 7",key:"1vkiza"}]],Un=Ke("arrow-up-right",fv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const rv=[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]],ov=Ke("chevron-left",rv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const dv=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],cm=Ke("chevron-right",dv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const mv=[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"r6nss1"}]],sm=Ke("house",mv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const hv=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2",key:"1m3agn"}],["circle",{cx:"9",cy:"9",r:"2",key:"af1f0g"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21",key:"1xmnt7"}]],yv=Ke("image",hv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const vv=[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2",key:"8i5ue5"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2",key:"1b9ql8"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12",key:"1jonct"}]],fm=Ke("link-2",vv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const gv=[["circle",{cx:"12",cy:"16",r:"1",key:"1au0dj"}],["rect",{x:"3",y:"10",width:"18",height:"12",rx:"2",key:"6s8ecr"}],["path",{d:"M7 10V7a5 5 0 0 1 10 0v3",key:"1pqi11"}]],bv=Ke("lock-keyhole",gv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const pv=[["path",{d:"m16 17 5-5-5-5",key:"1bji2h"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}]],rm=Ke("log-out",pv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Sv=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],Id=Ke("plus",Sv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const _v=[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z",key:"1c8476"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7",key:"1ydtos"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7",key:"t51u73"}]],Ev=Ke("save",_v);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Av=[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]],Ds=Ke("search",Av);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const jv=[["path",{d:"M10 5H3",key:"1qgfaw"}],["path",{d:"M12 19H3",key:"yhmn1j"}],["path",{d:"M14 3v4",key:"1sua03"}],["path",{d:"M16 17v4",key:"1q0r14"}],["path",{d:"M21 12h-9",key:"1o4lsq"}],["path",{d:"M21 19h-5",key:"1rlt1p"}],["path",{d:"M21 5h-7",key:"1oszz2"}],["path",{d:"M8 10v4",key:"tgpxqk"}],["path",{d:"M8 12H3",key:"a7s4jb"}]],om=Ke("sliders-horizontal",jv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const zv=[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]],Nv=Ke("sparkles",zv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Tv=[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]],Hs=Ke("star",Tv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const xv=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],Iu=Ke("trash-2",xv);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Ov=[["path",{d:"M12 3v12",key:"1x0j5s"}],["path",{d:"m17 8-5-5-5 5",key:"7q97r8"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}]],Dv=Ke("upload",Ov);/** - * @license lucide-react v0.575.0 - ISC - * - * This source code is licensed under the ISC license. - * See the LICENSE file in the root directory of this source tree. - */const Mv=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],kl=Ke("x",Mv),Uv="2026-07-16T12:00:00.000Z",dm=["Administración","Recursos Humanos","CDC"],Cv=[];function Rv(){return{schemaVersion:1,apps:Cv.map(f=>({...f,keywords:[...f.keywords]})),favoritesByUser:{},recentByUser:{},updatedAt:Uv}}const On="glm-hub:state:v1";function qv(f){if(!f||typeof f!="object")return!1;const d=f;return typeof d.id=="string"&&typeof d.name=="string"&&typeof d.description=="string"&&typeof d.category=="string"&&Array.isArray(d.keywords)&&typeof d.url=="string"&&typeof d.mark=="string"&&typeof d.accent=="string"&&typeof d.iconDataUrl=="string"&&(d.visibility==="published"||d.visibility==="hidden")}function Hv(f){if(!f||typeof f!="object")return!1;const d=f;return d.schemaVersion===1&&Array.isArray(d.apps)&&d.apps.every(qv)&&!!d.favoritesByUser&&typeof d.favoritesByUser=="object"&&!!d.recentByUser&&typeof d.recentByUser=="object"}function Pd(f,d){return Object.fromEntries(Object.entries(f).map(([v,r])=>[v,r.filter(O=>d.has(O))]))}function Bv(f){switch(f){case"Administración":case"Recursos Humanos":case"CDC":return f;case"Recursos":return"Recursos Humanos";case"Clientes":case"Creatividad":return"CDC";case"Operaciones":case"Analítica":default:return"Administración"}}function Lv(f){let d=!1;const v=f.apps.map(r=>{const O=Bv(r.category);return O===r.category?r:(d=!0,{...r,category:O})});return d?{...f,apps:v,updatedAt:new Date().toISOString()}:f}function Gv(f){const d=f.apps.filter(r=>!!r.iconDataUrl.trim());if(d.length===f.apps.length)return f;const v=new Set(d.map(r=>r.id));return{...f,apps:d,favoritesByUser:Pd(f.favoritesByUser,v),recentByUser:Pd(f.recentByUser,v),updatedAt:new Date().toISOString()}}function Yv(){const f=Rv();try{const d=localStorage.getItem(On);if(!d)return localStorage.setItem(On,JSON.stringify(f)),{data:f,warning:""};const v=JSON.parse(d);if(!Hv(v))return localStorage.setItem(`${On}:backup`,d),localStorage.setItem(On,JSON.stringify(f)),{data:f,warning:"Los datos locales no eran válidos. Restauramos el catálogo inicial."};const r=Lv(v),O=Gv(r);return O!==v&&localStorage.setItem(On,JSON.stringify(O)),{data:O,warning:""}}catch{return{data:f,warning:"No pudimos leer los datos guardados. Estás viendo el catálogo inicial."}}}function Ca(f){return f.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toLocaleLowerCase("es-DO").trim()}function Jl(f){if(!f.trim())return null;try{const d=new URL(f.trim()),v=d.protocol==="http:"&&(d.hostname==="localhost"||d.hostname==="127.0.0.1");return d.protocol!=="https:"&&!v||d.username||d.password?null:d.toString()}catch{return null}}const mm="https://dbit.digitalcompass.agency".trim(),hm="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE".trim(),ym=globalThis.supabase;if(!mm||!hm)throw new Error("Faltan VITE_SUPABASE_URL o VITE_SUPABASE_ANON_KEY en el archivo .env.");if(!ym)throw new Error("No se pudo cargar la librería de Supabase.");const qe=ym.createClient(mm,hm,{auth:{autoRefreshToken:!0,persistSession:!0,detectSessionInUrl:!0,flowType:"pkce"}}),Mn="glm_hub_apps",Ms="glm_hub_favorites",vm="glm_hub_recent_apps",Pu="glm-hub-icons",em="glm-hub:supabase-catalog-migrated:v1";function gm(f){return{id:f.id,name:f.name,description:f.description,category:f.category,keywords:[],url:f.url??"",mark:"",accent:"#4F758B",iconDataUrl:f.icon_url,visibility:f.visibility,createdAt:f.created_at,updatedAt:f.updated_at}}function Qv(f){const d=/^data:(image\/(?:png|jpeg|webp));base64,([a-zA-Z0-9+/=]+)$/.exec(f);if(!d)throw new Error("El ícono no tiene un formato válido.");const v=d[1],r=atob(d[2]),O=new Uint8Array(r.length);for(let z=0;zr.app_id)}async function Vv(f){const{data:d,error:v}=await qe.from(vm).select("app_id,last_opened_at").eq("user_id",f).order("last_opened_at",{ascending:!1}).limit(30);if(v)throw new Error(`No se pudieron cargar los accesos recientes: ${v.message}`);return(d??[]).map(r=>r.app_id)}async function Kv(f){const[d,v,r]=await Promise.all([Bs(),Zv(f),Vv(f)]);return{schemaVersion:1,apps:d,favoritesByUser:{[f]:v},recentByUser:{[f]:r},updatedAt:new Date().toISOString()}}async function bm(f,d,v){const r=(d==null?void 0:d.id)??crypto.randomUUID(),O=await wv(r,f.iconDataUrl),z={name:f.name,description:f.description,category:f.category,url:f.url||null,icon_url:O,visibility:f.visibility,updated_by:v};let U;if(d?U=await qe.from(Mn).update(z).eq("id",r).select("id,name,description,category,url,icon_url,visibility,created_at,updated_at").single():U=await qe.from(Mn).insert({id:r,...z,created_by:v}).select("id,name,description,category,url,icon_url,visibility,created_at,updated_at").single(),U.error)throw O!==f.iconDataUrl&&await Us(O),new Error(`No se pudo guardar la aplicación: ${U.error.message}`);return d&&d.iconDataUrl!==O&&await Us(d.iconDataUrl),gm(U.data)}async function Jv(f){const{error:d}=await qe.from(Mn).delete().eq("id",f.id);if(d)throw new Error(`No se pudo eliminar la aplicación: ${d.message}`);await Us(f.iconDataUrl)}async function kv(f,d,v){if(v){const{error:O}=await qe.from(Ms).upsert({user_id:f,app_id:d},{onConflict:"user_id,app_id"});if(O)throw new Error(`No se pudo guardar el favorito: ${O.message}`);return}const{error:r}=await qe.from(Ms).delete().eq("user_id",f).eq("app_id",d);if(r)throw new Error(`No se pudo quitar el favorito: ${r.message}`)}async function $v(f,d){const{error:v}=await qe.from(vm).upsert({user_id:f,app_id:d,last_opened_at:new Date().toISOString()},{onConflict:"user_id,app_id"});if(v)throw new Error(`No se pudo registrar el acceso reciente: ${v.message}`)}async function Wv(f,d){if(f.role!=="admin"||d.length===0||localStorage.getItem(em)==="completed")return 0;const v=await Bs(),r=new Set(v.map(U=>U.name.trim().toLocaleLowerCase("es-DO"))),O=d.filter(U=>{const V=U.name.trim().toLocaleLowerCase("es-DO");return!!U.iconDataUrl.trim()&&!r.has(V)});let z=0;for(const U of O)await bm({name:U.name,description:U.description,category:U.category,url:U.url,iconDataUrl:U.iconDataUrl,visibility:U.visibility},null,f.id),r.add(U.name.trim().toLocaleLowerCase("es-DO")),z+=1;return localStorage.setItem(em,"completed"),z}function Fv(f){const d=qe.channel("glm-hub-apps-shared").on("postgres_changes",{event:"*",schema:"public",table:Mn},()=>f()).subscribe();return()=>{qe.removeChannel(d)}}const Cs=new Intl.Collator("es-DO",{sensitivity:"base"}),Iv="@gomezleemarketing.com",tm="https://agenteit.digitalcompass.agency/webhook/glm-hub-generar-icono".trim()??"",lm="https://agenteit.digitalcompass.agency/webhook/glm-hub-solicitar-acceso".trim()??"";function Ns(f=""){return`/${f}`}function Pv(){return new URL("/",window.location.origin).toString()}function e0(f,d){var U,V;const v=f.user.user_metadata??{},r=v.full_name??v.name,z=(((U=f.user.email)==null?void 0:U.trim().toLocaleLowerCase("en-US"))??"").split("@")[0]||"Usuario GLM";return((V=d==null?void 0:d.full_name)==null?void 0:V.trim())||(typeof r=="string"?r.trim():"")||z}function t0(f){const d=f.user.user_metadata??{},v=d.avatar_url??d.picture;if(typeof v!="string"||!v.trim())return"";try{const r=new URL(v.trim());return r.protocol==="https:"?r.toString():""}catch{return""}}async function l0(f){var U;const d=((U=f.user.email)==null?void 0:U.trim().toLocaleLowerCase("en-US"))??"";if(!d.endsWith(Iv))return{session:null,error:"Debes continuar con una cuenta corporativa @gomezleemarketing.com."};const{data:v,error:r}=await qe.from("glm_hub_authorized_users").select("email, full_name, role, is_active").eq("email",d).limit(1),z=(v??[])[0]??null;return r?(console.error("No se pudo validar el perfil de acceso:",r),{session:null,error:"No pudimos completar el inicio de sesión. Intenta nuevamente."}):z&&!z.is_active?{session:null,error:"Tu acceso al GLM Hub está deshabilitado. Contacta a IT Support."}:{session:{user:{id:f.user.id,name:e0(f,z),email:d,role:(z==null?void 0:z.role)==="admin"?"admin":"member",avatarUrl:t0(f)},expiresAt:(f.expires_at??Math.floor(Date.now()/1e3)+3600)*1e3},error:""}}function pm(f){const d=f.trim().split(/\s+/).filter(Boolean);if(d.length===0)return"GL";if(d.length===1)return d[0].slice(0,2).toLocaleUpperCase("es-DO");const v=d.length>=4?d.length-2:d.length-1;return`${d[0][0]}${d[v][0]}`.toLocaleUpperCase("es-DO")}function a0(){const f=new Date().getHours();return f<12?"Buenos días":f<19?"Buenas tardes":"Buenas noches"}function am(f){return f&&f[0].toLocaleUpperCase("es-DO")+f.slice(1)}function nm(f){const d=new Intl.DateTimeFormat("es-DO",{weekday:"long",day:"numeric",month:"long",year:"numeric"}).formatToParts(f),v=r=>{var O;return((O=d.find(z=>z.type===r))==null?void 0:O.value)??""};return`${am(v("weekday"))} ${v("day")} de ${am(v("month"))} de ${v("year")}`}function n0(){const[f,d]=H.useState(()=>nm(new Date));return H.useEffect(()=>{const v=()=>d(nm(new Date));v();const r=window.setInterval(v,6e4);return()=>window.clearInterval(r)},[]),f}function Wu(){return{name:"",description:"",category:"Administración",url:"",iconDataUrl:"",visibility:"published"}}function Dn(f){return{name:f.name,description:f.description,category:f.category,url:f.url,iconDataUrl:f.iconDataUrl,visibility:f.visibility}}async function Sm(f,d=!0){if(!new Set(["image/png","image/jpeg","image/webp"]).has(f.type))throw new Error("Usa un ícono en formato PNG, JPG o WebP.");if(d&&f.size>1024*1024)throw new Error("El ícono debe pesar menos de 1 MB.");const r=await createImageBitmap(f);if(r.width>4096||r.height>4096)throw r.close(),new Error("El ícono no puede superar 4096 × 4096 px.");const O=document.createElement("canvas");O.width=192,O.height=192;const z=O.getContext("2d");if(!z)throw r.close(),new Error("Este navegador no pudo procesar el ícono.");const U=Math.min(192/r.width,192/r.height),V=r.width*U,q=r.height*U,E=(192-V)/2,G=(192-q)/2;return z.clearRect(0,0,192,192),z.drawImage(r,E,G,V,q),r.close(),O.toDataURL("image/webp",.9)}async function u0(f){if(!f.startsWith("data:image/"))throw new Error("La IA no devolvió una imagen válida.");const v=await(await fetch(f)).blob();return _m(v)}async function _m(f){const d=f.type||"image/png";if(!d.startsWith("image/"))throw new Error("El flujo de IA no devolvió un archivo de imagen.");const v=d==="image/jpeg"?"jpg":d.split("/")[1]||"png",r=new File([f],`icono-generado.${v}`,{type:d});return Sm(r,!1)}function ei({compact:f=!1}){return c.jsx("img",{className:f?"brand-logo brand-logo--compact":"brand-logo",src:"/glm-logo.png",alt:"GomezLee Marketing",width:"350",height:"109"})}function ti({app:f,size:d="regular",showPlaceholder:v=!1}){const[r,O]=H.useState(!1),z=!!f.iconDataUrl&&!r;return c.jsx("span",{className:`app-mark app-mark--${d}`,"aria-hidden":"true",children:z?c.jsx("img",{src:f.iconDataUrl,alt:"",onError:()=>O(!0)}):v?c.jsx(yv,{className:"app-mark__placeholder",size:36,strokeWidth:1.5}):null})}function Em({user:f,label:d}){const[v,r]=H.useState(!1),O=!!f.avatarUrl&&!v;return c.jsx("span",{className:"avatar","aria-label":d,"aria-hidden":d?void 0:!0,children:O?c.jsx("img",{src:f.avatarUrl,alt:"",referrerPolicy:"no-referrer",onError:()=>r(!0)}):pm(f.name)})}function Ts({messages:f,onDismiss:d}){return c.jsx("div",{className:"toast-stack","aria-live":"polite","aria-relevant":"additions",children:f.map(v=>c.jsxs("div",{className:`toast toast--${v.kind}`,children:[c.jsx("span",{className:"toast__signal","aria-hidden":"true"}),c.jsxs("div",{children:[c.jsx("strong",{children:v.title}),v.detail?c.jsx("p",{children:v.detail}):null]}),c.jsx("button",{type:"button",className:"icon-button icon-button--quiet","aria-label":"Cerrar mensaje",onClick:()=>d(v.id),children:c.jsx(kl,{size:18,"aria-hidden":"true"})})]},v.id))})}function i0({onLogin:f,error:d,disabled:v=!1}){const[r,O]=H.useState(!1),z=async()=>{O(!0),await f(),O(!1)};return c.jsxs("main",{className:"login-shell",children:[c.jsxs("section",{className:"login-story","aria-labelledby":"login-headline",children:[c.jsx("div",{className:"login-story__topline",children:c.jsx(ei,{})}),c.jsxs("div",{className:"login-story__content",children:[c.jsx("p",{className:"eyebrow",children:"ACCESO INTERNO"}),c.jsxs("h1",{id:"login-headline",children:["Todo el trabajo",c.jsx("span",{children:"de GLM, a un clic."})]}),c.jsx("p",{className:"login-story__lede",children:"Tu punto de partida para abrir herramientas, encontrar recursos y mantener el día en movimiento."})]}),c.jsx("div",{className:"login-story__type","aria-hidden":"true",children:"GLM"})]}),c.jsx("section",{className:"login-panel","aria-label":"Inicio de sesión",children:c.jsxs("div",{className:"login-panel__inner",children:[c.jsxs("div",{className:"login-panel__heading",children:[c.jsx("p",{className:"section-kicker",children:"GLM HUB"}),c.jsx("h2",{children:"Entra a tu espacio."})]}),c.jsxs("div",{className:"login-form",children:[d?c.jsx("p",{className:"form-error",id:"login-error",role:"alert",children:d}):null,c.jsxs("button",{className:"primary-button primary-button--full",type:"button",disabled:v||r,onClick:()=>void z(),children:[c.jsx(bv,{size:18,"aria-hidden":"true"}),r?"Conectando…":"Continuar con Google",r?null:c.jsx(Un,{size:18,"aria-hidden":"true"})]})]})]})})]})}function c0({user:f,view:d,onNavigate:v,onLogout:r}){return c.jsxs("aside",{className:"sidebar",children:[c.jsx("div",{className:"sidebar__brand",children:c.jsx(ei,{compact:!0})}),c.jsxs("nav",{className:"sidebar__nav","aria-label":"Navegación principal",children:[c.jsxs("button",{type:"button",className:d==="hub"?"is-active":"",onClick:()=>v("hub"),"aria-current":d==="hub"?"page":void 0,children:[c.jsx(sm,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Aplicaciones"})]}),f.role==="admin"?c.jsxs("button",{type:"button",className:d==="admin"?"is-active":"",onClick:()=>v("admin"),"aria-current":d==="admin"?"page":void 0,children:[c.jsx(om,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Administrar"})]}):null]}),c.jsxs("div",{className:"sidebar__account",children:[c.jsx(Em,{user:f}),c.jsxs("span",{className:"sidebar__account-copy",children:[c.jsx("strong",{children:f.name}),c.jsx("small",{children:f.role==="admin"?"Administrador":"Usuario"})]}),c.jsx("button",{type:"button",className:"icon-button","aria-label":"Cerrar sesión",onClick:r,children:c.jsx(rm,{size:18,"aria-hidden":"true"})})]})]})}function s0({user:f}){return c.jsxs("header",{className:"mobile-header",children:[c.jsx(ei,{compact:!0}),c.jsx(Em,{user:f,label:`Sesión de ${f.name}`})]})}function f0({user:f,view:d,onNavigate:v,onLogout:r}){return c.jsxs("nav",{className:"mobile-nav","aria-label":"Navegación móvil",children:[c.jsxs("button",{type:"button",className:d==="hub"?"is-active":"",onClick:()=>v("hub"),children:[c.jsx(sm,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Inicio"})]}),f.role==="admin"?c.jsxs("button",{type:"button",className:d==="admin"?"is-active":"",onClick:()=>v("admin"),children:[c.jsx(om,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Administrar"})]}):null,c.jsxs("button",{type:"button",onClick:r,children:[c.jsx(rm,{size:20,"aria-hidden":"true"}),c.jsx("span",{children:"Salir"})]})]})}function r0({app:f,isFavorite:d,onActivate:v,onFavorite:r}){const O=!!Jl(f.url);return c.jsxs("article",{className:"quick-launch",children:[c.jsxs("div",{className:"quick-launch__top",children:[c.jsx(ti,{app:f,size:"regular"}),c.jsx("button",{type:"button",className:`favorite-button ${d?"is-favorite":""}`,onClick:()=>r(f.id),"aria-label":d?`Quitar ${f.name} de favoritos`:`Agregar ${f.name} a favoritos`,"aria-pressed":d,children:c.jsx(Hs,{size:18,fill:d?"currentColor":"none","aria-hidden":"true"})})]}),c.jsxs("div",{className:"quick-launch__copy",children:[c.jsx("span",{className:"quick-launch__category",children:f.category}),c.jsx("h3",{children:f.name}),c.jsx("p",{children:f.description})]}),c.jsxs("button",{type:"button",className:"quick-launch__action",onClick:()=>v(f),children:[c.jsx("span",{children:O?"Abrir aplicación":"Enlace pendiente"}),O?c.jsx(Un,{size:18,"aria-hidden":"true"}):c.jsx(fm,{size:17,"aria-hidden":"true"})]})]})}function o0({app:f,index:d,isFavorite:v,onActivate:r,onFavorite:O}){const z=!!Jl(f.url);return c.jsxs("article",{className:"directory-row",children:[c.jsx("span",{className:"directory-row__number","aria-hidden":"true",children:String(d+1).padStart(2,"0")}),c.jsx(ti,{app:f,size:"small"}),c.jsxs("div",{className:"directory-row__copy",children:[c.jsx("h3",{children:f.name}),c.jsx("p",{children:f.description})]}),c.jsx("span",{className:"directory-row__category",children:f.category}),c.jsxs("span",{className:`availability ${z?"availability--ready":"availability--pending"}`,children:[c.jsx("span",{"aria-hidden":"true"}),z?"Disponible":"Enlace pendiente"]}),c.jsx("button",{type:"button",className:`favorite-button ${v?"is-favorite":""}`,onClick:()=>O(f.id),"aria-label":v?`Quitar ${f.name} de favoritos`:`Agregar ${f.name} a favoritos`,"aria-pressed":v,children:c.jsx(Hs,{size:18,fill:v?"currentColor":"none","aria-hidden":"true"})}),c.jsxs("button",{type:"button",className:"directory-row__open",onClick:()=>r(f),children:[c.jsx("span",{children:z?"Abrir":"Ver estado"}),z?c.jsx(Un,{size:17,"aria-hidden":"true"}):c.jsx(cm,{size:17,"aria-hidden":"true"})]})]})}function d0({search:f,favoritesOnly:d,onClear:v}){return c.jsxs("div",{className:"empty-state",children:[c.jsx("span",{className:"empty-state__mark","aria-hidden":"true",children:"0"}),c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"SIN RESULTADOS"}),c.jsx("h3",{children:d?"Aún no tienes favoritos aquí.":`No encontramos “${f||"esa aplicación"}”.`}),c.jsx("p",{children:"Prueba otro término, cambia la categoría o vuelve a ver todo el directorio."}),c.jsx("button",{type:"button",className:"text-button",onClick:v,children:"Limpiar filtros"})]})]})}function m0({apps:f,onSubmit:d}){const v=H.useRef(null),[r,O]=H.useState("Todas"),[z,U]=H.useState(""),[V,q]=H.useState(!1),E=H.useMemo(()=>[...f].filter(w=>w.visibility==="published").sort((w,ee)=>Cs.compare(w.name,ee.name)),[f]),G=H.useMemo(()=>r==="Todas"?E:E.filter(w=>w.category===r),[r,E]);H.useEffect(()=>{z&&!G.some(w=>w.id===z)&&U("")},[z,G]),H.useEffect(()=>{if(!V)return;const w=ee=>{ee.preventDefault(),ee.returnValue=""};return window.addEventListener("beforeunload",w),()=>window.removeEventListener("beforeunload",w)},[V]);const B=()=>{var w;O("Todas"),U(""),(w=v.current)==null||w.showModal()},J=()=>{var w;V||(w=v.current)==null||w.close()},ye=async w=>{var Z;w.preventDefault();const ee=E.find(te=>te.id===z);if(!(!ee||V)){q(!0);try{await d(ee)&&((Z=v.current)==null||Z.close(),O("Todas"),U(""))}finally{q(!1)}}};return c.jsxs("section",{className:"access-request-bridge","aria-label":"Solicitud de acceso a aplicaciones",children:[c.jsx("div",{className:"access-request-bridge__number","aria-hidden":"true",children:"?"}),c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"SOLICITUD DE ACCESO"}),c.jsx("h2",{children:"¿No tienes acceso a una aplicación?"}),c.jsx("p",{children:"Selecciona el portal que necesitas y envía la solicitud al equipo responsable."})]}),c.jsxs("button",{type:"button",className:"secondary-button",onClick:B,children:["Solicitar acceso aquí",c.jsx(Un,{size:18,"aria-hidden":"true"})]}),c.jsxs("dialog",{className:"access-request-dialog",ref:v,onCancel:w=>{V&&w.preventDefault()},children:[c.jsx("button",{type:"button",className:"access-request-dialog__close",onClick:J,"aria-label":"Cerrar",children:c.jsx(kl,{size:19,"aria-hidden":"true"})}),c.jsx("p",{className:"section-kicker",children:"GLM HUB"}),c.jsx("h2",{children:"Solicitar acceso"}),c.jsx("p",{className:"access-request-dialog__intro",children:"Elige el área y la aplicación. El catálogo se actualiza automáticamente con los portales publicados."}),c.jsxs("form",{onSubmit:w=>void ye(w),children:[c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"access-request-area",children:["Área",c.jsx(Kl,{})]}),c.jsxs("select",{id:"access-request-area",value:r,onChange:w=>O(w.target.value),disabled:V,required:!0,children:[c.jsx("option",{value:"Todas",children:"Todas"}),c.jsx("option",{value:"Administración",children:"Administración"}),c.jsx("option",{value:"Recursos Humanos",children:"Recursos Humanos"}),c.jsx("option",{value:"CDC",children:"CDC"})]})]}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"access-request-app",children:["Aplicación",c.jsx(Kl,{})]}),c.jsxs("select",{id:"access-request-app",value:z,onChange:w=>U(w.target.value),disabled:V||G.length===0,required:!0,children:[c.jsx("option",{value:"",children:G.length===0?"No hay aplicaciones publicadas en esta área":"Selecciona una aplicación"}),G.map(w=>c.jsx("option",{value:w.id,children:w.name},w.id))]})]}),c.jsxs("div",{className:"access-request-dialog__actions",children:[c.jsx("button",{type:"button",className:"secondary-button secondary-button--quiet",onClick:J,disabled:V,children:"Cancelar"}),c.jsx("button",{type:"submit",className:"primary-button",disabled:!z||V,children:V?"Enviando…":"Enviar solicitud"})]})]})]}),V?c.jsx("div",{className:"generation-overlay",role:"dialog","aria-modal":"true","aria-labelledby":"access-request-loading-title",children:c.jsxs("div",{className:"generation-overlay__card",children:[c.jsx("span",{className:"generation-spinner","aria-hidden":"true"}),c.jsx("p",{className:"section-kicker",children:"GLM HUB"}),c.jsx("h2",{id:"access-request-loading-title",children:"Enviando la solicitud…"}),c.jsx("p",{children:"Estamos registrando la solicitud y enviando el correo a las personas responsables."})]})}):null]})}function h0(f,d,v=!1){return d<=(v?5:7)?Array.from({length:d},(O,z)=>z+1):v?f<=3?[1,2,3,"ellipsis-end",d]:f>=d-2?[1,"ellipsis-start",d-2,d-1,d]:[1,"ellipsis-start",f,"ellipsis-end",d]:f<=4?[1,2,3,4,5,"ellipsis-end",d]:f>=d-3?[1,"ellipsis-start",d-4,d-3,d-2,d-1,d]:[1,"ellipsis-start",f-1,f,f+1,"ellipsis-end",d]}function Rs({currentPage:f,totalPages:d,onPageChange:v,compact:r=!1,label:O}){if(d<=1)return null;const z=h0(f,d,r);return c.jsxs("nav",{className:`pagination ${r?"pagination--compact":""}`,"aria-label":O,children:[c.jsx("button",{type:"button",className:"pagination__arrow",disabled:f<=1,onClick:()=>v(f-1),"aria-label":"Página anterior",children:c.jsx(ov,{size:16,"aria-hidden":"true"})}),c.jsx("div",{className:"pagination__pages",children:z.map(U=>typeof U=="number"?c.jsx("button",{type:"button",className:`pagination__page ${U===f?"is-active":""}`,onClick:()=>v(U),"aria-label":`Ir a la página ${U}`,"aria-current":U===f?"page":void 0,children:U},U):c.jsx("span",{className:"pagination__ellipsis","aria-hidden":"true",children:"…"},U))}),c.jsx("button",{type:"button",className:"pagination__arrow",disabled:f>=d,onClick:()=>v(f+1),"aria-label":"Página siguiente",children:c.jsx(cm,{size:16,"aria-hidden":"true"})})]})}const Fu=10,xs=6,Os=10;function y0({user:f,data:d,storageWarning:v,onActivate:r,onFavorite:O,onAdmin:z,onRequestAccess:U}){const[V,q]=H.useState({Todas:"",Administración:"","Recursos Humanos":"",CDC:""}),[E,G]=H.useState("Todas"),[B,J]=H.useState(!1),[ye,w]=H.useState(1),[ee,Z]=H.useState(1),te=V[E]??"",Ne=D=>{q(b=>({...b,[E]:D}))},Te=H.useDeferredValue(te),se=n0(),pe=f.role==="admin",Ae=d.favoritesByUser[f.id]??[],I=d.recentByUser[f.id]??[],ne=H.useMemo(()=>new Set(Ae),[Ae]),Me=H.useMemo(()=>[...d.apps.filter(D=>D.visibility==="published"&&!!D.iconDataUrl.trim())].sort((D,b)=>Cs.compare(D.name,b.name)),[d.apps]),Ue=H.useMemo(()=>{const D=Ca(Te);return Me.filter(b=>E!=="Todas"&&b.category!==E||B&&!ne.has(b.id)?!1:D?Ca(b.name).includes(D):!0).sort((b,o)=>Number(ne.has(o.id))-Number(ne.has(b.id))||Cs.compare(b.name,o.name))},[E,Te,ne,B,Me]),ve=Math.max(1,Math.ceil(Ue.length/Fu));H.useEffect(()=>{w(1)},[te,E,B]),H.useEffect(()=>{ye>ve&&w(ve)},[ye,ve]);const He=H.useMemo(()=>{const D=(ye-1)*Fu;return Ue.slice(D,D+Fu)},[ye,Ue]),lt=D=>{w(Math.min(Math.max(D,1),ve)),window.requestAnimationFrame(()=>{var b;(b=document.getElementById("directory-title"))==null||b.scrollIntoView({behavior:"smooth",block:"start"})})},Y=H.useMemo(()=>{const D=new Map(Me.map(R=>[R.id,R])),b=[],o=new Set,A=R=>{const L=D.get(R);!L||o.has(R)||(b.push(L),o.add(R))};if(Ae.forEach(A),b.length<3){for(const R of I)if(A(R),b.length>=3)break}if(b.length<3){for(const R of Me)if(A(R.id),b.length>=3)break}return b},[Ae,Me,I]),k=Math.max(1,Math.ceil(Y.length/xs)),S=H.useMemo(()=>{const D=(ee-1)*xs;return Y.slice(D,D+xs)},[Y,ee]);H.useEffect(()=>{ee>k&&Z(k)},[ee,k]),H.useEffect(()=>{Z(1)},[d.favoritesByUser,d.recentByUser,f.id]);const T=D=>{Z(Math.min(Math.max(D,1),k)),window.requestAnimationFrame(()=>{var b;(b=document.getElementById("quick-title"))==null||b.scrollIntoView({behavior:"smooth",block:"start"})})},C=()=>{q({Todas:"",Administración:"","Recursos Humanos":"",CDC:""}),G("Todas"),J(!1)};return c.jsxs("main",{className:"page-content hub-page",children:[c.jsxs("header",{className:"page-header",children:[c.jsxs("div",{children:[c.jsxs("p",{className:"page-header__meta",children:[a0(),", ",f.name]}),c.jsx("h1",{children:"Tu mesa de trabajo."})]}),c.jsx("div",{className:"page-header__aside",children:c.jsx("span",{children:se})})]}),v?c.jsx("div",{className:"inline-alert",role:"status",children:v}):null,c.jsxs("section",{className:"search-stage","aria-labelledby":"search-title",children:[c.jsx("div",{className:"search-stage__copy",children:c.jsx("h2",{id:"search-title",children:"¿Qué necesitas abrir?"})}),c.jsxs("div",{className:"hub-search",children:[c.jsx(Ds,{size:21,"aria-hidden":"true"}),c.jsx("label",{className:"sr-only",htmlFor:"hub-search-input",children:"Buscar por nombre de proyecto"}),c.jsx("input",{id:"hub-search-input",type:"search",value:te,onChange:D=>Ne(D.target.value),placeholder:"Buscar por nombre de proyecto…"}),te?c.jsx("button",{type:"button",onClick:()=>Ne(""),"aria-label":"Limpiar búsqueda",children:c.jsx(kl,{size:18,"aria-hidden":"true"})}):null]})]}),c.jsxs("section",{className:"quick-section","aria-labelledby":"quick-title",children:[c.jsxs("div",{className:"section-heading",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"FIJADAS PARA TI"}),c.jsx("h2",{id:"quick-title",children:"Acceso rápido"})]}),c.jsx("p",{children:"Abre lo que más usas sin detener el ritmo."})]}),c.jsx("div",{className:"quick-grid",children:S.map(D=>c.jsx(r0,{app:D,isFavorite:ne.has(D.id),onActivate:r,onFavorite:O},D.id))}),c.jsx(Rs,{currentPage:ee,totalPages:k,onPageChange:T,compact:k>5,label:"Paginación de acceso rápido"})]}),c.jsxs("section",{className:"directory-section","aria-labelledby":"directory-title",children:[c.jsxs("div",{className:"section-heading section-heading--directory",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"DIRECTORIO GLM"}),c.jsx("h2",{id:"directory-title",children:"Todas las aplicaciones"})]}),c.jsxs("div",{className:"directory-count","aria-live":"polite",children:[c.jsx("strong",{children:Ue.length}),c.jsx("span",{children:Ue.length===1?"resultado":"resultados"})]})]}),c.jsxs("div",{className:"filter-bar","aria-label":"Filtros del directorio",children:[c.jsx("div",{className:"category-filters",children:["Todas",...dm].map(D=>c.jsx("button",{type:"button",className:E===D?"is-active":"",onClick:()=>G(D),"aria-pressed":E===D,children:D},D))}),c.jsxs("div",{className:"filter-bar__search",children:[c.jsx(Ds,{size:16,"aria-hidden":"true"}),c.jsx("label",{className:"sr-only",htmlFor:"directory-search-input",children:`Buscar por nombre de proyecto en ${E}`}),c.jsx("input",{id:"directory-search-input",type:"search",value:te,onChange:D=>Ne(D.target.value),placeholder:E==="Todas"?"Buscar por nombre de proyecto…":`Buscar en ${E}…`}),te?c.jsx("button",{type:"button",onClick:()=>Ne(""),"aria-label":"Limpiar búsqueda",children:c.jsx(kl,{size:15,"aria-hidden":"true"})}):null]}),c.jsxs("button",{type:"button",className:`favorites-filter ${B?"is-active":""}`,onClick:()=>J(D=>!D),"aria-pressed":B,children:[c.jsx(Hs,{size:17,fill:B?"currentColor":"none","aria-hidden":"true"}),"Solo favoritos"]})]}),Ue.length>0?c.jsxs(c.Fragment,{children:[c.jsx("div",{className:"directory-list",children:He.map((D,b)=>c.jsx(o0,{app:D,index:(ye-1)*Fu+b,isFavorite:ne.has(D.id),onActivate:r,onFavorite:O},D.id))}),c.jsx(Rs,{currentPage:ye,totalPages:ve,onPageChange:lt,compact:ve>5,label:"Paginación de aplicaciones"})]}):c.jsx(d0,{search:te,favoritesOnly:B,onClear:C})]}),pe?c.jsxs("section",{className:"admin-bridge","aria-label":"Acceso al panel de administración",children:[c.jsx("div",{className:"admin-bridge__number","aria-hidden":"true",children:"+"}),c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"CONTROL DEL CATÁLOGO"}),c.jsx("h2",{children:"¿Falta una herramienta?"}),c.jsx("p",{children:"Adjunta su ícono, pega el enlace y publícala para todo el equipo."})]}),c.jsxs("button",{type:"button",className:"secondary-button",onClick:z,children:["Administrar aplicaciones",c.jsx(Un,{size:18,"aria-hidden":"true"})]})]}):c.jsx(m0,{apps:Me,onSubmit:U})]})}function v0({apps:f,selectedId:d,onSelect:v,onDelete:r}){const[O,z]=H.useState(""),[U,V]=H.useState(1),[q,E]=H.useState(null),G=H.useRef(null),B=H.useMemo(()=>{const Z=Ca(O);return Z?f.filter(te=>Ca(`${te.name} ${te.category}`).includes(Z)):f},[f,O]),J=Math.max(1,Math.ceil(B.length/Os));H.useEffect(()=>{V(1)},[O]),H.useEffect(()=>{U>J&&V(J)},[U,J]);const ye=H.useMemo(()=>{const Z=(U-1)*Os;return B.slice(Z,Z+Os)},[B,U]),w=(Z,te)=>{var Ne;Z.stopPropagation(),E(te),(Ne=G.current)==null||Ne.showModal()},ee=async()=>{var Z;q&&await r(q.id)&&((Z=G.current)==null||Z.close(),E(null))};return c.jsxs("aside",{className:"admin-list","aria-label":"Aplicaciones configuradas",children:[c.jsxs("div",{className:"admin-list__top",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:"CATÁLOGO"}),c.jsxs("h2",{children:[f.length," ",f.length===1?"aplicación":"aplicaciones"]})]}),c.jsx("button",{type:"button",className:"icon-button icon-button--accent",onClick:()=>v(null),"aria-label":"Crear aplicación",children:c.jsx(Id,{size:20,"aria-hidden":"true"})})]}),c.jsxs("div",{className:"admin-list__search",children:[c.jsx(Ds,{size:17,"aria-hidden":"true"}),c.jsx("label",{htmlFor:"admin-search",className:"sr-only",children:"Buscar en el catálogo"}),c.jsx("input",{id:"admin-search",type:"search",value:O,onChange:Z=>z(Z.target.value),placeholder:"Buscar…"}),O?c.jsx("button",{type:"button",onClick:()=>z(""),"aria-label":"Limpiar búsqueda",children:c.jsx(kl,{size:15,"aria-hidden":"true"})}):null]}),c.jsxs("div",{className:"admin-list__items",children:[U===1?c.jsxs("button",{type:"button",className:`admin-list__new ${d===null?"is-active":""}`,onClick:()=>v(null),children:[c.jsx("span",{className:"admin-list__new-icon",children:c.jsx(Id,{size:18,"aria-hidden":"true"})}),c.jsxs("span",{className:"admin-list__item-info",children:[c.jsx("strong",{children:"Nueva aplicación"}),c.jsx("small",{children:"Crear y publicar"})]})]}):null,ye.map(Z=>c.jsxs("div",{className:`admin-list__item-row ${d===Z.id?"is-active":""}`,onClick:()=>v(Z.id),role:"button",tabIndex:0,onKeyDown:te=>{(te.key==="Enter"||te.key===" ")&&v(Z.id)},children:[c.jsx(ti,{app:Z,size:"small"}),c.jsxs("span",{className:"admin-list__item-info",children:[c.jsx("strong",{children:Z.name}),c.jsx("small",{children:Z.category})]}),c.jsxs("div",{className:"admin-list__item-actions",children:[c.jsx("span",{className:`mini-status ${Z.visibility==="hidden"?"is-hidden":""}`,children:Z.visibility==="hidden"?"Oculta":Jl(Z.url)?"Lista":"Pendiente"}),c.jsx("button",{type:"button",className:"admin-list__delete-icon",onClick:te=>w(te,Z),title:`Eliminar ${Z.name}`,"aria-label":`Eliminar ${Z.name}`,children:c.jsx(Iu,{size:15,"aria-hidden":"true"})})]})]},Z.id))]}),c.jsx(Rs,{currentPage:U,totalPages:J,onPageChange:V,compact:!0,label:"Paginación del catálogo de administración"}),c.jsxs("dialog",{className:"confirm-dialog",ref:G,children:[c.jsx("button",{type:"button",className:"confirm-dialog__close",onClick:()=>{var Z;return(Z=G.current)==null?void 0:Z.close()},"aria-label":"Cerrar",children:c.jsx(kl,{size:19,"aria-hidden":"true"})}),c.jsx("span",{className:"confirm-dialog__icon",children:c.jsx(Iu,{size:22,"aria-hidden":"true"})}),c.jsx("p",{className:"section-kicker",children:"ACCIÓN PERMANENTE"}),c.jsxs("h2",{children:["Eliminar ",q==null?void 0:q.name]}),c.jsx("p",{children:"El portal y sus accesos se eliminarán permanentemente. Esta acción no se puede deshacer."}),c.jsxs("div",{className:"confirm-dialog__actions",children:[c.jsx("button",{type:"button",className:"secondary-button",onClick:()=>{var Z;return(Z=G.current)==null?void 0:Z.close()},children:"Conservar"}),c.jsx("button",{type:"button",className:"danger-button danger-button--solid",onClick:ee,children:"Sí, eliminar"})]})]})]})}function Kl(){return c.jsxs(c.Fragment,{children:[c.jsx("span",{className:"required-mark","aria-hidden":"true",children:"*"}),c.jsx("span",{className:"sr-only",children:" obligatorio"})]})}function g0({app:f,allApps:d,onSave:v,onDelete:r,onCancel:O}){const[z,U]=H.useState(()=>f?Dn(f):Wu()),[V,q]=H.useState(()=>JSON.stringify(f?Dn(f):Wu())),[E,G]=H.useState({}),[B,J]=H.useState(""),[ye,w]=H.useState(!1),[ee,Z]=H.useState(!1),[te,Ne]=H.useState(!1),[Te,se]=H.useState(!1),pe=H.useRef(null),Ae=H.useRef(null),I=JSON.stringify(z)!==V,ne=ye||ee||te,Me=z.name.trim().length>=2&&!!z.description.trim();H.useEffect(()=>{const b=f?Dn(f):Wu();U(b),q(JSON.stringify(b)),G({}),J(""),window.requestAnimationFrame(()=>{var o;return(o=Ae.current)==null?void 0:o.focus()})},[f]),H.useEffect(()=>{if(!I&&!ee)return;const b=o=>o.preventDefault();return window.addEventListener("beforeunload",b),()=>window.removeEventListener("beforeunload",b)},[ee,I]),H.useEffect(()=>{if(!ee)return;const b=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=b}},[ee]);const Ue={id:(f==null?void 0:f.id)??"preview",name:z.name||"Nombre de la aplicación",description:z.description||"Una descripción breve ayuda al equipo a reconocerla.",category:z.category,keywords:[],url:z.url,mark:pm(z.name||"GLM"),accent:(f==null?void 0:f.accent)??"#4F758B",iconDataUrl:z.iconDataUrl,visibility:z.visibility,createdAt:(f==null?void 0:f.createdAt)??new Date().toISOString(),updatedAt:new Date().toISOString()},ve=(b,o)=>{U(A=>({...A,[b]:o})),G(A=>({...A,[b]:""}))},He=async b=>{if(!(!b||ee)){J(""),w(!0);try{const o=await Sm(b);ve("iconDataUrl",o)}catch(o){J(o instanceof Error?o.message:"No pudimos procesar el ícono.")}finally{w(!1)}}},lt=b=>{var o;He((o=b.target.files)==null?void 0:o[0]),b.target.value=""},Y=b=>{var o;b.preventDefault(),se(!1),He((o=b.dataTransfer.files)==null?void 0:o[0])},k=async()=>{var F;const b=z.name.trim(),o=z.description.trim(),A={};if(b.length<2&&(A.name="Completa el nombre antes de generar el ícono."),o||(A.description="Completa la descripción antes de generar el ícono."),Object.keys(A).length>0){G($=>({...$,...A}));return}if(!tm){J("Falta configurar VITE_ICON_GENERATOR_WEBHOOK_URL en el archivo .env.");return}J(""),Z(!0);const R=new AbortController,L=window.setTimeout(()=>R.abort(),18e4);try{const{data:{session:$}}=await qe.auth.getSession();if(!($!=null&&$.access_token))throw new Error("La sesión venció. Inicia sesión nuevamente.");const ue=await fetch(tm,{method:"POST",mode:"cors",cache:"no-store",credentials:"omit",signal:R.signal,headers:{Accept:"image/*, application/json;q=0.9, text/plain;q=0.8","Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify({accessToken:$.access_token,name:b,description:o})}),Je=((F=ue.headers.get("content-type"))==null?void 0:F.toLocaleLowerCase("en-US"))??"";if(ue.ok&&Je.startsWith("image/")){const tl=await _m(await ue.blob());ve("iconDataUrl",tl);return}const je=await ue.text();let Pe=null;if(je)try{Pe=JSON.parse(je)}catch{Pe=null}if(ue.ok&&(Pe!=null&&Pe.ok)&&Pe.imageDataUrl){const tl=await u0(Pe.imageDataUrl);ve("iconDataUrl",tl);return}throw new Error((Pe==null?void 0:Pe.error)||(je&&je.length<500?je:"")||`El flujo no pudo generar el ícono (HTTP ${ue.status}).`)}catch($){$ instanceof DOMException&&$.name==="AbortError"?J("La generación tardó más de 3 minutos y fue cancelada. Intenta nuevamente."):$ instanceof TypeError&&/failed to fetch/i.test($.message)?J("No se pudo conectar con el webhook de n8n. Verifica que el workflow esté activo y publicado."):J($ instanceof Error?$.message:"No pudimos generar el ícono con IA.")}finally{window.clearTimeout(L),Z(!1)}},S=()=>{const b={},o=z.name.trim(),A=z.description.trim();(o.length<2||o.length>60)&&(b.name="Escribe un nombre de 2 a 60 caracteres."),A||(b.description="Añade una descripción breve."),A.length>180&&(b.description="La descripción no puede superar 180 caracteres."),z.iconDataUrl||(b.iconDataUrl="Adjunta o genera un ícono antes de publicar la aplicación."),z.url.trim()&&!Jl(z.url)&&(b.url="Usa una URL https:// válida, sin credenciales embebidas.");const R=Ca(o);return d.some(F=>F.id!==(f==null?void 0:f.id)&&Ca(F.name)===R)&&(b.name="Ya existe una aplicación con ese nombre."),G(b),Object.keys(b).length===0},T=async b=>{if(b.preventDefault(),ne||!S()){window.requestAnimationFrame(()=>{var o,A;return(A=(o=document.querySelector(".field-error"))==null?void 0:o.focus)==null?void 0:A.call(o)});return}Ne(!0);try{const o=await v({...z,name:z.name.trim(),description:z.description.trim(),url:z.url.trim()},(f==null?void 0:f.id)??null);if(o){const A=Dn(o);U(A),q(JSON.stringify(A))}}finally{Ne(!1)}},C=()=>{if(!ee&&(!I||window.confirm("Hay cambios sin guardar. ¿Quieres descartarlos?"))){const b=f?Dn(f):Wu();U(b),q(JSON.stringify(b)),G({}),J(""),O()}},D=async()=>{var b;!f||ne||await r(f.id)&&((b=pe.current)==null||b.close(),O())};return c.jsxs("section",{className:"app-editor","aria-labelledby":"editor-title","aria-busy":ne,children:[c.jsxs("div",{className:"app-editor__heading",children:[c.jsxs("div",{children:[c.jsx("p",{className:"section-kicker",children:f?"EDITAR APLICACIÓN":"NUEVA APLICACIÓN"}),c.jsx("h2",{id:"editor-title",children:f?f.name:"Configura el nuevo acceso"})]}),I?c.jsxs("span",{className:"dirty-state is-dirty",children:[c.jsx("span",{"aria-hidden":"true"}),"Cambios sin guardar"]}):null]}),c.jsxs("div",{className:"editor-layout",children:[c.jsxs("form",{className:"editor-form",onSubmit:T,noValidate:!0,children:[c.jsxs("section",{className:"editor-form__section","aria-labelledby":"identity-section-title",children:[c.jsx("h3",{className:"editor-form__section-title",id:"identity-section-title",children:"Identidad"}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-name",children:["Nombre de la aplicación",f?null:c.jsx(Kl,{})]}),c.jsx("input",{ref:Ae,id:"app-name",value:z.name,onChange:b=>ve("name",b.target.value),placeholder:"Ej. Media Planner",maxLength:60,"aria-invalid":!!E.name,"aria-describedby":E.name?"app-name-error":void 0,disabled:ne,required:!0}),c.jsxs("div",{className:"field-meta",children:[E.name?c.jsx("span",{id:"app-name-error",className:"field-error",role:"alert",tabIndex:-1,children:E.name}):c.jsx("span",{children:"Como el equipo la reconoce."}),c.jsxs("span",{children:[z.name.length,"/60"]})]})]}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-description",children:["Descripción breve",f?null:c.jsx(Kl,{})]}),c.jsx("textarea",{id:"app-description",value:z.description,onChange:b=>ve("description",b.target.value),placeholder:"Explica qué resuelve en una sola frase.",maxLength:180,rows:3,"aria-invalid":!!E.description,"aria-describedby":E.description?"app-description-error":void 0,disabled:ne,required:!0}),c.jsxs("div",{className:`field-meta ${E.description?"":"field-meta--counter-only"}`,children:[E.description?c.jsx("span",{id:"app-description-error",className:"field-error",role:"alert",tabIndex:-1,children:E.description}):null,c.jsxs("span",{children:[z.description.length,"/180"]})]})]}),c.jsxs("div",{className:"form-split",children:[c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-category",children:["Categoría",f?null:c.jsx(Kl,{})]}),c.jsx("select",{id:"app-category",value:z.category,onChange:b=>ve("category",b.target.value),disabled:ne,required:!0,children:dm.map(b=>c.jsx("option",{children:b},b))})]}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-visibility",children:["Visibilidad",f?null:c.jsx(Kl,{})]}),c.jsxs("select",{id:"app-visibility",value:z.visibility,onChange:b=>ve("visibility",b.target.value),disabled:ne,required:!0,children:[c.jsx("option",{value:"published",children:"Publicada"}),c.jsx("option",{value:"hidden",children:"Oculta"})]})]})]})]}),c.jsxs("section",{className:"editor-form__section","aria-labelledby":"icon-section-title",children:[c.jsxs("h3",{className:"editor-form__section-title",id:"icon-section-title",children:["Ícono",f?null:c.jsx(Kl,{})]}),c.jsxs("div",{className:"icon-config",children:[c.jsxs("label",{className:`icon-dropzone ${Te?"is-dragging":""}`,onDragEnter:b=>{b.preventDefault(),ne||se(!0)},onDragOver:b=>b.preventDefault(),onDragLeave:()=>se(!1),onDrop:Y,children:[c.jsx("input",{type:"file",accept:"image/png,image/jpeg,image/webp",onChange:lt,disabled:ne}),c.jsx("span",{className:"icon-dropzone__symbol",children:c.jsx(Dv,{size:20,"aria-hidden":"true"})}),c.jsxs("span",{children:[c.jsx("strong",{children:ye?"Procesando…":"Adjuntar ícono"}),c.jsx("small",{children:"PNG, JPG o WebP · máximo 1 MB"})]})]}),z.iconDataUrl?c.jsx("button",{type:"button",className:"text-button text-button--danger",disabled:ne,onClick:()=>ve("iconDataUrl",""),children:"Quitar ícono"}):null]}),c.jsx("div",{className:"ai-icon-actions",children:c.jsxs("button",{type:"button",className:"secondary-button ai-icon-button",onClick:()=>void k(),disabled:!Me||ne,title:Me?void 0:"Completa el nombre y la descripción breve.",children:[c.jsx(Nv,{size:18,"aria-hidden":"true"}),"Generar ícono con IA"]})}),B?c.jsx("p",{className:"field-error field-error--standalone",role:"alert",children:B}):null,E.iconDataUrl?c.jsx("p",{className:"field-error field-error--standalone",role:"alert",tabIndex:-1,children:E.iconDataUrl}):null]}),c.jsxs("section",{className:"editor-form__section","aria-labelledby":"destination-section-title",children:[c.jsx("h3",{className:"editor-form__section-title",id:"destination-section-title",children:"Destino"}),c.jsxs("div",{className:"form-field",children:[c.jsxs("label",{htmlFor:"app-url",children:["Enlace de la aplicación ",c.jsx("span",{children:"Opcional"})]}),c.jsxs("div",{className:"url-field",children:[c.jsx(fm,{size:18,"aria-hidden":"true"}),c.jsx("input",{id:"app-url",type:"url",value:z.url,onChange:b=>ve("url",b.target.value),placeholder:"https://aplicacion.com","aria-invalid":!!E.url,"aria-describedby":E.url?"app-url-error":"app-url-help",disabled:ne})]}),E.url?c.jsx("span",{id:"app-url-error",className:"field-error",role:"alert",tabIndex:-1,children:E.url}):c.jsx("span",{id:"app-url-help",className:"field-help",children:"Si lo dejas vacío, aparecerá como “Enlace pendiente”."})]})]}),c.jsxs("div",{className:"editor-actions",children:[c.jsxs("button",{type:"submit",className:"primary-button",disabled:ne,children:[c.jsx(Ev,{size:18,"aria-hidden":"true"}),te?"Guardando…":f?"Guardar cambios":"Publicar aplicación"]}),c.jsx("button",{type:"button",className:"secondary-button secondary-button--quiet",disabled:ne,onClick:C,children:"Cancelar"}),f?c.jsxs("button",{type:"button",className:"danger-button",disabled:ne,onClick:()=>{var b;return(b=pe.current)==null?void 0:b.showModal()},children:[c.jsx(Iu,{size:17,"aria-hidden":"true"}),"Eliminar"]}):null]})]}),c.jsxs("aside",{className:"app-preview","aria-label":"Vista previa de la aplicación",children:[c.jsxs("div",{className:"app-preview__label",children:[c.jsx("span",{children:"VISTA PREVIA"}),c.jsx("span",{className:"app-preview__rule"})]}),c.jsxs("div",{className:"preview-card",children:[c.jsx(ti,{app:Ue,size:"large",showPlaceholder:!f&&!z.iconDataUrl}),c.jsx("span",{className:"quick-launch__category",children:Ue.category}),c.jsx("h3",{children:Ue.name}),c.jsx("p",{children:Ue.description}),c.jsxs("span",{className:`availability ${Jl(Ue.url)?"availability--ready":"availability--pending"}`,children:[c.jsx("span",{"aria-hidden":"true"}),Jl(Ue.url)?"Lista para abrir":"Enlace pendiente"]})]}),c.jsx("p",{className:"app-preview__note",children:"Así aparecerá en el Hub para el equipo."})]})]}),c.jsxs("dialog",{className:"confirm-dialog",ref:pe,children:[c.jsx("button",{type:"button",className:"confirm-dialog__close",onClick:()=>{var b;return(b=pe.current)==null?void 0:b.close()},"aria-label":"Cerrar",children:c.jsx(kl,{size:19,"aria-hidden":"true"})}),c.jsx("span",{className:"confirm-dialog__icon",children:c.jsx(Iu,{size:22,"aria-hidden":"true"})}),c.jsx("p",{className:"section-kicker",children:"ACCIÓN PERMANENTE"}),c.jsxs("h2",{children:["Eliminar ",f==null?void 0:f.name]}),c.jsx("p",{children:"La aplicación se quitará del catálogo compartido para todo el equipo. Esta acción no se puede deshacer."}),c.jsxs("div",{className:"confirm-dialog__actions",children:[c.jsx("button",{type:"button",className:"secondary-button",onClick:()=>{var b;return(b=pe.current)==null?void 0:b.close()},children:"Conservar"}),c.jsx("button",{type:"button",className:"danger-button danger-button--solid",onClick:()=>void D(),children:"Sí, eliminar"})]})]}),ee?c.jsx("div",{className:"generation-overlay",role:"dialog","aria-modal":"true","aria-labelledby":"generation-title",children:c.jsxs("div",{className:"generation-overlay__card",children:[c.jsx("span",{className:"generation-spinner","aria-hidden":"true"}),c.jsx("p",{className:"section-kicker",children:"GEMINI"}),c.jsx("h2",{id:"generation-title",children:"Generando el ícono…"}),c.jsx("p",{children:"Estamos creando una propuesta a partir del nombre y la descripción de la aplicación."})]})}):null]})}function b0({data:f,onSave:d,onDelete:v,onBack:r}){const[O,z]=H.useState(null),U=O?f.apps.find(E=>E.id===O)??null:null,V=async(E,G)=>{const B=await d(E,G);return B&&z(B.id),B},q=async E=>{const G=await v(E);return G&&z(null),G};return c.jsxs("main",{className:"page-content admin-page",children:[c.jsx("header",{className:"page-header admin-header",children:c.jsxs("div",{children:[c.jsxs("button",{type:"button",className:"back-button",onClick:r,children:[c.jsx(sv,{size:17,"aria-hidden":"true"}),"Volver al Hub"]}),c.jsx("p",{className:"page-header__meta",children:"PANEL DE ADMINISTRACIÓN"}),c.jsx("h1",{children:"Controla el catálogo."})]})}),c.jsxs("div",{className:"admin-workspace",children:[c.jsx(v0,{apps:f.apps,selectedId:O,onSelect:z,onDelete:q}),c.jsx(g0,{app:U,allApps:f.apps,onSave:V,onDelete:q,onCancel:()=>z(null)})]})]})}function p0(){return c.jsxs("div",{className:"catalog-loading",role:"status","aria-live":"polite",children:[c.jsx(ei,{compact:!0}),c.jsx("span",{className:"generation-spinner","aria-hidden":"true"}),c.jsx("p",{children:"Cargando aplicaciones…"})]})}function S0(){const[f]=H.useState(()=>Yv()),[d,v]=H.useState({schemaVersion:1,apps:[],favoritesByUser:{},recentByUser:{},updatedAt:new Date().toISOString()}),[r,O]=H.useState(null),[z,U]=H.useState(()=>"hub"),[V,q]=H.useState([]),[E,G]=H.useState(!1),[B,J]=H.useState(!1),[ye,w]=H.useState(""),[ee,Z]=H.useState(""),te=H.useRef(0),Ne=H.useRef(null),Te=H.useCallback(Y=>{q(k=>k.filter(S=>S.id!==Y))},[]),se=H.useCallback((Y,k,S)=>{const T=crypto.randomUUID();q(C=>[...C.slice(-2),{id:T,kind:Y,title:k,detail:S}]),window.setTimeout(()=>{q(C=>C.filter(D=>D.id!==T))},5200)},[]);H.useEffect(()=>{let Y=!0;const k=C=>{const D=(C.expires_at??Math.floor(Date.now()/1e3)+3600)*1e3;O(b=>!b||b.user.id!==C.user.id||b.expiresAt===D?b:{...b,expiresAt:D})},S=async C=>{const D=++te.current;if(!C){if(!Y||D!==te.current)return;Ne.current=null,O(null),J(!1),G(!0);return}if(Ne.current===C.user.id){if(!Y||D!==te.current)return;k(C),G(!0);return}const b=await l0(C);if(!Y||D!==te.current)return;if(!b.session){Ne.current=null,O(null),Z(b.error),J(!1),G(!0),await qe.auth.signOut({scope:"local"});return}const o=b.session;Ne.current=o.user.id,Z(""),O(o),G(!0),window.location.hash!=="#hub"&&window.location.hash!=="#admin"&&window.history.replaceState(null,"",Ns("#hub"))};qe.auth.getSession().then(({data:{session:C}})=>{S(C)});const{data:{subscription:T}}=qe.auth.onAuthStateChange((C,D)=>{if(C!=="INITIAL_SESSION"){if(C==="TOKEN_REFRESHED"&&D&&Ne.current===D.user.id){k(D);return}window.setTimeout(()=>{S(D)},0)}});return()=>{Y=!1,T.unsubscribe()}},[]);const pe=(r==null?void 0:r.user)??null;H.useEffect(()=>{if(!pe)return;let Y=!0,k=!1;const S=async()=>{if(!k){k=!0;try{const D=await Bs();if(!Y)return;v(b=>({...b,apps:D,updatedAt:new Date().toISOString()}))}catch(D){console.error("No se pudo refrescar el catálogo compartido:",D)}finally{k=!1}}};(async()=>{J(!1),w("");try{const D=await Wv(pe,f.data.apps),b=await Kv(pe.id);if(!Y)return;v(b),J(!0),D>0&&se("success","Catálogo compartido activado",`${D} ${D===1?"aplicación fue migrada":"aplicaciones fueron migradas"} a Supabase.`)}catch(D){if(!Y)return;const b=D instanceof Error?D.message:"No se pudo cargar el catálogo compartido.";w(b),J(!0),se("error","No se pudo cargar el catálogo",b)}})();const C=Fv(()=>void S());return()=>{Y=!1,C()}},[pe==null?void 0:pe.id,pe==null?void 0:pe.role,f.data.apps,se]),H.useEffect(()=>{const Y=()=>{const k=window.location.hash==="#admin"?"admin":"hub";if(k==="admin"&&(r==null?void 0:r.user.role)!=="admin"){U("hub"),window.history.replaceState(null,"","#hub");return}U(k)};return Y(),window.addEventListener("hashchange",Y),()=>window.removeEventListener("hashchange",Y)},[r==null?void 0:r.user.role]);const Ae=Y=>{if(Y==="admin"&&(r==null?void 0:r.user.role)!=="admin"){se("error","Acceso restringido","Necesitas permisos de administrador para abrir este panel.");return}U(Y),window.history.replaceState(null,"",Ns(Y==="admin"?"#admin":"#hub")),window.scrollTo({top:0,behavior:"smooth"})},I=async Y=>{if(!r)return;const k=r.user.id,S=d.favoritesByUser[k]??[],T=S.includes(Y),C=T?S.filter(D=>D!==Y):[Y,...S];v(D=>({...D,favoritesByUser:{...D.favoritesByUser,[k]:C},updatedAt:new Date().toISOString()}));try{await kv(k,Y,!T),se("success",T?"Quitada de favoritos":"Agregada a favoritos")}catch(D){v(b=>({...b,favoritesByUser:{...b.favoritesByUser,[k]:S}})),se("error","No se actualizó el favorito",D instanceof Error?D.message:void 0)}},ne=Y=>{if(!r)return;const k=Jl(Y.url);if(!k){se("info","Enlace pendiente",`${Y.name} todavía no tiene un enlace configurado.`);return}const S=window.open(k,"_blank","noopener,noreferrer");S&&(S.opener=null);const T=r.user.id,C=d.recentByUser[T]??[],D=[Y.id,...C.filter(b=>b!==Y.id)].slice(0,30);v(b=>({...b,recentByUser:{...b.recentByUser,[T]:D},updatedAt:new Date().toISOString()})),$v(T,Y.id).catch(b=>console.warn("No se guardó el acceso reciente:",b))},Me=async(Y,k)=>{if(!r||r.user.role!=="admin")return null;const S=k?d.apps.find(T=>T.id===k)??null:null;try{const T=await bm(Y,S,r.user.id);return v(C=>({...C,apps:S?C.apps.map(D=>D.id===T.id?T:D):[T,...C.apps],updatedAt:new Date().toISOString()})),se("success",S?"Cambios guardados":"Aplicación publicada",`${T.name} ya está disponible en el catálogo compartido.`),T}catch(T){return se("error","No se guardó la aplicación",T instanceof Error?T.message:void 0),null}},Ue=async Y=>{if(!r||r.user.role!=="admin")return!1;const k=d.apps.find(S=>S.id===Y);if(!k)return!1;try{await Jv(k);const S=T=>Object.fromEntries(Object.entries(T).map(([C,D])=>[C,D.filter(b=>b!==Y)]));return v(T=>({...T,apps:T.apps.filter(C=>C.id!==Y),favoritesByUser:S(T.favoritesByUser),recentByUser:S(T.recentByUser),updatedAt:new Date().toISOString()})),se("success","Aplicación eliminada",`${k.name} salió del catálogo compartido.`),!0}catch(S){return se("error","No se eliminó la aplicación",S instanceof Error?S.message:void 0),!1}},ve=async Y=>{if(!r||r.user.role==="admin")return!1;if(!lm)return se("error","No se pudo enviar la solicitud","La función de solicitudes no está disponible en este momento."),!1;const k=new AbortController,S=window.setTimeout(()=>k.abort(),12e4);try{const{data:{session:T}}=await qe.auth.getSession();if(!(T!=null&&T.access_token))throw new Error("La sesión venció. Cierra sesión e inicia nuevamente.");const C=await fetch(lm,{method:"POST",mode:"cors",cache:"no-store",credentials:"omit",signal:k.signal,headers:{Accept:"application/json, text/plain;q=0.9","Content-Type":"text/plain;charset=UTF-8"},body:JSON.stringify({accessToken:T.access_token,appId:Y.id})}),D=await C.text();let b=null;if(D)try{b=JSON.parse(D)}catch{b=null}if(!C.ok||!(b!=null&&b.ok)){const o=String((b==null?void 0:b.error)||"").toLowerCase();let A="No pudimos enviar la solicitud en este momento. Intenta nuevamente.";throw o.includes("pendiente")?A="Ya tienes una solicitud pendiente para esta aplicación.":o.includes("sesión")||C.status===401?A="Tu sesión venció. Cierra sesión e inicia nuevamente.":o.includes("ya no está publicada")||o.includes("no está disponible")?A="La aplicación seleccionada ya no está disponible.":(o.includes("no está autorizado")||C.status===403)&&(A="Tu cuenta no está habilitada para enviar esta solicitud."),console.error("Error interno al enviar la solicitud de acceso",{status:C.status,responseText:D}),new Error(A)}return se("success","Solicitud enviada",b.message||`La solicitud para ${Y.name} fue enviada correctamente.`),!0}catch(T){return T instanceof DOMException&&T.name==="AbortError"?se("error","La solicitud tardó demasiado","Intenta nuevamente en unos minutos."):T instanceof TypeError&&/failed to fetch/i.test(T.message)?(console.error("No se pudo contactar el servicio de solicitudes",T),se("error","No se pudo enviar la solicitud","Intenta nuevamente en unos minutos.")):se("error","No se pudo enviar la solicitud",T instanceof Error?T.message:"Intenta nuevamente en unos minutos."),!1}finally{window.clearTimeout(S)}},He=async()=>{Z("");const{error:Y}=await qe.auth.signInWithOAuth({provider:"google",options:{redirectTo:Pv(),queryParams:{hd:"gomezleemarketing.com",prompt:"select_account"}}});Y&&(console.error("No se pudo iniciar el acceso con Google:",Y),Z("No pudimos abrir el acceso con Google. Intenta nuevamente."))},lt=async()=>{const{error:Y}=await qe.auth.signOut();if(Y){se("error","No se pudo cerrar la sesión",Y.message);return}O(null),J(!1),U("hub"),window.history.replaceState(null,"",Ns())};return!E||!r?c.jsxs(c.Fragment,{children:[c.jsx(i0,{onLogin:He,error:ee,disabled:!E}),c.jsx(Ts,{messages:V,onDismiss:Te})]}):B?c.jsxs("div",{className:"app-shell",children:[c.jsx(c0,{user:r.user,view:z,onNavigate:Ae,onLogout:lt}),c.jsx(s0,{user:r.user}),z==="admin"&&r.user.role==="admin"?c.jsx(b0,{data:d,onSave:Me,onDelete:Ue,onBack:()=>Ae("hub")}):c.jsx(y0,{user:r.user,data:d,storageWarning:ye,onActivate:ne,onFavorite:Y=>void I(Y),onAdmin:()=>Ae("admin"),onRequestAccess:ve}),c.jsx(f0,{user:r.user,view:z,onNavigate:Ae,onLogout:lt}),c.jsx(Ts,{messages:V,onDismiss:Te})]}):c.jsxs(c.Fragment,{children:[c.jsx(p0,{}),c.jsx(Ts,{messages:V,onDismiss:Te})]})}const um="https://dbit.digitalcompass.agency/storage/v1/object/public/public-assets/GLM.png?v=glm-hub-20260722-v3";function _0(){document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]').forEach(v=>{v.remove()});const f=document.createElement("link");f.rel="icon",f.type="image/png",f.sizes="512x512",f.href=um,document.head.appendChild(f);const d=document.createElement("link");d.rel="shortcut icon",d.type="image/png",d.href=um,document.head.appendChild(d)}_0();tv.createRoot(document.getElementById("root")).render(c.jsx(H.StrictMode,{children:c.jsx(S0,{})})); diff --git a/dist/index.html b/dist/index.html index 3c86a61..cc5866a 100644 --- a/dist/index.html +++ b/dist/index.html @@ -9,8 +9,8 @@ GLM Hub — GomezLee Marketing - - + +
diff --git a/n8n/GLM-Hub-Solicitudes-Acceso-Aprobacion.json b/n8n/GLM-Hub-Solicitudes-Acceso-Aprobacion.json index 679b202..9fec15c 100644 --- a/n8n/GLM-Hub-Solicitudes-Acceso-Aprobacion.json +++ b/n8n/GLM-Hub-Solicitudes-Acceso-Aprobacion.json @@ -10,13 +10,13 @@ "allowedOrigins": "*" } }, - "id": "c1e25778-7556-4c87-9069-560c848cf185", + "id": "80c8fbc9-c126-447e-a2b3-b2c9ac6e9468", "name": "Webhook - Solicitar acceso", "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ - -240, - 368 + -928, + 192 ], "webhookId": "ad3e98b9-baf2-400f-90e7-dcd4c5c20457" }, @@ -24,13 +24,13 @@ "parameters": { "jsCode": "const source = $json.body ?? $json;\nlet payload = source;\nif (typeof payload === 'string') {\n try { payload = JSON.parse(payload); } catch { payload = {}; }\n}\nconst accessToken = String(payload?.accessToken ?? '').trim();\nconst appId = String(payload?.appId ?? '').trim();\nconst jwtPattern = /^[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$/;\nconst uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nlet error = '';\nif (!jwtPattern.test(accessToken)) error = 'La sesión recibida no es válida.';\nelse if (!uuidPattern.test(appId)) error = 'Selecciona una aplicación válida.';\nreturn [{ json: { valid: !error, error, authorization: `Bearer ${accessToken}`, appId } }];" }, - "id": "382d40fd-c718-4ca5-be37-33fe80ad0483", + "id": "7d5b3911-3db7-4023-a89b-ac690bc99101", "name": "Validar solicitud de acceso", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ - -16, - 368 + -704, + 192 ] }, { @@ -58,13 +58,13 @@ }, "options": {} }, - "id": "edbdd398-aa28-46b5-8fdd-d359e9d8dcbd", + "id": "3c1cd649-6e3a-4751-ba1f-e775e8040f1d", "name": "¿Solicitud de acceso válida?", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ - 208, - 368 + -480, + 192 ] }, { @@ -83,13 +83,13 @@ } } }, - "id": "81e1ad6e-ca84-4c3f-9897-bdfcab58e965", + "id": "ff32cfc2-c5ed-4e10-8804-2209cd17ef69", "name": "Responder solicitud inválida", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ - 432, - 528 + -160, + 352 ] }, { @@ -108,46 +108,44 @@ "value": "={{ $('Validar solicitud de acceso').first().json.authorization }}" }, { - "name": "Content-Type", + "name": "Accept", "value": "application/json" } ] }, "sendBody": true, - "contentType": "raw", - "rawContentType": "application/json", - "body": "={{ JSON.stringify({ p_app_id: $json.appId }) }}", + "specifyBody": "json", + "jsonBody": "={{ {\n p_app_id: $('Validar solicitud de acceso').first().json.appId\n} }}", "options": { "response": { "response": { "neverError": true, - "responseFormat": "json", - "fullResponse": true + "responseFormat": "json" } }, "timeout": 30000 } }, - "id": "513d8635-0e4b-49bf-beeb-1fcd76555b9d", + "id": "260ee2e0-d0d7-4395-a186-b6cec2a766db", "name": "Crear solicitud en Supabase", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ - 432, - 288 + 304, + 112 ] }, { "parameters": { - "jsCode": "const source = $input.first()?.json ?? {};\nconst parseJson = (value) => {\n if (typeof value !== 'string') return value;\n try { return JSON.parse(value); } catch { return value; }\n};\nlet payload = source.body ?? source.data ?? source.response?.body ?? source;\npayload = parseJson(payload);\nif (Array.isArray(payload)) payload = payload[0] ?? {};\nif (payload && typeof payload === 'object' && payload.body !== undefined && payload.ok === undefined) {\n payload = parseJson(payload.body);\n if (Array.isArray(payload)) payload = payload[0] ?? {};\n}\nif (payload?.ok !== true) {\n return [{ json: {\n created: false,\n publicError: 'La solicitud fue registrada, pero no se pudo enviar el correo. Intenta nuevamente en unos minutos.',\n technicalError: String(payload?.error ?? payload?.message ?? 'No se pudieron emitir los enlaces de aprobación.')\n } }];\n}\nconst escapeHtml = (value) => String(value ?? '').replace(/[&<>\"']/g, (c) => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst encode = encodeURIComponent;\nconst confirmBase = 'https://agenteit.digitalcompass.agency/webhook/glm-hub-confirmar-solicitud';\nconst requesterName = String(payload.requesterName ?? 'Usuario GLM');\nconst requesterEmail = String(payload.requesterEmail ?? '');\nconst appName = String(payload.appName ?? 'Aplicación GLM');\nconst appCategory = String(payload.appCategory ?? '');\nconst requestId = String(payload.requestId ?? '');\nconst approvers = Array.isArray(payload.approvers) ? payload.approvers : [];\nif (approvers.length !== 3) {\n return [{ json: {\n created: false,\n publicError: 'No se pudo completar el envío de la solicitud. Intenta nuevamente en unos minutos.',\n technicalError: `Se esperaban 3 aprobadores y se recibieron ${approvers.length}.`\n } }];\n}\nreturn approvers.map((approver) => {\n const approveUrl = `${confirmBase}?token=${encode(String(approver.token ?? ''))}&decision=approved&app=${encode(appName)}`;\n const rejectUrl = `${confirmBase}?token=${encode(String(approver.token ?? ''))}&decision=rejected&app=${encode(appName)}`;\n const html = `
\"GomezLee
GLM HUB · SOLICITUD DE ACCESO

Una persona necesita acceso.

Hola ${escapeHtml(approver.name)}, revisa la siguiente solicitud.

Solicitante${escapeHtml(requesterName)}
Correo${escapeHtml(requesterEmail)}
Aplicación${escapeHtml(appName)}
Área${escapeHtml(appCategory)}

Por seguridad, cada botón abre una pantalla de confirmación. La primera decisión confirmada será definitiva para los tres destinatarios.

Aceptar solicitudRechazar solicitud
Solicitud ${escapeHtml(requestId)} · GomezLee Marketing · Uso interno
`;\n return { json: { created: true, requestId, sendTo: String(approver.email ?? ''), subject: `Solicitud de acceso | ${appName} | ${requesterName}`, html } };\n});" + "jsCode": "const source = $input.first()?.json ?? {};\nconst parseJson = (value) => {\n if (typeof value !== 'string') return value;\n try { return JSON.parse(value); } catch { return value; }\n};\nlet payload = source.body ?? source.data ?? source.response?.body ?? source;\npayload = parseJson(payload);\nif (Array.isArray(payload)) payload = payload[0] ?? {};\nif (payload && typeof payload === 'object' && payload.body !== undefined && payload.ok === undefined) {\n payload = parseJson(payload.body);\n if (Array.isArray(payload)) payload = payload[0] ?? {};\n}\nif (payload?.ok !== true) {\n return [{ json: {\n created: false,\n publicError: 'La solicitud fue registrada, pero no se pudo enviar el correo. Intenta nuevamente en unos minutos.',\n technicalError: String(payload?.error ?? payload?.message ?? 'No se pudieron emitir los enlaces de aprobación.')\n } }];\n}\nconst escapeHtml = (value) => String(value ?? '').replace(/[&<>\"']/g, (c) => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst encode = encodeURIComponent;\nconst confirmBase = 'https://agenteit.digitalcompass.agency/webhook/glm-hub-confirmar-solicitud';\nconst requesterName = String(payload.requesterName ?? 'Usuario GLM');\nconst requesterEmail = String(payload.requesterEmail ?? '');\nconst appName = String(payload.appName ?? 'Aplicación GLM');\nconst appCategory = String(payload.appCategory ?? '');\nconst requestId = String(payload.requestId ?? '');\nconst approvers = Array.isArray(payload.approvers) ? payload.approvers : [];\nif (approvers.length < 3) {\n return [{ json: {\n created: false,\n publicError: 'No se pudo completar el envío de la solicitud. Intenta nuevamente en unos minutos.',\n technicalError: `Se esperaban al menos 3 aprobadores y se recibieron ${approvers.length}.`\n } }];\n}\nreturn approvers.map((approver) => {\n const approveUrl = `${confirmBase}?token=${encode(String(approver.token ?? ''))}&decision=approved&app=${encode(appName)}`;\n const rejectUrl = `${confirmBase}?token=${encode(String(approver.token ?? ''))}&decision=rejected&app=${encode(appName)}`;\n const html = `
\"GomezLee
GLM HUB · SOLICITUD DE ACCESO

Una persona necesita acceso.

Hola ${escapeHtml(approver.name)}, revisa la siguiente solicitud.

Solicitante${escapeHtml(requesterName)}
Correo${escapeHtml(requesterEmail)}
Aplicación${escapeHtml(appName)}
Área${escapeHtml(appCategory)}

Por seguridad, cada botón abre una pantalla de confirmación. La primera decisión confirmada será definitiva para los tres destinatarios.

Aceptar solicitudRechazar solicitud
Solicitud ${escapeHtml(requestId)} · GomezLee Marketing · Uso interno
`;\n return { json: { created: true, requestId, sendTo: String(approver.email ?? ''), subject: `Solicitud de acceso | ${appName} | ${requesterName}`, html } };\n});" }, - "id": "5cf9121e-d2e8-4975-a833-a426c77d9389", + "id": "c4bd59ac-3233-4d09-81af-17f08b9325f5", "name": "Preparar correos de aprobación", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ - 1328, - 208 + 1440, + 64 ] }, { @@ -175,18 +173,18 @@ }, "options": {} }, - "id": "ee5ecbd9-95ab-42f2-a013-33eff66be5ea", + "id": "eae9bf96-c598-42e0-b4df-c58319e3c354", "name": "¿Solicitud registrada?", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ - 1568, - 208 + 1680, + 64 ] }, { "parameters": { - "sendTo": "=iaracena@gomezleemarketing.com", + "sendTo": "={{ $json.sendTo }}", "subject": "={{ $json.subject }}", "message": "={{ $json.html }}", "options": { @@ -194,13 +192,13 @@ "senderName": "GLM Hub" } }, - "id": "6fafb4fa-b7bc-46ed-b435-63cbd6c85538", + "id": "f3f7f82d-d96e-499f-a2d6-9e26f5496bb1", "name": "Enviar solicitud a aprobadores", "type": "n8n-nodes-base.gmail", "typeVersion": 2.1, "position": [ - 1808, - 112 + 1920, + -32 ], "webhookId": "7dc65e7b-4fb6-4a2f-b685-34171dd9ce1a", "credentials": { @@ -213,7 +211,7 @@ { "parameters": { "respondWith": "json", - "responseBody": "={{ { ok: true, message: 'La solicitud fue enviada a Isaac Aracena, José Leopoldo Gómez y Máximo Gómez.', requestId: $('Preparar correos de aprobación').first().json.requestId } }}", + "responseBody": "={{ { ok: true, message: 'La solicitud fue enviada correctamente a las personas responsables de aprobación.', requestId: $('Preparar correos de aprobación').first().json.requestId } }}", "options": { "responseCode": 200, "responseHeaders": { @@ -226,19 +224,19 @@ } } }, - "id": "2aea248a-8970-4439-9c5b-18800257d835", + "id": "af925eb2-9fb8-4261-8652-4e162969e512", "name": "Responder solicitud enviada", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ - 2048, - 112 + 2160, + -32 ] }, { "parameters": { "respondWith": "json", - "responseBody": "={{ { ok: false, error: $json.publicError || 'No pudimos enviar la solicitud. Intenta nuevamente.' } }}", + "responseBody": "={{ {\n ok: false,\n error: $json.publicError || 'No pudimos enviar la solicitud. Intenta nuevamente.'\n} }}", "options": { "responseCode": 409, "responseHeaders": { @@ -251,13 +249,13 @@ } } }, - "id": "b2affc40-34dd-47a5-ae2c-c2f9e8bb4fe6", + "id": "0a104b37-5336-44ce-953b-979ce5faaa87", "name": "Responder error al registrar", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ - 1808, - 320 + 1920, + 176 ] }, { @@ -266,13 +264,13 @@ "responseMode": "responseNode", "options": {} }, - "id": "d1276943-026e-414e-92eb-d9665fce1aa4", + "id": "569dfd6e-b94f-4db8-8c88-4a890cff1ea3", "name": "Webhook - Confirmar decisión", "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ - -240, - 832 + 432, + 896 ], "webhookId": "cba1c38c-37bc-4acb-bd61-48035604a5c4" }, @@ -280,13 +278,13 @@ "parameters": { "jsCode": "const query = $json.query ?? {};\nconst token = String(query.token ?? '').trim();\nconst decision = String(query.decision ?? '').trim().toLowerCase();\nconst appName = String(query.app ?? 'aplicación GLM').trim();\nconst valid = /^[0-9a-f]{64}$/i.test(token) && ['approved','rejected'].includes(decision);\nconst escapeHtml = (value) => String(value ?? '').replace(/[&<>\"']/g, (c) => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst actionUrl = 'https://agenteit.digitalcompass.agency/webhook/glm-hub-resolver-solicitud';\nconst approved = decision === 'approved';\nconst title = approved ? 'Confirmar aprobación' : 'Confirmar rechazo';\nconst actionLabel = approved ? 'Sí, aprobar solicitud' : 'Sí, rechazar solicitud';\nconst actionColor = approved ? '#6CC24A' : '#E87722';\nconst html = valid\n ? `${title} · GLM Hub
\"GomezLee

GLM HUB · DECISIÓN DE ACCESO

${title}

Vas a ${approved ? 'aprobar' : 'rechazar'} la solicitud de acceso a ${escapeHtml(appName)}. La decisión será definitiva y los otros enlaces quedarán sin efecto.

Cierra esta pestaña para cancelar sin registrar ninguna decisión.

`\n : `
\"GomezLee

Enlace no válido

El enlace está incompleto o no corresponde a una solicitud de GLM Hub.

`;\nreturn [{ json: { html } }];" }, - "id": "84f519ec-c313-42ae-ba6c-7fb612b7b510", + "id": "66f986d2-7c8b-4c25-9a5c-4310f5c37d3a", "name": "Construir página de confirmación", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ - -16, - 832 + 656, + 896 ] }, { @@ -313,13 +311,13 @@ } } }, - "id": "9fab6a61-b360-4bb9-9b07-6c8244ba40db", + "id": "abba0ac3-e1fc-4c2a-a6fc-ecba5e924cdf", "name": "Mostrar confirmación", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ - 208, - 832 + 880, + 896 ] }, { @@ -329,13 +327,13 @@ "responseMode": "responseNode", "options": {} }, - "id": "95a17231-e0aa-4004-9d0e-dd581488b524", + "id": "9baccfdb-9561-4e85-bf43-7993eb6bc65d", "name": "Webhook - Resolver solicitud", "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ - -240, - 1200 + -544, + 1584 ], "webhookId": "54eeee1b-b24b-46ae-84dc-70c4103e3a3a" }, @@ -343,13 +341,13 @@ "parameters": { "jsCode": "const source = $json.body ?? $json;\nlet payload = source;\nif (typeof payload === 'string') {\n try {\n payload = Object.fromEntries(new URLSearchParams(payload));\n } catch { payload = {}; }\n}\nconst token = String(payload?.token ?? '').trim();\nconst decision = String(payload?.decision ?? '').trim().toLowerCase();\nlet error = '';\nif (!/^[0-9a-f]{64}$/i.test(token)) error = 'El enlace de decisión no es válido.';\nelse if (!['approved','rejected'].includes(decision)) error = 'La decisión recibida no es válida.';\nreturn [{ json: { valid: !error, error, token, decision } }];" }, - "id": "87155b04-5944-43ae-beff-9310138b2863", + "id": "0760c143-2039-428e-85d2-f9fdec1ed4f7", "name": "Validar decisión", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ - -16, - 1200 + -320, + 1584 ] }, { @@ -377,26 +375,26 @@ }, "options": {} }, - "id": "876e85ab-fbcd-4090-a5a4-31daf40711f5", + "id": "dfacee52-d608-4086-b287-560ce870c980", "name": "¿Decisión válida?", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ - 208, - 1200 + -96, + 1584 ] }, { "parameters": { "jsCode": "const message = String($json.error ?? 'El enlace de decisión no es válido.');\nconst escapeHtml = (value) => String(value ?? '').replace(/[&<>\"']/g, (c) => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst html = `
\"GomezLee

No se pudo procesar

${escapeHtml(message)}

`;\nreturn [{ json: { html } }];" }, - "id": "c0527ef0-615e-463d-9e54-f7a942e02421", + "id": "8bebdbfd-3ee5-4a87-a0d4-c0b3a9bd17d4", "name": "Preparar decisión inválida", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ - 432, - 1392 + 128, + 1776 ] }, { @@ -423,13 +421,13 @@ } } }, - "id": "88bb2617-4e75-4f99-9aca-7c06bb28c86e", + "id": "bdaa54d2-e20d-4523-963b-1cc88f4d8669", "name": "Responder decisión inválida", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ - 672, - 1392 + 368, + 1776 ] }, { @@ -446,13 +444,20 @@ { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" + }, + { + "name": "Accept", + "value": "application/json" + }, + { + "name": "Content-Type", + "value": "application/json" } ] }, "sendBody": true, - "contentType": "raw", - "rawContentType": "application/json", - "body": "={{ JSON.stringify({ p_token: $json.token, p_decision: $json.decision }) }}", + "specifyBody": "json", + "jsonBody": "={{ {\n p_token: $('Validar decisión').first().json.token,\n p_decision: $('Validar decisión').first().json.decision\n} }}", "options": { "response": { "response": { @@ -463,26 +468,26 @@ "timeout": 30000 } }, - "id": "675cfecd-8a18-4c75-8e3f-aebb79390f34", + "id": "df9c350b-10f7-494a-8c5e-e0354c1606db", "name": "Registrar decisión en Supabase", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ - 432, - 1120 + 128, + 1504 ] }, { "parameters": { "jsCode": "const source = $input.first()?.json ?? {};\nlet payload = source.body ?? source;\nif (typeof payload === 'string') { try { payload = JSON.parse(payload); } catch { payload = {}; } }\nif (Array.isArray(payload)) payload = payload[0] ?? {};\nconst escapeHtml = (value) => String(value ?? '').replace(/[&<>\"']/g, (c) => ({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nconst status = String(payload.status ?? '');\nconst approved = status === 'approved';\nconst statusLabel = approved ? 'APROBADA' : status === 'rejected' ? 'RECHAZADA' : 'SIN PROCESAR';\nconst statusColor = approved ? '#6CC24A' : '#E87722';\nconst ok = payload.ok === true;\nconst alreadyDecided = payload.alreadyDecided === true;\nconst requesterName = String(payload.requesterName ?? '');\nconst requesterEmail = String(payload.requesterEmail ?? '');\nconst appName = String(payload.appName ?? 'Aplicación GLM');\nconst decidedByName = String(payload.decidedByName ?? '');\nconst decidedByEmail = String(payload.decidedByEmail ?? '');\nconst responseTitle = ok ? (approved ? 'Solicitud aprobada' : 'Solicitud rechazada') : alreadyDecided ? 'Solicitud ya atendida' : 'No se pudo procesar';\nconst responseMessage = ok\n ? `La decisión fue registrada. IT Support recibirá los datos para continuar con el acceso.`\n : alreadyDecided\n ? `Esta solicitud ya fue ${status === 'approved' ? 'aprobada' : 'rechazada'} por ${escapeHtml(decidedByName || decidedByEmail || 'otra persona')}. No se realizó ningún cambio adicional.`\n : escapeHtml(payload.error ?? 'El enlace no pudo ser validado.');\nconst responseHtml = `${responseTitle} · GLM Hub
\"GomezLee

GLM HUB · SOLICITUD DE ACCESO

${responseTitle}

${responseMessage}

Ya puedes cerrar esta pestaña.

`;\nconst itHtml = ok ? `
\"GomezLee
GLM HUB · DECISIÓN REGISTRADA

Solicitud ${statusLabel.toLowerCase()}.

IT Support debe continuar según la decisión indicada.

${statusLabel}
Persona solicitante${escapeHtml(requesterName)}
Correo solicitante${escapeHtml(requesterEmail)}
Aplicación${escapeHtml(appName)}
Decisión${statusLabel}
Decidido por${escapeHtml(decidedByName)}
Correo de quien decidió${escapeHtml(decidedByEmail)}
GomezLee Marketing · GLM Hub · Uso interno
` : '';\nreturn [{ json: { notifyIt: ok, responseHtml, itHtml, subject: `Acceso ${approved ? 'aprobado' : 'rechazado'} | ${appName} | ${requesterName}` } }];" }, - "id": "2c8fb533-fcc0-4958-a210-9498c55d98d2", + "id": "72ee2fcd-bf95-4542-aad1-90ca4d83a2e7", "name": "Preparar resultado de decisión", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ - 672, - 1120 + 1344, + 1520 ] }, { @@ -510,18 +515,18 @@ }, "options": {} }, - "id": "993d5ec8-1187-4e92-adce-8c9b41c08a91", + "id": "9f4e6707-3cb1-4c0e-833c-05be87602e07", "name": "¿Notificar a IT Support?", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ - 912, - 1120 + 1584, + 1520 ] }, { "parameters": { - "sendTo": "iaracena@gomezleemarketing.com", + "sendTo": "itsupport@gomezleemarketing.com", "subject": "={{ $json.subject }}", "message": "={{ $json.itHtml }}", "options": { @@ -529,13 +534,13 @@ "senderName": "GLM Hub" } }, - "id": "c9fbf481-045c-4f2b-80bd-2ad006b0af56", + "id": "56d73834-fc03-43c7-9844-dd4e691439b2", "name": "Enviar decisión a IT Support", "type": "n8n-nodes-base.gmail", "typeVersion": 2.1, "position": [ - 1152, - 1024 + 1824, + 1424 ], "webhookId": "234c8e3b-b904-41b8-8a74-9ca835f759df", "credentials": { @@ -569,26 +574,26 @@ } } }, - "id": "d16bcca2-1d7c-44e0-be65-658478a2623f", + "id": "e1d4a5ba-34fe-479a-a670-e07ebd87d0cf", "name": "Mostrar resultado final", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ - 1392, - 1120 + 2064, + 1520 ] }, { "parameters": { - "jsCode": "const source = $input.first()?.json ?? {};\n\nconst parseJson = (value) => {\n if (typeof value !== 'string') return value;\n try { return JSON.parse(value); } catch { return value; }\n};\n\nlet payload = source.body ?? source.data ?? source.response?.body ?? source;\npayload = parseJson(payload);\nif (Array.isArray(payload)) payload = payload[0] ?? {};\nif (payload && typeof payload === 'object' && payload.body !== undefined && payload.ok === undefined) {\n payload = parseJson(payload.body);\n if (Array.isArray(payload)) payload = payload[0] ?? {};\n}\n\nconst statusCode = Number(source.statusCode ?? source.status ?? source.response?.statusCode ?? 200);\nconst rawError = String(payload?.error ?? payload?.message ?? source?.message ?? '').trim();\nconst normalized = rawError.toLowerCase();\nconst code = String(payload?.code ?? '').toUpperCase();\n\nlet publicError = 'No pudimos registrar la solicitud. Intenta nuevamente.';\nif (code === 'PENDING_EXISTS' || normalized.includes('pendiente')) {\n publicError = 'Ya tienes una solicitud pendiente para esta aplicación.';\n} else if (normalized.includes('sesión') || statusCode === 401) {\n publicError = 'Tu sesión venció. Cierra sesión e inicia nuevamente.';\n} else if (normalized.includes('ya no está publicada') || normalized.includes('no está publicada')) {\n publicError = 'La aplicación seleccionada ya no está disponible.';\n} else if (normalized.includes('no está autorizado') || statusCode === 403) {\n publicError = 'Tu cuenta no está habilitada para enviar esta solicitud.';\n} else if (normalized.includes('administradores no necesitan')) {\n publicError = 'Tu cuenta administrativa no necesita solicitar acceso desde el Hub.';\n}\n\nreturn [{ json: {\n registered: payload?.ok === true && statusCode >= 200 && statusCode < 300,\n publicError,\n technicalError: rawError || `Respuesta HTTP ${statusCode} sin detalle`,\n statusCode,\n requestId: String(payload?.requestId ?? '')\n} }];" + "jsCode": "const source = $input.first()?.json ?? {};\n\nconst parseJson = (value) => {\n if (typeof value !== 'string') {\n return value;\n }\n\n try {\n return JSON.parse(value);\n } catch {\n return {};\n }\n};\n\nlet payload = source;\n\n// Compatibilidad por si n8n todavía entrega algún envoltorio.\nif (source.body !== undefined) {\n payload = source.body;\n} else if (source.data !== undefined) {\n payload = source.data;\n}\n\npayload = parseJson(payload);\n\nif (Array.isArray(payload)) {\n payload = payload[0] ?? {};\n}\n\nconst registered = payload?.ok === true;\nconst code = String(payload?.code ?? '').toUpperCase();\nconst internalMessage = String(\n payload?.error ??\n payload?.message ??\n ''\n).trim();\n\nconst normalizedMessage = internalMessage.toLowerCase();\n\nlet publicError = 'No pudimos enviar la solicitud. Intenta nuevamente.';\n\nif (\n code === 'PENDING_EXISTS' ||\n normalizedMessage.includes('solicitud pendiente')\n) {\n publicError = 'Ya tienes una solicitud pendiente para esta aplicación.';\n} else if (\n normalizedMessage.includes('sesión') ||\n normalizedMessage.includes('jwt')\n) {\n publicError = 'Tu sesión venció. Cierra sesión e inicia nuevamente.';\n} else if (\n normalizedMessage.includes('administradores no necesitan')\n) {\n publicError =\n 'Tu cuenta administrativa no necesita solicitar acceso desde el Hub.';\n} else if (\n normalizedMessage.includes('no está autorizado')\n) {\n publicError =\n 'Tu cuenta no está habilitada para enviar solicitudes de acceso.';\n} else if (\n normalizedMessage.includes('ya no está publicada')\n) {\n publicError =\n 'La aplicación seleccionada ya no está disponible.';\n}\n\nreturn [\n {\n json: {\n registered,\n publicError,\n internalMessage,\n requestId: String(payload?.requestId ?? ''),\n requesterName: String(payload?.requesterName ?? ''),\n requesterEmail: String(payload?.requesterEmail ?? ''),\n appName: String(payload?.appName ?? ''),\n appCategory: String(payload?.appCategory ?? '')\n }\n }\n];" }, - "id": "1f46de7c-f14a-44b1-8852-cf1a9d4d6bd5", + "id": "e2cc29db-5db2-46ea-a388-054c320ecfc2", "name": "Confirmar registro de solicitud", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ - 640, - 288 + 512, + 112 ] }, { @@ -616,13 +621,13 @@ }, "options": {} }, - "id": "0b0d9f6a-2d91-4d8f-b4f8-b20111a4d136", + "id": "7f6803be-bc3a-45e1-b1a4-c04c33ca25b9", "name": "¿Solicitud registrada en Supabase?", "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ - 864, - 288 + 736, + 112 ] }, { @@ -639,34 +644,137 @@ { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" + }, + { + "name": "Accept", + "value": "application/json" + }, + { + "name": "Content-Type", + "value": "application/json" } ] }, "sendBody": true, - "contentType": "raw", - "rawContentType": "application/json", - "body": "={{ JSON.stringify({ p_request_id: $json.requestId }) }}", + "specifyBody": "json", + "jsonBody": "={{ {\n p_request_id: $('Confirmar registro de solicitud').first().json.requestId\n} }}", "options": { "response": { "response": { "neverError": true, - "responseFormat": "json", - "fullResponse": true + "responseFormat": "json" } }, "timeout": 30000 } }, - "id": "9203157e-c9e7-4ad3-bb35-ae683c594f6b", + "id": "d684c268-bbd8-4a3b-8aab-b21510423c95", "name": "Emitir enlaces de aprobación", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ - 1088, - 208 + 1200, + 64 ] + }, + { + "parameters": { + "content": "## 1. RECEPCIÓN Y VALIDACIÓN\n\nEste bloque recibe desde GLM Hub una nueva solicitud de acceso y valida que la información obligatoria sea correcta.\n\n- Verifica los datos del usuario y de la aplicación solicitada.\n- Rechaza inmediatamente solicitudes incompletas o inválidas.\n- Solo las solicitudes válidas continúan hacia el registro en Supabase.", + "height": 560, + "width": 1104, + "color": 6 + }, + "type": "n8n-nodes-base.stickyNote", + "typeVersion": 1, + "position": [ + -1024, + -16 + ], + "id": "55489511-4594-4d60-8b68-87f0210e4b9e", + "name": "Sticky Note" + }, + { + "parameters": { + "content": "## 2. REGISTRO DE LA SOLICITUD\n\nGuarda la solicitud de acceso en Supabase y confirma que el registro se haya creado correctamente.\n\n- Almacena la información de la solicitud y su estado inicial.\n- Recupera y normaliza los datos devueltos por Supabase.\n- Solo permite continuar cuando existe una confirmación válida del registro.", + "height": 384, + "width": 736, + "color": 5 + }, + "type": "n8n-nodes-base.stickyNote", + "typeVersion": 1, + "position": [ + 192, + -64 + ], + "id": "729f2bb0-c1f2-424f-ae39-bf69ea94317c", + "name": "Sticky Note1" + }, + { + "parameters": { + "content": "## 3. ENVÍO A LOS APROBADORES\n\nGenera los enlaces de decisión, prepara los correos y notifica a las personas responsables de aprobar o rechazar la solicitud.\n\n- Mantiene como aprobadores base a Isaac Aracena, José Leopoldo Gómez y Máximo Gómez.\n- Agrega automáticamente al jefe inmediato del solicitante cuando existe `supervisor_email` en `empleados_glm`.\n- Evita duplicados cuando el jefe ya es uno de los aprobadores base.\n- Construye enlaces únicos para la aprobación y el rechazo.\n- Envía un correo personalizado a cada aprobador mediante Gmail.\n- La primera decisión registrada continúa siendo definitiva para todos los enlaces.", + "height": 560, + "width": 1264, + "color": "#357C27" + }, + "type": "n8n-nodes-base.stickyNote", + "typeVersion": 1, + "position": [ + 1104, + -224 + ], + "id": "32a9a9ad-bd7c-4d67-93db-d6537fd3a978", + "name": "Sticky Note2" + }, + { + "parameters": { + "content": "## 4. CONFIRMACIÓN DE LA DECISIÓN\n\nRecibe al aprobador desde el enlace enviado por correo y muestra una página previa antes de registrar la decisión definitiva.\n\n- Lee los parámetros incluidos en el enlace de aprobación o rechazo.\n- Construye una página con los datos de la solicitud.\n- Solicita una confirmación final para evitar decisiones accidentales.", + "height": 352, + "width": 1062, + "color": "#8F622D" + }, + "type": "n8n-nodes-base.stickyNote", + "typeVersion": 1, + "position": [ + 192, + 720 + ], + "id": "305bb9cd-16f5-4f87-a3b4-f6009a683085", + "name": "Sticky Note3" + }, + { + "parameters": { + "content": "## 5. VALIDACIÓN Y REGISTRO DE LA DECISIÓN\n\nValida la decisión confirmada por el aprobador y actualiza la solicitud correspondiente en Supabase.\n\n- Comprueba que la solicitud, el enlace y la decisión sean válidos.\n- Registra en Supabase la aprobación o el rechazo.\n- Impide procesar decisiones incorrectas, incompletas o manipuladas.\n- Muestra una respuesta controlada cuando la decisión no puede ser aceptada.", + "height": 624, + "width": 1184, + "color": "#52500F" + }, + "type": "n8n-nodes-base.stickyNote", + "typeVersion": 1, + "position": [ + -624, + 1328 + ], + "id": "0289d494-ec4a-4f09-89ed-02006e0fcc4e", + "name": "Sticky Note4" + }, + { + "parameters": { + "content": "## 6. NOTIFICACIÓN Y RESULTADO FINAL\n\nPrepara el resultado de la decisión, determina si se necesita intervención de IT Support y finaliza el proceso.\n\n- Construye el mensaje final de aprobación o rechazo.\n- Evalúa si la decisión debe notificarse al equipo de IT.\n- Envía por Gmail la información necesaria cuando corresponde.\n- Muestra al aprobador el resultado definitivo de la operación.", + "height": 432, + "width": 1104, + "color": "#276D4F" + }, + "type": "n8n-nodes-base.stickyNote", + "typeVersion": 1, + "position": [ + 1184, + 1264 + ], + "id": "7881e095-8b12-4b96-83fd-a174d8dd0703", + "name": "Sticky Note5" } ], + "pinData": {}, "connections": { "Webhook - Solicitar acceso": { "main": [ @@ -927,7 +1035,14 @@ "active": true, "settings": { "executionOrder": "v1", - "binaryMode": "separate" + "binaryMode": "separate", + "availableInMCP": true }, + "versionId": "dc3ed690-5728-414e-a322-137e35e8f9b6", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "b4b77b17af092830e794eef639ce2f6d7daccf7eddc075060b03b3b6545aac70" + }, + "id": "RaNkDfE2YCrZgCbx", "tags": [] } \ No newline at end of file diff --git a/scripts/build-static-esm.mjs b/scripts/build-static-esm.mjs index 93dccb5..1974181 100644 --- a/scripts/build-static-esm.mjs +++ b/scripts/build-static-esm.mjs @@ -6,6 +6,7 @@ const root = path.resolve(new URL('..', import.meta.url).pathname); const srcDir = path.join(root, 'src'); const distDir = path.join(root, 'dist'); const assetsDir = path.join(distDir, 'assets'); +const BUILD_VERSION = '20260814-single-access-status'; const env = { VITE_SUPABASE_URL: 'https://dbit.digitalcompass.agency', @@ -29,7 +30,7 @@ function fixLocalImports(code) { .replace(/^import\s+["']\.\/styles\.css["'];?\s*$/gm, '') .replace(/(from\s+["'])(\.\.?\/[^"']+)(["'])/g, (_m, start, spec, end) => { if (/\.(?:js|mjs|cjs|json|css)$/.test(spec)) return `${start}${spec}${end}`; - return `${start}${spec}.js${end}`; + return `${start}${spec}.js?v=${BUILD_VERSION}${end}`; }); } @@ -76,7 +77,7 @@ const indexHtml = ` GLM Hub — GomezLee Marketing - + - + `; fs.writeFileSync(path.join(distDir, 'index.html'), indexHtml); diff --git a/src/App.tsx b/src/App.tsx index e462901..a4a3de7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -35,6 +35,7 @@ import { deleteHubApp, fetchHubApps, fetchHubData, + fetchMyAppAccess, migrateLocalAppsIfNeeded, recordRecent, saveHubApp, @@ -536,14 +537,29 @@ function MobileNav({ user, view, onNavigate, onLogout }: MobileNavProps) { ); } +type AccessState = boolean | null; + +function AccessIndicator({ hasAccess }: { hasAccess: AccessState }) { + const label = hasAccess === null ? "Verificando acceso" : hasAccess ? "Disponible" : "Sin acceso"; + const stateClass = hasAccess === null ? "access-indicator--checking" : hasAccess ? "access-indicator--granted" : "access-indicator--denied"; + + return ( + + + ); +} + interface QuickLaunchProps { app: HubApp; isFavorite: boolean; + hasAccess: AccessState; onActivate: (app: HubApp) => void; onFavorite: (appId: string) => void; } -function QuickLaunch({ app, isFavorite, onActivate, onFavorite }: QuickLaunchProps) { +function QuickLaunch({ app, isFavorite, hasAccess, onActivate, onFavorite }: QuickLaunchProps) { const available = Boolean(getSafeUrl(app.url)); return (
@@ -560,7 +576,10 @@ function QuickLaunch({ app, isFavorite, onActivate, onFavorite }: QuickLaunchPro
- {app.category} +
+ {app.category} + +

{app.name}

{app.description}

@@ -576,11 +595,12 @@ interface DirectoryRowProps { app: HubApp; index: number; isFavorite: boolean; + hasAccess: AccessState; onActivate: (app: HubApp) => void; onFavorite: (appId: string) => void; } -function DirectoryRow({ app, index, isFavorite, onActivate, onFavorite }: DirectoryRowProps) { +function DirectoryRow({ app, index, isFavorite, hasAccess, onActivate, onFavorite }: DirectoryRowProps) { const available = Boolean(getSafeUrl(app.url)); return (
@@ -591,9 +611,8 @@ function DirectoryRow({ app, index, isFavorite, onActivate, onFavorite }: Direct

{app.description}

{app.category} - -