from reportlab.lib import colors
from reportlab.lib.enums import TA_CENTER, TA_LEFT
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak, Image, Table, TableStyle, KeepTogether
from pathlib import Path
from PIL import Image as PILImage

ROOT = Path(__file__).resolve().parents[2]
OUT = ROOT / "output" / "pdf" / "manual_usuario_imrd_cota_2026.pdf"
CAP = ROOT / "tmp" / "pdfs" / "manual_imrd_capturas"

GREEN = colors.HexColor("#176B3A")
DARK = colors.HexColor("#17324D")
LIGHT = colors.HexColor("#EAF4EE")
GRAY = colors.HexColor("#F3F5F7")

styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name="CoverTitle", parent=styles["Title"], fontName="Helvetica-Bold", fontSize=27, leading=33, textColor=GREEN, alignment=TA_CENTER, spaceAfter=18))
styles.add(ParagraphStyle(name="CoverSub", parent=styles["Normal"], fontSize=13, leading=19, textColor=DARK, alignment=TA_CENTER))
styles.add(ParagraphStyle(name="H1x", parent=styles["Heading1"], fontName="Helvetica-Bold", fontSize=19, leading=23, textColor=GREEN, spaceBefore=8, spaceAfter=10))
styles.add(ParagraphStyle(name="H2x", parent=styles["Heading2"], fontName="Helvetica-Bold", fontSize=14, leading=18, textColor=DARK, spaceBefore=9, spaceAfter=6))
styles.add(ParagraphStyle(name="H3x", parent=styles["Heading3"], fontName="Helvetica-Bold", fontSize=11.5, leading=15, textColor=GREEN, spaceBefore=7, spaceAfter=4))
styles.add(ParagraphStyle(name="Bodyx", parent=styles["BodyText"], fontSize=9.5, leading=14, spaceAfter=6))
styles.add(ParagraphStyle(name="Smallx", parent=styles["BodyText"], fontSize=8, leading=11, textColor=colors.HexColor("#506070"), spaceAfter=4))
styles.add(ParagraphStyle(name="Callout", parent=styles["BodyText"], fontSize=9.3, leading=14, leftIndent=10, rightIndent=10, borderColor=GREEN, borderWidth=1, borderPadding=8, backColor=LIGHT, spaceBefore=5, spaceAfter=8))

story=[]

def p(text, style="Bodyx"):
    story.append(Paragraph(text, styles[style]))

def h1(text):
    story.append(Paragraph(text, styles["H1x"]))

def h2(text):
    story.append(Paragraph(text, styles["H2x"]))

def h3(text):
    story.append(Paragraph(text, styles["H3x"]))

def bullets(items):
    for item in items:
        p("• " + item)

def shot(name, caption, width=16.5*cm, maxh=13*cm):
    path=CAP/name
    if not path.exists(): return
    with PILImage.open(path) as im:
        w,h=im.size
    scale=min(width/w, maxh/h)
    story.append(KeepTogether([Image(str(path), width=w*scale, height=h*scale), Spacer(1,3), Paragraph(caption, styles["Smallx"])]))

def table(rows, widths=None):
    t=Table([[Paragraph(str(c), styles["Smallx"]) for c in r] for r in rows], colWidths=widths, repeatRows=1)
    t.setStyle(TableStyle([
        ("BACKGROUND",(0,0),(-1,0),GREEN),("TEXTCOLOR",(0,0),(-1,0),colors.white),
        ("FONTNAME",(0,0),(-1,0),"Helvetica-Bold"),("GRID",(0,0),(-1,-1),0.35,colors.HexColor("#AAB5BE")),
        ("VALIGN",(0,0),(-1,-1),"TOP"),("BACKGROUND",(0,1),(-1,-1),colors.white),
        ("LEFTPADDING",(0,0),(-1,-1),5),("RIGHTPADDING",(0,0),(-1,-1),5),("TOPPADDING",(0,0),(-1,-1),4),("BOTTOMPADDING",(0,0),(-1,-1),4),
    ]))
    story.append(t); story.append(Spacer(1,8))

