diff --git a/docs/actas/index.md b/docs/actas/index.md index 952929b..b3e8282 100644 --- a/docs/actas/index.md +++ b/docs/actas/index.md @@ -42,7 +42,7 @@ El acta de ensamble no deja elegir un módulo sin aprobar, sin integración o ya | Acta | Qué registra | Procedimiento | |---|---|---| | [Instalación en campo](../formularios/instalacion.html) | Una por unidad y vehículo: sitio, equipo, alimentación 24 V, antenas, RTK FIX, señal 4G, fotos | [Checklist de puesta en marcha](../procedimientos/v5-checklist-puesta-en-marcha.md) · [Sitios](../sitios/index.md) | -| [Diagnóstico en campo](../formularios/diagnostico.html) | Una por visita; muestra las visitas anteriores y admite fotos desde el teléfono | [Diagnóstico en campo](../diagnostico/procedimiento-diagnostico-campo.md) · [Tablero de campo](../diagnostico/tablero-campo.html) | +| [Diagnóstico en campo](../formularios/diagnostico.html) | Una por visita; muestra las visitas anteriores y admite fotos desde el teléfono | [Diagnóstico en campo](../diagnostico/procedimiento-diagnostico-campo.md) · [Tablero de campo](../tableros/campo.md) | | [Envío](../formularios/envio.html) · [Recepción](../formularios/recepcion.html) | El tramo entre el banco y el puerto | [Ciclo de vida](../procedimientos/ciclo-de-vida.md) | | [Daño o incidente](../formularios/dano.html) | Cualquier serie; la marca en todos los formularios. «Reparada» la levanta, «Baja» la hace permanente | [Ciclo de vida](../procedimientos/ciclo-de-vida.md#dano-o-incidente) | @@ -51,7 +51,7 @@ El acta de ensamble no deja elegir un módulo sin aprobar, sin integración o ya 1. Abre el formulario y elige la serie (o los módulos, en integración y ensamble). 2. Llena cada sección conforme avanzas. Se guarda solo en el navegador: al reabrir con la misma serie recuperas lo escrito. 3. Marca el resultado (Aprobada / Falla), escribe tu nombre y confirma que seguiste el procedimiento. -4. Pulsa Enviar acta firmada. Queda en el servidor y en el [tablero](../tablero.html). +4. Pulsa Enviar acta firmada. Queda en el servidor y en el [tablero](../tableros/actas.md). La serie PRUEBA sirve para practicar: no cuenta y se puede reenviar. diff --git a/docs/admin.html b/docs/admin.html index d73d635..a6d4dd0 100644 --- a/docs/admin.html +++ b/docs/admin.html @@ -4,21 +4,22 @@ Administración — HBOX +

Administración de actas

Solo para el administrador.

-
← TableroUsuarios y equipo →
+
← Estado de actasUsuarios y equipo →

Comprobando permisos…

@@ -47,7 +48,7 @@
- 👁 Ver lo que escribí + Ver lo que escribí
@@ -72,7 +73,7 @@

Si olvidaste tu contraseña

No hay recuperación por correo: pídele a Leo que te la restablezca desde esta misma página. - Si todavía no tienes acceso, pídeselo a Leo (Administración → Usuarios y equipo). + Si todavía no tienes acceso, pídeselo a Leo (Administración → Usuarios y equipo).

@@ -94,7 +95,7 @@ function aviso(el, texto, bien) { yo = j.user || ''; $('quien').innerHTML = yo ? 'Entraste como ' + yo + '' + (j.admin ? ' · administrador' : '') - : '⚠ No puedo identificarte. Vuelve a entrar al sitio y recarga esta página.'; + : 'No puedo identificarte. Vuelve a entrar al sitio y recarga esta página.'; if (j.admin) { $('bloqueAdmin').style.display = ''; try { @@ -130,7 +131,7 @@ $('nueva').addEventListener('input', () => { $('ver').addEventListener('click', () => { const t = $('nueva').type === 'password' ? 'text' : 'password'; $('nueva').type = t; $('confirma').type = t; $('actual').type = t; - $('ver').textContent = t === 'text' ? '🙈 Ocultar' : '👁 Ver lo que escribí'; + $('ver').textContent = t === 'text' ? 'Ocultar' : 'Ver lo que escribí'; }); const AVISO_SESION = @@ -148,7 +149,7 @@ $('guardar').addEventListener('click', async () => { }); const j = await r.json(); if (!r.ok || !j.ok) throw new Error(j.error || ('HTTP ' + r.status)); - aviso($('msg'), '✓ Contraseña cambiada.' + AVISO_SESION, true); + aviso($('msg'), 'Contraseña cambiada.' + AVISO_SESION, true); $('actual').value = $('nueva').value = $('confirma').value = ''; $('barra').style.width = '0'; } catch (e) { @@ -169,7 +170,7 @@ $('resetear').addEventListener('click', async () => { }); const j = await r.json(); if (!r.ok || !j.ok) throw new Error(j.error || ('HTTP ' + r.status)); - aviso($('msgR'), '✓ Contraseña de ' + u + ' restablecida. Pásasela en persona o por ' + aviso($('msgR'), 'Contraseña de ' + u + ' restablecida. Pásasela en persona o por ' + 'mensaje directo, y dile que la cambie aquí mismo cuando entre.' + (u === yo ? AVISO_SESION : ''), true); $('nuevaR').value = ''; diff --git a/docs/descargas/index.md b/docs/descargas/index.md index 77a5f8c..156fa1f 100644 --- a/docs/descargas/index.md +++ b/docs/descargas/index.md @@ -15,7 +15,7 @@ version: "2.3" | Módem 4G NTRIP Master | Parámetros `$$$AS+…` | Terminal serie por el USB XBEE | [Módem 4G](#parametros-del-modem-4g-ntrip-master) | | simpleRTK2B Pro (ZED-F9P) | Configuración u-center y firmware u-blox | u-center por el USB POWER+GPS | [ZED-F9P](#firmware-y-configuracion-del-simplertk2b-pro-zed-f9p) | -Cada carga se registra en el [acta de reflasheo](../formularios/reflasheo.html) y queda en el [expediente](../unidad.html) con las capturas de antes y después. +Cada carga se registra en el [acta de reflasheo](../formularios/reflasheo.html) y queda en el [expediente](../tableros/unidad.md) con las capturas de antes y después. ## Verifica el SHA-256 diff --git a/docs/diagnostico/procedimiento-diagnostico-campo.md b/docs/diagnostico/procedimiento-diagnostico-campo.md index 6b8102c..4d9e165 100644 --- a/docs/diagnostico/procedimiento-diagnostico-campo.md +++ b/docs/diagnostico/procedimiento-diagnostico-campo.md @@ -152,7 +152,7 @@ Elige lo que observaste, no lo que supones. "No está claro" es una respuesta v ## 8. Después de enviar el acta -- Queda en el servidor con tu nombre, hora y fotos, y aparece en el [tablero de campo](tablero-campo.html). +- Queda en el servidor con tu nombre, hora y fotos, y aparece en el [tablero de campo](../tableros/campo.md). - Quien abra el acta de esa unidad verá tu visita antes de empezar. - Sin señal, el acta se guarda sola en el teléfono; fotos y envío necesitan datos. Si falla, reintenta desde el mismo formulario. - Unidad desmontada: sigue en [diagnóstico en banco](../procedimientos/diagnostico-banco.md). Tarjeta: [manual V3](../manuales/manual-tarjeta-V3.md). diff --git a/docs/diagnostico/tablero-campo.html b/docs/diagnostico/tablero-campo.html index 69caf26..dd73b79 100644 --- a/docs/diagnostico/tablero-campo.html +++ b/docs/diagnostico/tablero-campo.html @@ -1,200 +1,18 @@ + -Tablero de campo — diagnósticos HBOX - + +Visitas de campo - Drogheda + + + -
-
-

Tablero de campo — diagnósticos HBOX

Cargando…
-
- ← Documentación - Nueva acta de diagnóstico - -
-
-
-
- - +

Este tablero ahora está dentro del sitio: Visitas de campo.

diff --git a/docs/fonts/OFL-Atkinson-Hyperlegible-Mono.txt b/docs/fonts/OFL-Atkinson-Hyperlegible-Mono.txt new file mode 100644 index 0000000..8d2ce88 --- /dev/null +++ b/docs/fonts/OFL-Atkinson-Hyperlegible-Mono.txt @@ -0,0 +1,93 @@ +Copyright 2020-2024 The Atkinson Hyperlegible Mono Project Authors (https://github.com/googlefonts/atkinson-hyperlegible-next-mono) AtkinsonHyperlegibleMono-Italic[wght].ttf: Copyright 2020-2024 The Atkinson Hyperlegible Mono Project Authors (https://github.com/googlefonts/atkinson-hyperlegible-next-mono) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/fonts/OFL-Atkinson-Hyperlegible-Next.txt b/docs/fonts/OFL-Atkinson-Hyperlegible-Next.txt new file mode 100644 index 0000000..9459440 --- /dev/null +++ b/docs/fonts/OFL-Atkinson-Hyperlegible-Next.txt @@ -0,0 +1,93 @@ +Copyright 2020-2024 The Atkinson Hyperlegible Next Project Authors (https://github.com/googlefonts/atkinson-hyperlegible-next) AtkinsonHyperlegibleNext-Italic[wght].ttf: Copyright 2020-2024 The Atkinson Hyperlegible Next Project Authors (https://github.com/googlefonts/atkinson-hyperlegible-next) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/fonts/OFL-League-Spartan.txt b/docs/fonts/OFL-League-Spartan.txt new file mode 100644 index 0000000..a3dad34 --- /dev/null +++ b/docs/fonts/OFL-League-Spartan.txt @@ -0,0 +1,93 @@ +Copyright 2020 The League Spartan Project Authors (https://github.com/theleagueof/league-spartan) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/fonts/atkinson-hyperlegible-mono-latin.woff2 b/docs/fonts/atkinson-hyperlegible-mono-latin.woff2 new file mode 100644 index 0000000..f5c1081 Binary files /dev/null and b/docs/fonts/atkinson-hyperlegible-mono-latin.woff2 differ diff --git a/docs/fonts/atkinson-hyperlegible-next-latin.woff2 b/docs/fonts/atkinson-hyperlegible-next-latin.woff2 new file mode 100644 index 0000000..a9ca4bd Binary files /dev/null and b/docs/fonts/atkinson-hyperlegible-next-latin.woff2 differ diff --git a/docs/fonts/league-spartan-latin.woff2 b/docs/fonts/league-spartan-latin.woff2 new file mode 100644 index 0000000..92f6e10 Binary files /dev/null and b/docs/fonts/league-spartan-latin.woff2 differ diff --git a/docs/formularios/acta.css b/docs/formularios/acta.css index a8ccac5..5e6ed7c 100644 --- a/docs/formularios/acta.css +++ b/docs/formularios/acta.css @@ -1,75 +1,112 @@ -/* Estilo compartido de las actas HBOX — pensado para tablet/laptop en el banco */ -:root{ - --naranja:#e8590c; --naranja-suave:#fff1e8; --tinta:#1d1c19; --tinta2:#5a564d; - --linea:#e2ddd2; --papel:#faf8f4; --tarjeta:#ffffff; --ok:#2f9e44; --falla:#e03131; - --ok-bg:#ebfbee; --falla-bg:#fff5f5; --aviso:#f08c00; --aviso-bg:#fff9db; +/* Estilo compartido de las actas HBOX — pensado para tablet/laptop en el banco y en el patio. + Colores y letras: stylesheets/helgen.css (oscuro por omisión; claro si la persona lo eligió: + js/tema.js pone y agrega el botón de modo al encabezado). */ +@import url("../stylesheets/helgen.css"); + +:root { + /* nombres de siempre, ahora sobre los tokens de Helgen (los usan acta.js y las páginas) */ + --naranja: var(--hg-liga); + --naranja-suave: var(--hg-acento-suave); + --tinta: var(--hg-texto); + --tinta2: var(--hg-texto-2); + --linea: var(--hg-linea); + --papel: var(--hg-fondo); + --tarjeta: var(--hg-plano); + --ok: var(--hg-hecho); + --falla: var(--hg-bloqueado); + --ok-bg: var(--hg-hecho-bg); + --falla-bg: var(--hg-bloqueado-bg); + --aviso: var(--hg-aviso); + --aviso-bg: var(--hg-aviso-bg); + --plane: var(--hg-liga); + --crit: var(--hg-bloqueado); + --crit-soft: var(--hg-bloqueado-bg); } + *{box-sizing:border-box} -body{margin:0;background:var(--papel);color:var(--tinta); - font:16px/1.5 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;-webkit-text-size-adjust:100%} +body{margin:0;background:var(--hg-fondo);color:var(--hg-texto); + font:16px/1.5 var(--hg-fuente);-webkit-text-size-adjust:100%; + -webkit-font-smoothing:antialiased} +a{color:var(--hg-liga)} +:focus-visible{outline:2px solid var(--hg-foco);outline-offset:2px} +code{font-family:var(--hg-fuente-mono);font-size:.9em;background:var(--hg-elevado);border-radius:4px;padding:0 .3em} .wrap{max-width:820px;margin:0 auto;padding:16px 16px 120px} -header.top{background:#2C3C5B;color:#fff;padding:16px;border-radius:12px;margin-bottom:16px} -header.top h1{margin:0;font-size:20px} -header.top p{margin:4px 0 0;color:#d7d2c8;font-size:14px} -.borrador{background:var(--aviso-bg);border:1px solid var(--aviso);color:#a5620a; +header.top{position:relative;background:var(--hg-barra);color:var(--hg-texto);border:1px solid var(--hg-linea); + padding:16px 58px 16px 16px;border-radius:12px;margin-bottom:16px} +html[data-tema="claro"] header.top{background:var(--hg-indigo);border-color:var(--hg-indigo);color:#fff} +header.top h1{margin:0;font-family:var(--hg-fuente-titulo);font-weight:600;font-size:23px;line-height:1.15;letter-spacing:0} +header.top p{margin:6px 0 0;color:var(--hg-texto-2);font-size:14px} +html[data-tema="claro"] header.top p{color:rgba(255,255,255,.78)} +/* botón de modo claro/oscuro (js/tema.js) */ +.hg-modo{position:absolute;top:12px;right:12px;width:34px;height:34px;display:grid;place-items:center; + border-radius:8px;border:1px solid var(--hg-linea-2);background:transparent;color:var(--hg-texto-2);cursor:pointer;padding:0} +.hg-modo:hover{color:var(--hg-texto-fuerte);background:var(--hg-elevado)} +html[data-tema="claro"] .hg-modo{border-color:rgba(255,255,255,.35);color:rgba(255,255,255,.85)} +html[data-tema="claro"] .hg-modo:hover{background:rgba(255,255,255,.12);color:#fff} + +.borrador{background:var(--aviso-bg);border:1px solid color-mix(in srgb,var(--aviso) 45%,transparent);color:var(--aviso); padding:10px 14px;border-radius:10px;margin-bottom:16px;font-size:14px} .datos{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:8px} @media(max-width:560px){.datos{grid-template-columns:1fr}} -label{display:block;font-weight:600;font-size:14px;margin-bottom:4px} -input[type=text],input[type=number],select,textarea{ - width:100%;padding:11px 12px;border:1px solid var(--linea);border-radius:9px; - font-size:16px;background:#fff;color:var(--tinta)} -input:focus,select:focus,textarea:focus{outline:2px solid var(--naranja);border-color:var(--naranja)} -section.paso{background:var(--tarjeta);border:1px solid var(--linea);border-radius:12px; +label{display:block;font-weight:600;font-size:14px;margin-bottom:5px;color:var(--hg-texto-2)} +input[type=text],input[type=number],input[type=password],input[type=email],input[type=tel],select,textarea{ + width:100%;padding:11px 12px;border:1px solid var(--hg-linea-2);border-radius:9px; + font:inherit;font-size:16px;background:var(--hg-plano);color:var(--hg-texto)} +input::placeholder,textarea::placeholder{color:var(--hg-texto-3)} +input:focus,select:focus,textarea:focus{outline:2px solid var(--hg-foco);outline-offset:1px;border-color:transparent} +section.paso{background:var(--hg-plano-2);border:1px solid var(--hg-linea);border-radius:12px; padding:14px 16px;margin:14px 0} -section.paso h2{margin:0 0 4px;font-size:17px;color:var(--naranja)} -section.paso .sub{color:var(--tinta2);font-size:13.5px;margin:0 0 10px} -.item{padding:10px 0;border-top:1px solid var(--linea)} +section.paso h2{margin:0 0 4px;font-family:var(--hg-fuente-titulo);font-weight:600;font-size:19px;line-height:1.2;color:var(--hg-texto-fuerte)} +section.paso .sub{color:var(--hg-texto-2);font-size:14px;margin:0 0 10px} +.item{padding:10px 0;border-top:1px solid var(--hg-linea)} .item:first-of-type{border-top:0} .chk{display:flex;gap:12px;align-items:flex-start;cursor:pointer} -.chk input{width:26px;height:26px;margin:1px 0 0;flex:0 0 auto;accent-color:var(--naranja)} +.chk input{width:26px;height:26px;margin:1px 0 0;flex:0 0 auto;accent-color:var(--hg-teal)} .chk .txt{flex:1} .medida{display:flex;flex-wrap:wrap;gap:8px 12px;align-items:center} .medida .txt{flex:1 1 100%;font-weight:600} -.medida .esp{flex:1 1 100%;color:var(--tinta2);font-size:13px;margin-top:-2px} +.medida .esp{flex:1 1 100%;color:var(--hg-texto-2);font-size:13px;margin-top:-2px} .medida input{max-width:150px} -.medida .u{color:var(--tinta2)} -.nota-item{color:var(--tinta2);font-size:14px} -.aviso{background:var(--aviso-bg);border-left:3px solid var(--aviso);padding:8px 12px; - border-radius:0 8px 8px 0;font-size:13.5px;margin:6px 0} -.firma{background:var(--naranja-suave);border:1px solid #ffd8a8} +.medida .u{color:var(--hg-texto-2)} +.nota-item{color:var(--hg-texto-2);font-size:14px} +.aviso{background:var(--aviso-bg);border:1px solid color-mix(in srgb,var(--aviso) 35%,transparent);padding:8px 12px; + border-radius:8px;font-size:13.5px;margin:6px 0;color:var(--hg-texto)} +.firma{background:var(--hg-plano)} .resultado{display:flex;gap:10px;margin-top:6px} -.resultado label{flex:1;border:2px solid var(--linea);border-radius:10px;padding:12px; - text-align:center;cursor:pointer;font-weight:700;margin:0} +.resultado label{flex:1;border:2px solid var(--hg-linea-2);border-radius:10px;padding:12px; + text-align:center;cursor:pointer;font-weight:700;margin:0;color:var(--hg-texto)} .resultado input{position:absolute;opacity:0} .resultado label:has(input:checked).ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ok)} .resultado label:has(input:checked).falla{border-color:var(--falla);background:var(--falla-bg);color:var(--falla)} -.barra{position:fixed;left:0;right:0;bottom:0;background:#fff;border-top:1px solid var(--linea); +.resultado label:has(input:focus-visible){outline:2px solid var(--hg-foco);outline-offset:2px} +.barra{position:fixed;left:0;right:0;bottom:0;background:var(--hg-barra);border-top:1px solid var(--hg-linea); padding:12px 16px;display:flex;gap:12px;align-items:center;justify-content:space-between} -.barra .estado{font-size:13px;color:var(--tinta2)} -button.enviar{background:var(--naranja);color:#fff;border:0;border-radius:10px; - padding:13px 22px;font-size:16px;font-weight:700;cursor:pointer} +.barra .estado{font-size:13px;color:var(--hg-texto-2)} +button.enviar{background:var(--hg-acento);color:var(--hg-sobre-acento);border:0;border-radius:10px; + padding:13px 22px;font:inherit;font-size:16px;font-weight:700;cursor:pointer} +button.enviar:hover:not(:disabled){filter:brightness(1.07)} button.enviar:disabled{opacity:.5;cursor:not-allowed} .msg{padding:12px 14px;border-radius:10px;margin-top:12px;font-weight:600;display:none} -.msg.ok{display:block;background:var(--ok-bg);color:var(--ok);border:1px solid var(--ok)} -.msg.err{display:block;background:var(--falla-bg);color:var(--falla);border:1px solid var(--falla)} +.msg.ok{display:block;background:var(--ok-bg);color:var(--ok);border:1px solid color-mix(in srgb,var(--ok) 40%,transparent)} +.msg.err{display:block;background:var(--falla-bg);color:var(--falla);border:1px solid color-mix(in srgb,var(--falla) 45%,transparent)} .enviada{opacity:.6;pointer-events:none} -a.volver{color:var(--naranja);font-size:14px;text-decoration:none} -button.limpiar{background:#fff;color:var(--tinta2);border:1px solid var(--linea); - border-radius:10px;padding:13px 16px;font-size:15px;cursor:pointer} -button.limpiar:hover{border-color:var(--naranja);color:var(--naranja)} +a.volver{color:var(--hg-liga);font-size:14px;text-decoration:none} +a.volver:hover{text-decoration:underline} +button.limpiar{background:transparent;color:var(--hg-texto-2);border:1px solid var(--hg-linea-2); + border-radius:10px;padding:13px 16px;font:inherit;font-size:15px;cursor:pointer} +button.limpiar:hover{border-color:var(--hg-linea-2);background:var(--hg-elevado);color:var(--hg-texto-fuerte)} /* ---- actas compuestas (ensamble / integración): estado de cada módulo ---- */ .datos{grid-template-columns:repeat(auto-fit,minmax(240px,1fr))} -.datos .serie-calc{grid-column:1 / -1;background:var(--naranja-suave);border:1px solid #ffd8a8;border-radius:10px;padding:10px 12px} -.datos .serie-calc input{font-weight:700;font-size:20px;letter-spacing:.04em;background:#fff} -.badge{display:inline-block;margin-top:6px;font-size:13px;font-weight:700;padding:3px 10px;border-radius:99px;background:#f1efe9;color:var(--tinta2)} +.datos .serie-calc{grid-column:1 / -1;background:var(--hg-plano);border:1px solid var(--hg-linea);border-radius:10px;padding:10px 12px} +.datos .serie-calc input{font-family:var(--hg-fuente-mono);font-weight:600;font-size:20px;letter-spacing:.04em;background:var(--hg-plano-2)} +.badge{display:inline-block;margin-top:6px;font-size:13px;font-weight:600;padding:3px 10px;border-radius:6px;background:var(--hg-pend-bg);color:var(--hg-texto-2)} .badge.ok{background:var(--ok-bg);color:var(--ok)} .badge.falla{background:var(--falla-bg);color:var(--falla)} -.badge.pend{background:#f1efe9;color:var(--tinta2)} +.badge.pend{background:var(--hg-pend-bg);color:var(--hg-texto-2)} .radios{display:flex;flex-wrap:wrap;gap:8px 16px;margin-top:4px} -.radios .rad{font-weight:500;display:flex;align-items:center;gap:6px;cursor:pointer} -.radios input{width:22px;height:22px;accent-color:var(--naranja)} +.radios .rad{font-weight:500;display:flex;align-items:center;gap:6px;cursor:pointer;color:var(--hg-texto)} +.radios input{width:22px;height:22px;accent-color:var(--hg-teal)} /* ================= actas de campo (diagnóstico / instalación) ================= */ @@ -77,41 +114,42 @@ button.limpiar:hover{border-color:var(--naranja);color:var(--naranja)} .oculto{display:none !important} /* la unidad elegida: máquina y terminal, para que el técnico confirme que abrió la correcta */ -.ficha-unidad:not(:empty){margin-top:8px;padding:8px 10px;background:var(--naranja-suave); - border:1px solid #ffd8a8;border-radius:8px;font-size:13.5px;line-height:1.35} +.ficha-unidad:not(:empty){margin-top:8px;padding:8px 10px;background:var(--hg-plano); + border:1px solid var(--hg-linea);border-radius:8px;font-size:13.5px;line-height:1.35} /* historial de visitas anteriores a la misma unidad */ -.hist{margin:0 0 14px;padding:12px 14px;background:#eef3f8;border:1px solid #c9dcec; - border-radius:10px;font-size:14px;color:#1b3b57} +.hist{margin:0 0 14px;padding:12px 14px;background:var(--hg-info-bg);border:1px solid color-mix(in srgb,var(--hg-info) 30%,transparent); + border-radius:10px;font-size:14px;color:var(--hg-texto)} .hist:empty{display:none} .hist-t{margin-bottom:6px} -.hist-r{padding:4px 0;border-top:1px solid #d6e4f0} +.hist-r{padding:4px 0;border-top:1px solid color-mix(in srgb,var(--hg-info) 22%,transparent)} /* fotos */ .item.foto .txt{display:block;font-weight:600;margin-bottom:8px} -button.btn-foto{width:100%;background:#fff;color:var(--naranja);border:2px dashed var(--naranja); - border-radius:12px;padding:16px;font-size:16px;font-weight:700;cursor:pointer} -button.btn-foto:active{background:var(--naranja-suave)} +button.btn-foto{width:100%;background:transparent;color:var(--hg-liga);border:2px dashed var(--hg-linea-2); + border-radius:12px;padding:16px;font:inherit;font-size:16px;font-weight:700;cursor:pointer} +button.btn-foto:hover{border-color:var(--hg-liga)} +button.btn-foto:active{background:var(--hg-acento-suave)} .miniaturas{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px} .miniaturas:empty{margin-top:0} -.mini{width:104px;border:1px solid var(--linea);border-radius:10px;padding:6px;background:#fff; +.mini{width:104px;border:1px solid var(--hg-linea);border-radius:10px;padding:6px;background:var(--hg-plano); display:flex;flex-direction:column;gap:4px;align-items:center} -.mini img{width:90px;height:90px;object-fit:cover;border-radius:6px;background:#eee} +.mini img{width:90px;height:90px;object-fit:cover;border-radius:6px;background:var(--hg-pend-bg)} .mini .est{font-size:11px;font-weight:700;text-align:center;line-height:1.2} -.mini.ok{border-color:var(--ok)} .mini.ok .est{color:var(--ok)} -.mini.err{border-color:var(--falla)} .mini.err .est{color:var(--falla)} -.mini.subiendo .est{color:var(--tinta2)} -button.mini-btn{background:#fff;border:1px solid var(--linea);border-radius:6px; - font-size:11px;padding:3px 7px;cursor:pointer;color:var(--tinta2)} +.mini.ok{border-color:color-mix(in srgb,var(--ok) 55%,transparent)} .mini.ok .est{color:var(--ok)} +.mini.err{border-color:color-mix(in srgb,var(--falla) 55%,transparent)} .mini.err .est{color:var(--falla)} +.mini.subiendo .est{color:var(--hg-texto-2)} +button.mini-btn{background:transparent;border:1px solid var(--hg-linea-2);border-radius:6px; + font:inherit;font-size:11px;padding:3px 7px;cursor:pointer;color:var(--hg-texto-2)} /* aviso de seguridad: más fuerte que un 'aviso' normal */ -.peligro{background:var(--falla-bg);border:2px solid var(--falla);color:#a01a1a; +.peligro{background:var(--falla-bg);border:2px solid var(--falla);color:var(--hg-texto); padding:12px 14px;border-radius:10px;margin:10px 0;font-size:14px;line-height:1.45} .peligro b{color:var(--falla)} /* en el patio: con guantes, sol y prisa — todo más grande */ @media(max-width:560px){ - body{font:17px/1.55 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif} + body{font-size:17px;line-height:1.55} .wrap{padding:12px 12px 130px} .chk input{width:30px;height:30px} .medida input{max-width:none;flex:1 1 140px;font-size:17px;padding:13px 12px} @@ -124,24 +162,32 @@ button.mini-btn{background:#fff;border:1px solid var(--linea);border-radius:6px; /* archivos de log adjuntos (capturas por USB) */ .mini.doc{width:auto;min-width:160px;max-width:260px;flex-direction:row;flex-wrap:wrap; align-items:center;gap:6px;padding:8px 10px} -.mini.doc .ico{font-size:18px} -.mini.doc .nom{font-size:12.5px;font-weight:600;word-break:break-all;flex:1 1 90px} +.mini.doc .ico{font-size:12px;font-weight:700;color:var(--hg-texto-3)} +.mini.doc .nom{font-family:var(--hg-fuente-mono);font-size:12.5px;font-weight:500;word-break:break-all;flex:1 1 90px} .mini.doc .est{font-size:11.5px;flex:0 0 auto} -input[type=date]{width:100%;padding:11px 12px;border:1px solid var(--linea);border-radius:9px; - font-size:16px;background:#fff;color:var(--tinta)} +input[type=date]{width:100%;padding:11px 12px;border:1px solid var(--hg-linea-2);border-radius:9px; + font:inherit;font-size:16px;background:var(--hg-plano);color:var(--hg-texto)} /* marca de daño / baja: se muestra en cualquier acta al elegir la serie */ .marca{display:none;margin:0 0 14px;padding:12px 14px;border-radius:10px;font-size:14.5px;line-height:1.45} -.marca.danada{display:block;background:var(--aviso-bg);border:2px solid var(--aviso);color:#7a4a00} -.marca.baja{display:block;background:var(--falla-bg);border:2px solid var(--falla);color:#8a1a1a} +.marca.danada{display:block;background:var(--aviso-bg);border:2px solid var(--aviso);color:var(--hg-texto)} +.marca.baja{display:block;background:var(--falla-bg);border:2px solid var(--falla);color:var(--hg-texto)} .marca a{color:inherit;font-weight:700} /* tabla de registro (tipo 'tabla') */ .tabla-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin-top:6px} .tabla{border-collapse:collapse;font-size:13px;min-width:100%} -.tabla th,.tabla td{border:1px solid #ddd;padding:4px 5px;text-align:left;vertical-align:middle;white-space:nowrap} -.tabla thead th{background:#f3f3f3;font-weight:600;font-size:12px} -.tabla tbody th{background:#fafafa;font-weight:600;font-variant-numeric:tabular-nums} -.tabla input,.tabla select{width:100%;min-width:64px;font-size:14px;padding:6px 6px;border:1px solid #ccc;border-radius:6px;box-sizing:border-box} +.tabla th,.tabla td{border:1px solid var(--hg-linea);padding:4px 5px;text-align:left;vertical-align:middle;white-space:nowrap} +.tabla thead th{background:var(--hg-plano);color:var(--hg-texto-2);font-weight:600;font-size:12px} +.tabla tbody th{background:var(--hg-plano-2);font-weight:600;font-variant-numeric:tabular-nums} +.tabla input,.tabla select{width:100%;min-width:64px;font-size:14px;padding:6px 6px;border:1px solid var(--hg-linea-2);border-radius:6px;box-sizing:border-box;background:var(--hg-plano);color:var(--hg-texto)} .tabla input[inputmode=decimal]{max-width:90px} -.enviada .tabla input,.enviada .tabla select{background:#f6f6f6} +.enviada .tabla input,.enviada .tabla select{background:var(--hg-plano-2)} + +@media print{ + body{background:#fff;color:#000} + header.top{background:#fff !important;color:#000 !important;border-color:#000} + header.top p{color:#333 !important} + .hg-modo,.barra{display:none !important} + section.paso{background:#fff;border-color:#999} +} diff --git a/docs/formularios/acta.js b/docs/formularios/acta.js index 030a537..99771a9 100644 --- a/docs/formularios/acta.js +++ b/docs/formularios/acta.js @@ -57,7 +57,7 @@ function opciones(sel, prefijo, desde, hasta, pad) { sel.append($('option', { value: '', text: '— elegir —' })); - sel.append($('option', { value: prefijo + '-PRUEBA', text: '⚙ PRUEBA (no cuenta)' })); + sel.append($('option', { value: prefijo + '-PRUEBA', text: 'PRUEBA (no cuenta)' })); for (let i = desde; i <= hasta; i++) { const s = prefijo + '-' + String(i).padStart(pad, '0'); sel.append($('option', { value: s, text: s })); @@ -81,7 +81,7 @@ wrap.append(nav); if (cfg.borrador) - wrap.append($('div', { class: 'borrador', html: '⚠ BORRADOR — este formulario aún debe revisarse con ingeniería antes de usarlo como registro oficial.' })); + wrap.append($('div', { class: 'borrador', html: 'BORRADOR — este formulario aún debe revisarse con ingeniería antes de usarlo como registro oficial.' })); if (cfg.intro) wrap.append($('div', { class: 'nota-item', style: 'margin:0 0 10px', html: cfg.intro })); // ---------------- cabecera: serie (simple o compuesta) + técnico ---------------- @@ -108,9 +108,9 @@ serieSel.append(og); }); if (!cfg.sinEnsambladas) cargarEnsambladas(); - if (!cfg.sinEnsambladas) serieSel.insertBefore($('option', { value: '__HBOX__', text: '🧩 Unidad HBOX completa — elegir sus 3 piezas' }), serieSel.children[1] || null); - serieSel.append($('option', { value: '__OTRA__', text: '➕ Otra unidad (no está en la lista)' })); - serieSel.append($('option', { value: 'CAMPO-PRUEBA', text: '⚙ PRUEBA (no cuenta)' })); + if (!cfg.sinEnsambladas) serieSel.insertBefore($('option', { value: '__HBOX__', text: 'Unidad HBOX completa: elegir sus 3 piezas' }), serieSel.children[1] || null); + serieSel.append($('option', { value: '__OTRA__', text: 'Otra unidad (no está en la lista)' })); + serieSel.append($('option', { value: 'CAMPO-PRUEBA', text: 'PRUEBA (no cuenta)' })); // Unidad HBOX completa armada a mano: tarjeta + ArduSimple + módem → misma serie que el acta de ensamble. [['einar', 'Tarjeta EinarBoard', 'V5', 2], ['ard', 'ArduSimple', 'ARD', 3], ['modem', 'Módem 4G', 'RTK', 4]].forEach(([k, t, pre, pad]) => { const sel = $('select'); opciones(sel, pre, 1, 30, pad); armarSel[k] = sel; @@ -178,10 +178,10 @@ marcaBox.className = 'marca ' + (baja ? 'baja' : 'danada'); marcaBox.innerHTML = avisos.map(({ s, j }) => { const a = j.acta || {}; - return (j.marca === 'BAJA' ? '⛔ ' + s + ' está dada de BAJA' : '⚠ ' + s + ' está marcada como DAÑADA') + return (j.marca === 'BAJA' ? '' + s + ' está dada de BAJA' : '' + s + ' está marcada como DAÑADA') + (a.fecha ? ' desde el ' + a.fecha : '') + (a.clasificacion ? ' — ' + a.clasificacion : '') + (a.resumen ? '
' + a.resumen : '') - + '
Ver su expediente' + + '
Ver su expediente' + (j.marca === 'BAJA' ? '. No debe usarse ni instalarse.' : '. Revisa el acta de daño antes de continuar.'); }).join('
'); } @@ -344,7 +344,7 @@ box.append($('span', { class: 'txt', html: (it.req ? 'Archivo obligatorio — ' : 'Archivo — ') + it.txt })); if (it.ayuda) box.append($('div', { class: 'nota-item', html: it.ayuda })); const inp = $('input', { type: 'file', accept: '.txt,.log,.csv,.nmea,.ubx,.json,.cfg,text/plain', multiple: 'multiple', style: 'display:none' }); - const btn = $('button', { type: 'button', class: 'btn-foto', text: '📄 Subir archivo de captura' }); + const btn = $('button', { type: 'button', class: 'btn-foto', text: 'Subir archivo de captura' }); const tiras = $('div', { class: 'miniaturas', 'data-fotos': id }); const marca = $('input', { type: 'hidden', 'data-id': id, 'data-lbl': 'Archivos: ' + String(it.txt || '').replace(/<[^>]+>/g, ''), value: '' }); btn.addEventListener('click', () => inp.click()); @@ -355,7 +355,7 @@ box.append($('span', { class: 'txt', html: (it.req ? 'Foto obligatoria — ' : 'Foto — ') + it.txt })); if (it.ayuda) box.append($('div', { class: 'nota-item', html: it.ayuda })); const inp = $('input', { type: 'file', accept: 'image/*', capture: 'environment', multiple: 'multiple', style: 'display:none' }); - const btn = $('button', { type: 'button', class: 'btn-foto', text: '📷 Tomar o elegir foto' }); + const btn = $('button', { type: 'button', class: 'btn-foto', text: 'Tomar o elegir foto' }); const tiras = $('div', { class: 'miniaturas', 'data-fotos': id }); const marca = $('input', { type: 'hidden', 'data-id': id, 'data-lbl': 'Fotos: ' + String(it.txt || '').replace(/<[^>]+>/g, ''), value: '' }); btn.addEventListener('click', () => inp.click()); @@ -413,7 +413,7 @@ if (!t) return; const li = $('div', { class: 'mini ok' }); li.append($('img', { src: '/api/adjunto?ruta=' + encodeURIComponent(f.ruta) }), - $('span', { class: 'est', text: '✓ guardada' })); + $('span', { class: 'est', text: 'Guardada' })); if (marca) li.append(quitarFoto(f, li, marca)); t.append(li); }); @@ -423,9 +423,9 @@ const t = wrap.querySelector(`.miniaturas[data-fotos="${a.campo}"]`); if (!t) return; const li = $('div', { class: 'mini doc ok' }); - li.append($('span', { class: 'ico', text: '📄' }), + li.append($('span', { class: 'ico', text: 'Log' }), $('span', { class: 'nom', text: String(a.nombre || '').slice(0, 28) }), - $('span', { class: 'est', text: '✓ guardado' })); + $('span', { class: 'est', text: 'Guardado' })); t.append(li); }); } @@ -471,7 +471,7 @@ borrar.style.display = admin ? '' : 'none'; banner.className = 'msg ok'; const f = (a._recibido || '').replace('T', ' ').slice(0, 16); - banner.innerHTML = '✓ Acta ya enviada por ' + (a.tecnico || '—') + '' + banner.innerHTML = 'Acta ya enviada por ' + (a.tecnico || '—') + '' + (f ? ' el ' + f : '') + '. Registro final' + (a.resultado ? ' — resultado ' + a.resultado + '' : '') + '.' + (admin ? '' : ' Para rehacerla, pide a Leo que la borre.'); @@ -521,7 +521,7 @@ } function quitarFoto(f, li, marca) { - const b = $('button', { type: 'button', class: 'mini-btn', text: '✕ quitar' }); + const b = $('button', { type: 'button', class: 'mini-btn', text: 'Quitar' }); b.addEventListener('click', () => { fotos = fotos.filter(x => x !== f); li.remove(); marca.value = fotos.filter(x => x.campo === f.campo).length || ''; @@ -538,7 +538,7 @@ const j = await r.json(); if (!r.ok || !j.ok) throw new Error(j.error || ('HTTP ' + r.status)); const f = j.fotos[0]; f.campo = campo; fotos.push(f); - li.className = 'mini ok'; est.textContent = '✓ guardada'; + li.className = 'mini ok'; est.textContent = 'Guardada'; li.append(quitarFoto(f, li, marca)); marca.value = fotos.filter(x => x.campo === campo).length; guardarLocal(); aplicarCondiciones(); @@ -557,7 +557,7 @@ if (!serieActual()) { fail('Primero elige la unidad: los archivos se guardan con su número de serie.'); return; } for (const file of Array.from(lista).slice(0, 10)) { const li = $('div', { class: 'mini doc subiendo' }); - li.append($('span', { class: 'ico', text: '📄' }), + li.append($('span', { class: 'ico', text: 'Log' }), $('span', { class: 'nom', text: file.name.slice(0, 28) })); const est = $('span', { class: 'est', text: 'subiendo…' }); li.append(est); tiras.append(li); const fd = new FormData(); @@ -568,8 +568,8 @@ const j = await r.json(); if (!r.ok || !j.ok) throw new Error(j.error || ('HTTP ' + r.status)); const a = j.archivos[0]; a.campo = campo; archivos.push(a); - li.className = 'mini doc ok'; est.textContent = '✓ ' + kb(a.bytes); - const q = $('button', { type: 'button', class: 'mini-btn', text: '✕ quitar' }); + li.className = 'mini doc ok'; est.textContent = kb(a.bytes); + const q = $('button', { type: 'button', class: 'mini-btn', text: 'Quitar' }); q.addEventListener('click', () => { archivos = archivos.filter(x => x !== a); li.remove(); marca.value = archivos.filter(x => x.campo === campo).length || ''; @@ -609,7 +609,7 @@ const j = await r.json(); if (!j.total) { hist.innerHTML = '🆕 Primera visita registrada para esta unidad.'; return; } hist.innerHTML = ''; - hist.append($('div', { class: 'hist-t', html: '📋 ' + j.total + ' visita(s) anterior(es) a esta unidad — léelas antes de empezar:' })); + hist.append($('div', { class: 'hist-t', html: '' + j.total + ' visita(s) anterior(es) a esta unidad — léelas antes de empezar:' })); j.visitas.slice(0, 6).forEach(v => { const f = (v.recibido || '').replace('T', ' ').slice(0, 16); hist.append($('div', { class: 'hist-r', html: @@ -626,8 +626,8 @@ let verif = {}; // clave -> 'OK' | 'FALLA' | 'SIN_ACTA' | 'PRUEBA' | 'EN_USO' let usados = null; // { clave: { valor: serieUnidad } } — componentes ya asignados en otras actas de este tipo function setBadge(el, st, extra) { - const map = { OK: ['ok', '✓ Aprobado'], FALLA: ['falla', '✕ FALLA'], SIN_ACTA: ['falla', '✕ Sin acta'], - PRUEBA: ['pend', '⚙ prueba'], EN_USO: ['falla', '⚠ ya en ' + (extra || 'otra unidad')], CONSULTANDO: ['pend', '…'] }; + const map = { OK: ['ok', 'Aprobado'], FALLA: ['falla', 'Falla'], SIN_ACTA: ['falla', 'Sin acta'], + PRUEBA: ['pend', 'Prueba'], EN_USO: ['falla', 'Ya en ' + (extra || 'otra unidad')], CONSULTANDO: ['pend', '…'] }; const m = map[st] || ['pend', '—']; el.className = 'badge ' + m[0]; el.textContent = m[1]; } @@ -745,7 +745,7 @@ cargarLocal(); aplicarCondiciones(); if (compuesta && cfg.exigirAprobados && !todoAprobado()) { banner.className = 'msg err'; - banner.innerHTML = '⛔ No se puede ensamblar con esta selección. Todos los módulos deben estar aprobados en su acta y no estar ya asignados a otra unidad. Revisa los indicadores de arriba.'; + banner.innerHTML = 'No se puede ensamblar con esta selección. Todos los módulos deben estar aprobados en su acta y no estar ya asignados a otra unidad. Revisa los indicadores de arriba.'; } } } @@ -805,10 +805,10 @@ if (!r.ok || !j.ok) throw new Error(j.error || ('HTTP ' + r.status)); try { localStorage.removeItem(key()); } catch (e) {} msg.className = 'msg ok'; - msg.innerHTML = '✓ Acta enviada y registrada como ' + d.serie + '.' + msg.innerHTML = 'Acta enviada y registrada como ' + d.serie + '.' + (compuesta && !esPrueba(d.serie) ? '
Etiqueta de la unidad: ' + d.serie + '' : ''); if (cfg.repetible) { - msg.innerHTML = '✓ Registro enviado para ' + d.serie + '' + msg.innerHTML = 'Registro enviado para ' + d.serie + '' + (d.fotos && d.fotos.length ? ' con ' + d.fotos.length + ' foto(s)' : '') + '.
Ingeniería ya puede verlo. Puedes cerrar o elegir otra unidad.'; btn.disabled = false; btn.textContent = 'Enviar acta firmada'; diff --git a/docs/formularios/ardusimple.html b/docs/formularios/ardusimple.html index 4d01ca9..3084dc5 100644 --- a/docs/formularios/ardusimple.html +++ b/docs/formularios/ardusimple.html @@ -4,6 +4,7 @@ Acta de módulo — simpleRTK2B Pro (RTK) + diff --git a/docs/formularios/banco.html b/docs/formularios/banco.html index 866f061..a78ca91 100644 --- a/docs/formularios/banco.html +++ b/docs/formularios/banco.html @@ -4,6 +4,7 @@ Acta de diagnóstico en banco — HBOX + diff --git a/docs/formularios/dano.html b/docs/formularios/dano.html index 2b5c117..4f0bd11 100644 --- a/docs/formularios/dano.html +++ b/docs/formularios/dano.html @@ -4,6 +4,7 @@ Acta de daño o incidente — HBOX + diff --git a/docs/formularios/diagnostico.html b/docs/formularios/diagnostico.html index 7155065..ea2c2c1 100644 --- a/docs/formularios/diagnostico.html +++ b/docs/formularios/diagnostico.html @@ -4,6 +4,7 @@ Acta de diagnóstico en campo — HBOX + diff --git a/docs/formularios/ensamble.html b/docs/formularios/ensamble.html index f3f7323..cdbddd8 100644 --- a/docs/formularios/ensamble.html +++ b/docs/formularios/ensamble.html @@ -4,6 +4,7 @@ Acta de ensamble — unidad HBOX v5 + diff --git a/docs/formularios/envio.html b/docs/formularios/envio.html index 2f3100b..c18422e 100644 --- a/docs/formularios/envio.html +++ b/docs/formularios/envio.html @@ -4,6 +4,7 @@ Acta de envío — HBOX + diff --git a/docs/formularios/ethernet-serie.html b/docs/formularios/ethernet-serie.html index 7593c0e..2de79d9 100644 --- a/docs/formularios/ethernet-serie.html +++ b/docs/formularios/ethernet-serie.html @@ -4,6 +4,7 @@ Prueba de banco — Ethernet y puertos serie (V5) + diff --git a/docs/formularios/instalacion.html b/docs/formularios/instalacion.html index 889c032..827d698 100644 --- a/docs/formularios/instalacion.html +++ b/docs/formularios/instalacion.html @@ -4,9 +4,10 @@ Acta de instalación en campo — HBOX + diff --git a/docs/formularios/integracion.html b/docs/formularios/integracion.html index 33561bd..4b336ba 100644 --- a/docs/formularios/integracion.html +++ b/docs/formularios/integracion.html @@ -4,6 +4,7 @@ Acta de integración — RTK + 4G + diff --git a/docs/formularios/modem4g.html b/docs/formularios/modem4g.html index ff14c6d..d470d4f 100644 --- a/docs/formularios/modem4g.html +++ b/docs/formularios/modem4g.html @@ -4,6 +4,7 @@ Acta de módulo — 4G NTRIP Master + diff --git a/docs/formularios/prueba-bateria.html b/docs/formularios/prueba-bateria.html index 40c7f34..a6e27cc 100644 --- a/docs/formularios/prueba-bateria.html +++ b/docs/formularios/prueba-bateria.html @@ -4,6 +4,7 @@ Prueba de banco — módem 4G en batería + diff --git a/docs/formularios/recepcion.html b/docs/formularios/recepcion.html index e1f45f1..b03664b 100644 --- a/docs/formularios/recepcion.html +++ b/docs/formularios/recepcion.html @@ -4,6 +4,7 @@ Acta de recepción e inspección — HBOX + diff --git a/docs/formularios/reflasheo.html b/docs/formularios/reflasheo.html index 389233e..11d1c3c 100644 --- a/docs/formularios/reflasheo.html +++ b/docs/formularios/reflasheo.html @@ -4,6 +4,7 @@ Acta de reflasheo y configuración — HBOX + diff --git a/docs/formularios/v4.html b/docs/formularios/v4.html index 0bfb0de..65ad747 100644 --- a/docs/formularios/v4.html +++ b/docs/formularios/v4.html @@ -4,6 +4,7 @@ Acta de prueba — EinarBoard V4 (fw 0.6.0) + @@ -55,7 +56,7 @@ Acta.render({ + 'V4 — preparación y prueba con 0.6.0. ' + 'Graba la consola desde el primer minuto; al final se sube completa. ' + 'Si una etapa no pasa, marca «me detengo»: lo que sigue se oculta, llenas el Cierre y envías como FALLA. ' - + 'Sin número de serie: el siguiente V4 libre del tablero. La serie PRUEBA sirve para practicar.', + + 'Sin número de serie: el siguiente V4 libre del tablero de actas. La serie PRUEBA sirve para practicar.', secciones: [ { titulo: '1 · Datos', diff --git a/docs/formularios/v5.html b/docs/formularios/v5.html index 2f37bd8..ad42b36 100644 --- a/docs/formularios/v5.html +++ b/docs/formularios/v5.html @@ -4,6 +4,7 @@ Acta de prueba — EinarBoard V5 + diff --git a/docs/formularios/ver.html b/docs/formularios/ver.html index a30b6b4..d357b99 100644 --- a/docs/formularios/ver.html +++ b/docs/formularios/ver.html @@ -4,6 +4,7 @@ Ver acta — HBOX + + +Inventario - Drogheda + + + -
-
-

Inventario de materiales

Cargando…
- -
- -
- Cómo se usa -
    -
  1. El stock no se escribe a mano: es la suma de los movimientos. Llegó material → Entrada. Se usó en un ensamble o se envió → Salida con la unidad o el acta como referencia.
  2. -
  3. Contaste y no cuadra → Ajuste con el conteo físico; el sistema calcula la diferencia y la deja registrada con tu nombre.
  4. -
  5. Toca el código para ver los movimientos de ese ítem. Cada uno dice quién, cuándo, cuánto y por qué.
  6. -
  7. Alerta (rojo) = stock por debajo del mínimo. El mínimo lo pone quien compra; el tablero de producción lo repite.
  8. -
  9. Nuevo ítem solo para cosas que se cuentan: tarjetas, módulos, gabinetes, cajas, fuentes, packs, antenas, cables y los componentes de entrega larga. Nada de resistencias.
  10. -
  11. Exportar CSV baja la tabla para Excel. Nada se borra: si un ítem ya no aplica, ponle «(obsoleto)» en la descripción.
  12. -
-
- -
- - - - - - - ⬇ Exportar CSV - -
-
-
-
- - - +

Este tablero ahora está dentro del sitio: Inventario.

diff --git a/docs/js/sitio.js b/docs/js/sitio.js new file mode 100644 index 0000000..49bf787 --- /dev/null +++ b/docs/js/sitio.js @@ -0,0 +1,33 @@ +/* Sitio Drogheda: detalles que necesitan datos del servidor en todas las páginas. + - Junto a «Pendientes» en el menú lateral, cuántos hay abiertos (de /api/tareas/resumen). + Si el servidor no responde, el menú queda igual. */ +(function () { + function cuentaPendientes() { + var ligas = [].slice.call(document.querySelectorAll('.md-nav--primary a.md-nav__link')).filter(function (a) { + try { return /\/tableros\/pendientes\/?$/.test(new URL(a.href, location.href).pathname); } catch (e) { return false; } + }); + if (!ligas.length) return; + fetch('/api/tareas/resumen', { cache: 'no-store', credentials: 'same-origin' }) + .then(function (r) { return r.ok ? r.json() : null; }) + .then(function (j) { + if (!j || !j.ok || !j.por_pista) return; + var abiertos = 0; + Object.keys(j.por_pista).forEach(function (p) { + var e = j.por_pista[p] || {}; + abiertos += (e['por-hacer'] || 0) + (e['en-curso'] || 0) + (e['bloqueado'] || 0); + }); + var vencidos = (j.vencidas || []).length; + ligas.forEach(function (a) { + if (a.querySelector('.hg-cuenta')) return; + var s = document.createElement('span'); + s.className = 'hg-cuenta' + (vencidos ? ' hg-cuenta--vencidos' : ''); + s.textContent = abiertos; + s.title = abiertos + ' abiertos' + (vencidos ? ', ' + vencidos + ' vencido' + (vencidos > 1 ? 's' : '') : ''); + a.appendChild(s); + }); + }) + .catch(function () {}); + } + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', cuentaPendientes); + else cuentaPendientes(); +})(); diff --git a/docs/js/tema.js b/docs/js/tema.js new file mode 100644 index 0000000..b6c7ed5 --- /dev/null +++ b/docs/js/tema.js @@ -0,0 +1,43 @@ +/* Modo claro u oscuro en las páginas sueltas (actas, cuenta, administración). + Lee la misma preferencia que el sitio (Material la guarda en localStorage con la + clave ".__palette"; scope = extra.scope de mkdocs.yml = "/drogheda/"). + Oscuro por omisión. Va en el de cada página, antes de su hoja de estilo, + para que no parpadee. Agrega un botón de modo al encabezado de la página. */ +(function () { + var CLAVE = '/drogheda/.__palette'; + var html = document.documentElement; + function leer() { + try { var p = JSON.parse(localStorage.getItem(CLAVE) || 'null'); return p && p.color && p.color.scheme === 'default' ? 'claro' : 'oscuro'; } + catch (e) { return 'oscuro'; } + } + function aplicar(modo) { if (modo === 'claro') html.setAttribute('data-tema', 'claro'); else html.removeAttribute('data-tema'); } + function guardar(modo) { + // mismo formato que Material: índice 0 = oscuro (slate), 1 = claro (default) + var p = { index: modo === 'claro' ? 1 : 0, color: { media: '', scheme: modo === 'claro' ? 'default' : 'slate', primary: 'custom', accent: 'custom' } }; + try { localStorage.setItem(CLAVE, JSON.stringify(p)); } catch (e) {} + } + aplicar(leer()); + var SOL = ''; + var LUNA = ''; + function boton() { + var cab = document.querySelector('header.top'); + if (!cab || cab.querySelector('.hg-modo')) return; + var b = document.createElement('button'); + b.type = 'button'; b.className = 'hg-modo'; + function pintar() { + var claro = html.getAttribute('data-tema') === 'claro'; + b.setAttribute('aria-label', claro ? 'Cambiar a modo oscuro' : 'Cambiar a modo claro'); + b.title = b.getAttribute('aria-label'); + b.innerHTML = ''; + } + b.addEventListener('click', function () { + var modo = html.getAttribute('data-tema') === 'claro' ? 'oscuro' : 'claro'; + aplicar(modo); guardar(modo); pintar(); + }); + pintar(); + cab.appendChild(b); + } + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boton); else boton(); + // si la persona cambia el modo en otra pestaña del sitio, esta página lo sigue + window.addEventListener('storage', function (e) { if (e.key === CLAVE) aplicar(leer()); }); +})(); diff --git a/docs/procedimientos/ciclo-de-vida.md b/docs/procedimientos/ciclo-de-vida.md index b2bc543..63e0204 100644 --- a/docs/procedimientos/ciclo-de-vida.md +++ b/docs/procedimientos/ciclo-de-vida.md @@ -15,7 +15,7 @@ version: 1.2 - Tiempo: acta de envío o recepción 15–30 min por unidad. - Necesitas: los [formularios](../actas/index.md); para recepción, fuente de 24 V (≥ 1 A; límite en 1 A si lo tiene), multímetro, cable USB con datos y laptop. -Todas las actas cuelgan del número de serie; el [expediente](../unidad.html) de cualquier tarjeta, módulo o unidad cuenta la historia completa, daños incluidos. +Todas las actas cuelgan del número de serie; el [expediente](../tableros/unidad.md) de cualquier tarjeta, módulo o unidad cuenta la historia completa, daños incluidos. ## Mapa diff --git a/docs/procedimientos/v4-prueba-fw-0.5.6.md b/docs/procedimientos/v4-prueba-fw-0.5.6.md index b77f7e2..d9b8555 100644 --- a/docs/procedimientos/v4-prueba-fw-0.5.6.md +++ b/docs/procedimientos/v4-prueba-fw-0.5.6.md @@ -11,7 +11,7 @@ version: 1.6 !!! abstract "Para quién · Cuándo · Tiempo · Necesitas" - Para quién: técnico de banco. - - Cuándo: una vez por tarjeta V4 (EinarBoard 2.0, Blackpill en zócalo), antes de darla por buena con el firmware de campo. Sin serie: etiquétala V4-NN con el siguiente libre del [tablero](../tablero.html). + - Cuándo: una vez por tarjeta V4 (EinarBoard 2.0, Blackpill en zócalo), antes de darla por buena con el firmware de campo. Sin serie: etiquétala V4-NN con el siguiente libre del [tablero](../tableros/actas.md). - Tiempo: ~1 h por tarjeta, más ~20 min en batería. - Necesitas: tarjeta V4 completa (Blackpill, simpleRTK2B, módem con SIM, antena GNSS con cielo, antena LTE, batería); 24 V al GX16 que puedas desconectar; diodo Schottky BAT54 (como D5), BAT85, BAT43 o 1N5711, nunca 1N5819; alambre wire-wrap, cautín fino, flux, Kapton, termofil, lupa; multímetro con MIN/MAX; laptop con terminal serie y `dfu-util` o STM32CubeProgrammer; dos cables USB-A a USB-C (uno normal y uno sin 5 V, Preparación 2); cargador Li-ion de 1 celda o fuente de banco; monitor y [acta de prueba V4](../formularios/v4.html) abierta desde el inicio (se guarda sola en el navegador). @@ -113,7 +113,7 @@ Pasa si en los dos casos el módem registra solo en < 2 min y el monitor vuelve ## Registro -Todo va en el [acta de prueba V4](../formularios/v4.html), con el log completo de consola. Cada etapa termina con una pregunta de paso; si la tarjeta no pasa, marca "me detengo", llena el cierre y envía con resultado FALLA. Queda en el [expediente](../unidad.html) y en el [tablero](../tablero.html). +Todo va en el [acta de prueba V4](../formularios/v4.html), con el log completo de consola. Cada etapa termina con una pregunta de paso; si la tarjeta no pasa, marca "me detengo", llena el cierre y envía con resultado FALLA. Queda en el [expediente](../tableros/unidad.md) y en el [tablero](../tableros/actas.md). !!! danger "Detente y avisa a ingeniería" - P2 en 0 V con 24 V puestos. diff --git a/docs/produccion/index.md b/docs/produccion/index.md index 80e36cc..d5447d4 100644 --- a/docs/produccion/index.md +++ b/docs/produccion/index.md @@ -4,7 +4,7 @@ title: "Producción" # Producción -De la tarjeta desnuda a la unidad lista para embarcar. Una unidad a la vez; cada paso deja su acta y la unidad no avanza si falla un paso. Plan y avance real: [Tablero de producción](../tableros/produccion.html). Existencias: [Inventario](../inventario/inventario.html). +De la tarjeta desnuda a la unidad lista para embarcar. Una unidad a la vez; cada paso deja su acta y la unidad no avanza si falla un paso. Plan y avance real: [Tablero de producción](../tableros/produccion.md). Existencias: [Inventario](../tableros/inventario.md). ## Plan de 570 unidades (13-oct-2026) @@ -36,10 +36,10 @@ La V4 no entra al pipeline de unidades V5; se prepara y prueba en [Taller](../ta ## Dónde ver el avance -- [Tablero de producción](../tableros/produccion.html): plan 113 / 327 / 130 contra las unidades reales por etapa; bloqueos. -- [Estado de actas](../tablero.html): qué tarjeta, módulo y unidad pasó cada paso (series V5-NN, ARD-NNN, RTK-NNNN). -- [Expediente de una unidad](../unidad.html): la historia completa de una serie. +- [Tablero de producción](../tableros/produccion.md): plan 113 / 327 / 130 contra las unidades reales por etapa; bloqueos. +- [Estado de actas](../tableros/actas.md): qué tarjeta, módulo y unidad pasó cada paso (series V5-NN, ARD-NNN, RTK-NNNN). +- [Expediente de una unidad](../tableros/unidad.md): la historia completa de una serie. - [Inventario](../inventario/index.md): tarjetas, módulos, gabinetes, cajas, paquetes, fuentes; mínimos y alertas. -- [Kanban](../tableros/kanban.html): tareas de la pista Producción y Compras. +- [Pendientes](../tableros/pendientes.md): tareas de la pista Producción y Compras. - [Descargas](../descargas/index.md): firmware vigente por tarjeta y SHA-256. Hoy: 0.6.0 CAMPO; 0.6.3 solo banco. - [Índice de actas](../actas/index.md): cómo se llenan y qué registra cada una. diff --git a/docs/salir.html b/docs/salir.html index 8d37fa3..5bc1c97 100644 --- a/docs/salir.html +++ b/docs/salir.html @@ -4,6 +4,7 @@ Cerrar sesión — HBOX + @@ -12,7 +13,7 @@

Cerrando sesión…