flowchart TD
classDef startEnd fill:#333,stroke:#333,stroke-width:2px,color:#fff;
classDef process fill:#e1f5fe,stroke:#0288d1;
classDef decision fill:#fff9c4,stroke:#fbc02d;
classDef cloudAction fill:#e8eaf6,stroke:#3f51b5;
classDef fail fill:#ffebee,stroke:#e53935;
classDef success fill:#e8f5e9,stroke:#43a047;
START([Inicio del Sistema]):::startEnd --> INIT[Inicializar ESP32, Sensores, RFID, OLED]:::process
INIT --> CONN{¿Conexión a Internet / Firebase / MQTT?}:::decision
CONN -- No --> BYPASS_CHK1{¿Activar Bypass?}:::decision
BYPASS_CHK1 -- Sí --> OPEN_BY[Abrir Molinete mediante Hardware de Emergencia]:::fail
OPEN_BY --> RECONN[Intentar Reconexión]:::process
RECONN --> CONN
CONN -- Sí --> LOOP[Bucle Principal]:::process
LOOP --> PUB[Publicar Telemetría vía MQTT\nVelocidad, Estado]:::cloudAction
PUB --> CHECK_BY{¿Circuito Bypass Activo por Operador?}:::decision
CHECK_BY -- Sí --> HOLD[Mantener Servo Abierto]:::fail
HOLD --> LOOP
CHECK_BY -- No --> WAIT_RFID{¿Tarjeta RFID o Celular detectado?}:::decision
WAIT_RFID -- No --> LOOP
WAIT_RFID -- Sí --> READ_ID[Leer ID y Enviar a Firebase]:::cloudAction
READ_ID --> FIREBASE_DEC{Firebase evalúa:\n¿Existe el Usuario y \nTiene Saldo > 0?}:::decision
FIREBASE_DEC -- No --> DENIED[Mostrar 'Acceso Denegado' en OLED\nEncender LED Rojo]:::fail
DENIED --> LOOP
FIREBASE_DEC -- Sí --> CLASSIFY[Firebase devuelve Perfil:\nDocente/Estudiante/Discapacidad/Extra]:::process
CLASSIFY --> DEDUCT[Descontar tarifa específica\nsegún el perfil]:::cloudAction
DEDUCT --> ALLOWED[Mostrar 'Acceso Permitido' y Saldo\nEncender LED Verde]:::success
ALLOWED --> OPEN_SERVO[ESP32 manda señal PWM\nAbrir Molinete MG90S]:::success
OPEN_SERVO --> WAIT_PASS[Esperar paso del pasajero]:::process
WAIT_PASS --> CLOSE_SERVO[Cerrar Molinete MG90S]:::process
CLOSE_SERVO --> LOOP
* Firebase es quien toma la decisión de acceso en función del ID recibido, aplicando tarifas discriminativas y validando el saldo. El ESP32 es el ejecutor que acciona los LEDs, la pantalla y el Servo.