def footer(canvas, doc):
    canvas.saveState()
    canvas.setStrokeColor(colors.HexColor("#D7DEE3")); canvas.line(1.8*cm,1.35*cm,19.2*cm,1.35*cm)
    canvas.setFont("Helvetica",7.5); canvas.setFillColor(colors.HexColor("#637381"))
    canvas.drawString(1.8*cm,0.95*cm,"Manual de usuario - Plataforma IMRD Cota 2026")
    canvas.drawRightString(19.2*cm,0.95*cm,f"Página {doc.page}")
    canvas.restoreState()

# Portada
story.append(Spacer(1,3.2*cm))
p("MANUAL DE USUARIO", "CoverTitle")
p("Programa Escuelas de Formación Deportiva IMRD Cota 2026", "CoverSub")
story.append(Spacer(1,1.2*cm))
p("Dirección oficial: <b>https://imrd-cota.nextgonsas.com.co</b>", "CoverSub")
p("Documento de referencia para consolidación funcional y producción posterior de un video explicativo", "CoverSub")
story.append(Spacer(1,2.2*cm))
p("Actualizado mediante recorrido funcional del dominio oficial. Fecha de revisión: 11 de agosto de 2026.", "Smallx")
story.append(PageBreak())

h1("1. Propósito, alcance y forma de usar este manual")
p("Este manual describe, paso a paso, la página pública, el formulario de inscripción y los paneles disponibles según el tipo de usuario. La referencia vigente es <b>https://imrd-cota.nextgonsas.com.co</b>. Los perfiles actualizados se verificaron directamente en ese dominio.")
p("El documento está pensado como fuente detallada para una IA que posteriormente produzca un video. Por eso distingue entre funciones efectivamente visibles, funciones que requieren datos previos y módulos que aparecen en el menú pero que todavía no muestran contenido operativo en el entorno revisado.", "Callout")
h2("Perfiles contemplados")
table([["Perfil","Finalidad principal","Acceso observado"],["Administrador","Gestión global de profesores, deportes, deportistas y metodólogos","Panel Administración del Sistema"],["Profesor","Gestión académica y deportiva de escuelas","Panel Gestión de Escuelas"],["Metodólogo","Análisis y seguimiento técnico","Panel Área Técnica - Metodología"],["Deportista/estudiante","Consultar estado, deportes y subsanar documentos","Portal de Servicios IMRD Cota"]],[4*cm,7*cm,6*cm])

h1("2. Página principal")
p("Al entrar a <b>https://imrd-cota.nextgonsas.com.co</b> se muestra la portada del Instituto Municipal de Recreación y Deporte de Cota. En el encabezado aparecen los logotipos institucionales y el nombre completo del Instituto. En la parte superior están los accesos <b>Descargar App</b> e <b>Iniciar Sesión</b>.")
p("La captura de portada se omitió porque el reproductor emergente del entorno de prueba ocultó la vista durante la captura. La estructura y los textos descritos sí fueron comprobados directamente.", "Smallx")
h2("Bloque principal y contador")
p("La zona destacada anuncia: <b>PROGRAMA ESCUELAS DE FORMACIÓN DEPORTIVA IMRD COTA 2026</b>. Debajo se lee el llamado a participar y aparece un contador regresivo dividido en <b>Días, Horas, Min y Seg</b>. Los números se actualizan automáticamente; no son campos que el usuario deba llenar.")
h2("Botones de inscripción")
table([["Botón","Qué hace"],["Inscribirse Ahora","Abre el mismo formulario de inscripción desde el bloque principal."],["Abrir en pantalla completa","Abre la ventana del formulario para trabajar con mayor espacio."],["Diligenciar Formulario","Abre el formulario desde la sección informativa."],["Cerrar","Cierra la ventana del formulario sin enviarlo."]],[5.3*cm,11.7*cm])
p("Los tres primeros botones conducen al mismo formulario. El usuario puede escoger el acceso que le resulte más visible. Antes de comenzar conviene tener listos los documentos en PDF o imagen.")

h2("Aplicación Android")
p("La sección <b>Lleva el Deporte en tu Bolsillo</b> explica que la aplicación permite mantenerse al día con asistencias, horarios de profesores e información de las escuelas. El botón <b>Descargar APK Android</b> descarga el archivo de instalación. La página identifica el APK como aplicación oficial y segura del IMRD Cota y muestra ejemplos de las pantallas Principal, Fútbol y Asistencia.")
p("Este manual se limita a la experiencia web: no incluye instalación ni uso interno del APK.", "Callout")
h2("Pie de página")
p("Al final se encuentra una descripción institucional, dirección (Carrera 4 No. 12 - 63, Palacio Municipal, Cota), horario de lunes a viernes de 8:00 a.m. a 5:00 p.m., conmutador, extensión anticorrupción y enlaces de Trámites, Transparencia y PQRS.")
story.append(PageBreak())

h1("3. Formulario público de inscripción")
p("Al oprimir cualquiera de los botones del formulario se abre una ventana superpuesta. No se debe cerrar ni recargar la página mientras se diligencian datos o se seleccionan archivos. Los campos marcados con asterisco son obligatorios.")
h2("3.1 Datos del deportista")
bullets(["Nombres y apellidos.","Tipo de documento: Registro Civil, T.I., C.C., C.E., P.T., Pasaporte o P.P.T.","Número de documento, lugar de expedición y fecha de nacimiento.","Copia del documento de identidad en PDF o imagen.","Correo electrónico, género y lugar de nacimiento.","Vereda o sector de vivienda y dirección exacta.","Institución educativa, tipo de institución y grado escolar.","Tipo de población: afrocolombiano, indígena, discapacidad, víctima del conflicto armado o ninguna."])
h2("3.2 Discapacidad y condición de víctima")
p("El formulario pregunta si el deportista tiene discapacidad. Si se responde Sí, se habilitan el tipo de discapacidad y la carga del Registro Único de Discapacidad. También pregunta si es víctima del conflicto armado y, cuando corresponde, permite adjuntar el Registro Único de Víctimas.")
h2("3.3 Información de salud")
bullets(["Grupo sanguíneo y RH.","EPS, tipo de régimen y certificado de afiliación activo.","Condiciones médicas previas y su descripción.","Enfermedades previas.","Cirugías, tipo y fecha.","Medicamentos actuales.","Alergias y descripción.","Lesiones actuales o pasadas, tipo y fecha.","Tratamiento psicológico, nombre y fecha de inicio."])
p("Cuando una pregunta se responde con No, los campos de detalle relacionados no deberían diligenciarse. Cuando se responde Sí, se debe aportar información completa y coherente.")
h2("3.4 Datos de acudientes y familia")
p("El primer acudiente es obligatorio: nombres, apellidos, tipo y número de documento, celular y correo. Existe un segundo bloque opcional para otro acudiente. Después se selecciona el tipo de familia entre las opciones disponibles, por ejemplo nuclear, monoparental, extensa, reconstituida, adoptiva/no parental o comunal.")
h2("3.5 Declaraciones, formatos y documentos finales")
bullets(["Certificar que la información es correcta y autorizar su revisión.","Autorizar o negar el tratamiento de datos personales conforme a la Ley 1581 de 2012.","Aceptar la responsabilidad del padre, madre o acudiente sobre la participación.","Leer y aceptar el Manual de Convivencia.","Descargar el consentimiento informado adecuado: menores de edad o mayores de edad.","Imprimir, firmar y cargar el consentimiento informado en PDF o imagen."])
p("La página contiene enlaces de descarga para formatos de menores y mayores de edad, un enlace de consulta sobre tipos de familia y el Manual de Convivencia. Antes de enviar, el usuario debe verificar que los archivos sean legibles y correspondan a la persona inscrita.")
h2("3.6 Envío")
p("El botón <b>Enviar Formulario</b> inicia una confirmación final. Solo debe confirmarse después de revisar todo. Si falta un campo obligatorio o un archivo, la página puede impedir el envío y señalar el dato pendiente. Después del envío, la solicitud pasa al flujo de revisión y el estado se consulta iniciando sesión como deportista.")
story.append(PageBreak())

h1("4. Inicio de sesión")
p("El acceso se abre con el botón <b>Iniciar Sesión</b> de la portada. La pantalla solicita <b>Usuario</b> y <b>Contraseña</b>. Después se oprime nuevamente <b>Iniciar Sesión</b>; durante la validación puede aparecer Procesando. La plataforma identifica el perfil y redirige automáticamente a su panel.")
shot("03_inicio_sesion.png","Pantalla de acceso. La imagen pudo no generarse en algunas sesiones del navegador; la estructura se verificó directamente.")
table([["Elemento","Uso"],["Usuario","Escribir el identificador asignado, respetando puntos y caracteres."],["Contraseña","Escribir la clave; se muestra oculta."],["¿Olvidaste o no recuerdas tu usuario?","Acceso previsto para recuperación de usuario."],["Ir a Inscripciones","Regresa a la página pública y al proceso de inscripción."],["Cerrar Sesión","Finaliza el acceso y vuelve al login."]],[6*cm,11*cm])
p("No se recomienda compartir credenciales ni dejar abierta una sesión en un computador público. Si aparece un error, verificar usuario, clave, conexión y que el perfil esté activo.")

h1("5. Perfil Administrador")
p("Al ingresar se muestra <b>Administración del Sistema</b>, el nombre del administrador y los accesos <b>Profesores, Deportes, Deportistas, Metodólogos y Ajustes</b>.")
shot("13_panel_administrador_actualizado.png","Panel administrativo actualizado en el dominio oficial.")
h2("5.1 Ajustes del perfil")
p("El nuevo botón <b>Ajustes</b> permite iniciar el cambio de contraseña, alternar entre apariencia Clara y Oscura y seleccionar Español, Inglés o Francés. El cambio de contraseña solo se confirma al completar el formulario y oprimir Cambiar.")
h2("5.1 Profesores")
p("Abre una lista de tarjetas. Cada tarjeta muestra nombre, código interno (por ejemplo PROF003), estado Activo/Inactivo, usuario, correo, teléfono y deportes asignados. El control visible permite <b>Marcar Inactivo</b> o reactivar según el estado. Esta acción afecta la disponibilidad del acceso del profesor, por lo que debe usarse con cuidado.")
p("En la versión revisada no se observó un formulario general para cambiar nombre, correo, teléfono o usuario del profesor desde esta lista; la operación disponible fue el cambio de estado. No debe afirmarse en el video que todos esos campos se editan si la interfaz publicada no lo muestra.", "Callout")
h2("5.2 Deportes")
p("Muestra tarjetas con código, nombre, condición Ofrecido/No ofrecido, número actual de estudiantes frente al cupo permitido y rango de edad. Al seleccionar una tarjeta se abre <b>Editar Deporte</b>.")
table([["Campo","Comportamiento"],["ID Deporte","Solo lectura; no editable."],["Edad mínima","Número mínimo admitido."],["Edad máxima","Número máximo admitido."],["Estudiantes permitidos","Cupo máximo configurado."],["Ofrecido a los padres","Casilla que habilita o retira el deporte de la oferta visible."],["Guardar","Confirma cambios."],["Cancelar / cerrar","Descarta cambios no guardados."]],[6*cm,11*cm])
p("El deporte de prueba se encontró como DEP075 - Deporte Prueba. La pantalla permite ajustar edades, cupo y estado de oferta. Siempre se debe comprobar el registro correcto antes de guardar.")
h2("5.3 Deportistas")
p("El módulo dispone de pestañas <b>Todos, En revisión, Verificado y Devuelto</b>; filtros por discapacidad y rangos de edad; y el campo <b>Buscar estudiante</b>. La carga inicial es lenta: puede tardar alrededor de <b>50 a 60 segundos</b>. Mientras aparece Cargando información de deportistas y los contadores siguen en cero, el administrador debe esperar sin cerrar el módulo ni recargar la página.")
p("Después de 55 segundos, la revisión mostró 2.991 registros: 3 En revisión, 2.614 Verificados y 374 Devueltos. Estas cantidades son dinámicas y cambiarán cuando se revisen nuevas solicitudes.")
shot("08_admin_deportista_detalle.png","Ficha administrativa de un estudiante de prueba. La captura muestra una de las pestañas del detalle.")
h3("Buscar y filtrar")
bullets(["Todos muestra el conjunto completo.","En revisión limita la lista a solicitudes pendientes.","Verificado muestra solicitudes aprobadas.","Devuelto muestra solicitudes que requieren correcciones.","Discapacidad permite ver todos, con discapacidad o sin discapacidad.","Edades filtra por 0-12, 13-17, 18-30 o 31 años en adelante.","Buscar estudiante localiza por el texto ingresado, por ejemplo nombre o documento."])
h3("Abrir la ficha")
p("Al seleccionar la tarjeta de un deportista se abre una ficha con nombre, documento, usuario y estado. La ficha se divide en <b>Salud, Identificación y Familia y Otros</b>.")
table([["Pestaña","Información consultable"],["Salud","EPS, régimen, RH, alergias, medicamentos, condiciones médicas, antecedentes de enfermedades, cirugías y lesiones, certificado EPS y discapacidad."],["Identificación","Lugar de nacimiento, expedición, género, dirección, vereda/barrio, población, institución, grado, tipo de institución, documento de identidad y consentimiento informado."],["Familia y Otros","Datos del acudiente principal: nombres, apellidos, documento y celular; puede contener información familiar adicional según el registro."]],[4*cm,13*cm])
h3("Cambiar estado y registrar devolución")
p("En la parte inferior se encuentra <b>Cambiar Estado</b>, con las opciones En revisión, Verificado y Devuelto. El campo <b>Motivo de devolución</b> sirve para explicar la corrección requerida. Después de elegir el estado y escribir la observación, <b>Guardar Cambios</b> confirma la actualización. Cerrar sale sin guardar.")
h3("Editar estudiante")
p("El botón <b>Editar Estudiante</b> abre un formulario para modificar <b>Nombre, Apellidos del deportista, Documento y Email</b>. Enviar guarda; Cancelar o cerrar descarta la edición. Debe comprobarse que se abrió la persona correcta antes de enviar.")
h3("Editar deportes del estudiante")
p("El botón <b>Editar Deportes</b> abre <b>Gestionar Deportes</b>. La plataforma carga una lista de disciplinas con casillas. Marcar una casilla inscribe o asocia el deporte; desmarcarla lo retira. Guardar aplica la selección y Cancelar la descarta. La lista puede tardar unos segundos adicionales en aparecer.")
h2("5.4 Metodólogos")
p("El módulo fue corregido y ahora muestra realmente los metodólogos. Cada tarjeta presenta nombre, código interno, estado y usuario. El administrador puede usar <b>Marcar Inactivo</b> o reactivar el perfil. En la revisión aparecieron Camila Morales (MET001), Alejandro Suarez (MET002) y Paula Mendoza (MET003).")
h2("5.5 Cerrar módulos y sesión")
p("Cada ventana administrativa tiene el botón Cerrar para volver al menú de cuatro opciones. <b>Cerrar Sesión</b> termina la sesión completa.")
story.append(PageBreak())

h1("6. Perfil Profesor")
p("El panel del profesor fue renovado. El acceso probado corresponde a Andres Coral, usuario <b>a.coral15</b>. Los antiguos botones Mis Grupos, Asistencia y Planificación fueron retirados. Ahora la navegación contiene <b>Mis Deportes</b> y <b>Ajustes</b>.")
shot("09_panel_profesor_actualizado.png","Pantalla Mis Deportes del profesor. Cada tarjeta abre la gestión de una disciplina.")
h2("6.1 Mis Deportes")
p("La pantalla muestra los deportes dictados por el profesor, su código y el estado Dictando. Andres Coral tenía asignados Deporte Prueba (DEP075) y Ajedrez masculino y femenino (DEP001). Al seleccionar una tarjeta se abre la gestión de esa disciplina.")
shot("10_profesor_gestion_deporte.png","Gestión de Deporte Prueba con las cuatro áreas operativas.")
h2("6.2 Curso y tabla de asistencia")
p("La pestaña <b>1) Curso</b> muestra una matriz por estudiante y clase. Incluye buscador, porcentaje acumulado y estados Asistió, Faltó o Tarde para cada sesión. Las columnas identifican número de clase, fecha y observación.")
h3("Tomar asistencia")
p("El botón <b>Tomar Asistencia</b> abre un proceso de dos pasos. En el primero se marca Asistió, Faltó o Tarde para cada deportista; <b>Marcar Todos Asistió</b> permite establecer la opción general y luego ajustar excepciones. En el segundo paso se completa Fecha de la clase, Lugar y Observaciones. Atrás regresa al listado; <b>Guardar Asistencia</b> registra definitivamente la sesión.")
p("Guardar Asistencia modifica el historial y no debe utilizarse en una demostración con datos reales.", "Callout")
h2("6.3 Lista de estudiantes")
p("La pestaña <b>2) Lista de Estudiantes</b> carga los deportistas inscritos con información de contacto y estado. Puede aparecer inicialmente Cargando lista de estudiantes; se debe esperar y usar Actualizar si es necesario.")
h2("6.4 Comunicados")
p("La pestaña <b>3) Comunicados</b> permite consultar avisos enviados y abrir <b>Enviar Comunicado</b>. El formulario solicita Título y Mensaje. Cancelar descarta; Enviar Comunicado publica el aviso para los deportistas vinculados al deporte.")
h2("6.5 Información del deporte")
p("La pestaña <b>4) Info Deporte</b> presenta estudiantes inscritos, cupo máximo, inclusión/discapacidad, edades, género permitido, profesores encargados y comentarios del metodólogo.")
h2("6.6 Ajustes y retorno")
p("Ajustes permite cambiar contraseña, apariencia e idioma. <b>Volver a Mis Deportes</b> regresa al listado; Cerrar Sesión termina el acceso.")

h1("7. Perfil Metodólogo")
p("El perfil fue reemplazado por un <b>Dashboard Metodólogo</b> completamente funcional para seguimiento, control e informes. En la revisión, Camila Morales tenía 75 deportes supervisados.")
shot("11_panel_metodologo_actualizado.png","Dashboard actualizado del metodólogo.")
h2("7.1 Buscar y actualizar")
p("El buscador filtra por nombre del deporte o código. <b>Actualizar</b> vuelve a cargar la información. Cada tarjeta muestra código, cupo permitido, edades, género y etiquetas que indican si aparece en Web o para Padres.")
h2("7.2 Comentario técnico")
p("El botón <b>Comentario</b> abre Agregar Comentario Metodólogo. El campo Observaciones/Comentario Técnico permite describir el desarrollo de las clases del profesor. <b>Guardar Comentario</b> publica la observación, que después aparece en Info Deporte del profesor; Cancelar o cerrar sale sin guardar.")
h2("7.3 Documento")
p("El botón <b>Documento</b> descarga el reporte actualizado de asistencia correspondiente al deporte, función anunciada por el propio dashboard. Se debe escoger primero la tarjeta correcta para no confundir reportes.")
h2("7.4 Ajustes")
p("El botón Ajustes permite cambiar contraseña, apariencia e idioma. Cerrar Sesión vuelve al acceso general.")
story.append(PageBreak())

h1("8. Perfil Deportista o Estudiante")
p("El panel muestra el nombre, estado de revisión, deportes inscritos y ajustes. Se comprobaron un estudiante Devuelto y otro Verificado para documentar ambos recorridos.")
shot("12_panel_deportista_actualizado.png","Estudiante verificado con un deporte inscrito.")
h2("8.1 Estados de revisión")
table([["Estado","Significado práctico"],["En revisión","La información fue enviada y está pendiente de validación."],["Verificado","La revisión fue aprobada."],["Devuelto","Se encontraron inconsistencias; el estudiante debe corregir documentos y reenviar."]],[4*cm,13*cm])
p("Cuando el estado es Devuelto aparece una explicación y el botón <b>Subsanar Documentos</b>. Un estudiante verificado puede no ver este botón.")
h2("8.2 Mis Deportes Inscritos")
p("La sección lista las disciplinas asociadas. Si no existe ninguna aparece No se encontraron deportes inscritos. Al seleccionar un deporte se abre una nueva pantalla con <b>Comunicados, Información del Profesor e Información del Deporte</b>.")
h3("Comunicados")
p("Muestra los avisos publicados por el profesor con título, fecha, hora y mensaje. Sirve para cambios de horario, suspensión de clases, evaluaciones, torneos y otras novedades.")
h3("Información del profesor")
p("Presenta Nombres y apellidos e Información adicional cuando esos datos están configurados. Si aparecen vacíos, el estudiante debe consultar al IMRD en vez de asumir información.")
h3("Información del deporte")
p("Muestra Lugar, Horario e Implementos. Los valores pueden aparecer Por definir hasta que sean configurados. <b>Volver al Panel</b> regresa a Mis Deportes Inscritos.")
h2("8.3 Ajustes del perfil")
p("El botón con icono de engranaje abre Ajustes del Perfil:")
bullets(["Contraseña: botón Cambiar para iniciar la actualización de clave.","Apariencia: alternar entre modo Claro y Oscuro.","Idioma: seleccionar Español, English (Inglés) o Français (Francés).","Cerrar: salir de ajustes y regresar al panel."])
h2("8.4 Subsanar documentos")
p("Al oprimir <b>Subsanar Documentos</b> aparece una pantalla con botón <b>Volver al Panel</b>, observaciones del revisor y campos para cargar correcciones. En el caso probado solicitó nuevamente:")
bullets(["Copia del documento de identidad (PDF o imagen).","Certificado de EPS activo; la interfaz advierte que no acepta certificado de la plataforma ADRES.","Consentimiento informado firmado, con enlaces para descargar formato de menores o mayores de edad.","Soporte de víctima del conflicto (RUV), cuando corresponda."])
p("Los controles indican máximo dos archivos por apartado. Después de elegir archivos correctos, se oprime <b>Enviar Correcciones</b>. El usuario debe comprobar que los documentos sean legibles y correspondan a la observación. Volver al Panel permite salir sin enviar.")
p("El envío de correcciones cambia información en el sistema. No se debe oprimir Enviar Correcciones durante una demostración salvo que se hayan seleccionado archivos de prueba autorizados.", "Callout")

h1("9. Recomendaciones para el guion del video")
bullets(["Comenzar siempre en https://imrd-cota.nextgonsas.com.co.","Presentar la portada, título 2026, contador, formulario y APK.","Explicar que Iniciar Sesión dirige automáticamente al perfil correspondiente.","En administrador, mostrar Ajustes y los cuatro módulos de gestión.","En profesor, comenzar por Mis Deportes y recorrer Curso, Lista de Estudiantes, Comunicados e Info Deporte.","Mostrar los dos pasos de Tomar Asistencia sin guardar una sesión ficticia.","En metodólogo, enseñar búsqueda, Actualizar, Comentario y Documento.","En deportista, diferenciar Devuelto de Verificado y mostrar Comunicados e información del deporte.","No mencionar los antiguos menús Mis Grupos, Asistencia, Planificación, Resumen, Planes o Evaluaciones: fueron retirados."])

h1("10. Solución de problemas frecuentes")
table([["Situación","Qué revisar"],["No inicia sesión","Usuario exacto, contraseña, conexión y estado activo del perfil."],["Aparece error de conexión","Recargar una vez, comprobar el identificador y volver a intentar; si persiste, reportarlo."],["El formulario no envía","Campos obligatorios, aceptación de declaraciones y archivos requeridos."],["Archivo rechazado","Formato PDF/imagen, legibilidad, tamaño y número máximo de archivos."],["No aparece un deporte","Estado Ofrecido, rango de edad, cupo y asociación del estudiante."],["Solicitud Devuelta","Leer observaciones, reemplazar documentos y usar Enviar Correcciones."],["Módulo queda cargando","Esperar brevemente, revisar conexión y comunicar el caso al soporte; no inventar datos."],["Menú sin contenido","Puede ser una función prevista aún no implementada o sin asignaciones para ese usuario."]],[5.5*cm,11.5*cm])

h1("11. Observaciones de la revisión funcional")
bullets(["La revisión actual se realizó en el dominio oficial; el entorno prueba devolvió 404 para el administrador.","El administrador incorporó Ajustes y el módulo Metodólogos fue corregido.","El profesor ahora gestiona deportes, asistencias, estudiantes, comunicados e información técnica.","El metodólogo ahora supervisa 75 deportes, registra comentarios y descarga documentos de asistencia.","El deportista verificado puede abrir cada deporte y consultar comunicados, profesor, lugar, horario e implementos.","El deportista Devuelto conserva el flujo de subsanación.","Los menús anteriores sin contenido fueron retirados de la interfaz y del manual."])
p("Fin del manual. Antes de producir el video definitivo, conviene repetir una comprobación corta en el dominio oficial para detectar cualquier modificación publicada después de esta revisión.", "Callout")

doc=SimpleDocTemplate(str(OUT),pagesize=A4,rightMargin=1.8*cm,leftMargin=1.8*cm,topMargin=1.7*cm,bottomMargin=1.7*cm,title="Manual de usuario IMRD Cota 2026",author="Codex")
doc.build(story,onFirstPage=footer,onLaterPages=footer)
print(OUT)
