<!doctype html>
<html lang="<?= esc($currentLocale ?? 'pt') ?>">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= esc($pageTitle ?? 'Quantum Demo | Simulador de manutencao') ?></title>
    <meta name="description" content="Demo publica Quantum para simular eventos tecnicos, rastreabilidade e auditoria de manutencoes.">
    <link rel="icon" type="image/png" href="<?= base_url('assets/icon.png') ?>">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&family=IBM+Plex+Sans:wght@400;500;600;700&family=Sora:wght@400;500;600;700&display=swap" rel="stylesheet">
    <script>
        (() => {
            try {
                const theme = localStorage.getItem('quantum-public-theme') || 'dark';
                document.documentElement.setAttribute('data-theme', theme);
            } catch (error) {
                document.documentElement.setAttribute('data-theme', 'dark');
            }
        })();
    </script>
    <style>
        :root{color-scheme:dark light;--bg:#07131f;--panel:rgba(10,23,36,.84);--panel-2:rgba(14,28,43,.96);--line:rgba(255,255,255,.1);--text:#f8fbff;--muted:#98adc1;--primary:#2563eb;--primary-soft:rgba(37,99,235,.14);--secondary:#22d3ee;--accent:#ffd166;--shadow:0 24px 70px rgba(0,0,0,.38);--r:24px;--max:1320px}
        *{box-sizing:border-box} body{margin:0;font-family:'IBM Plex Sans',sans-serif;color:var(--text);background:radial-gradient(circle at 10% 15%,rgba(37,99,235,.12),transparent 22%),radial-gradient(circle at 85% 15%,rgba(34,211,238,.12),transparent 24%),linear-gradient(180deg,#06111a 0%,#081522 50%,#07131f 100%)} body::before{content:"";position:fixed;inset:0;background-image:linear-gradient(rgba(255,255,255,.02) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.02) 1px,transparent 1px);background-size:80px 80px;mask-image:linear-gradient(180deg,rgba(0,0,0,.8),transparent 90%);pointer-events:none;z-index:-1}
        h1,h2,h3,strong.mono,.digit{font-family:'Sora',sans-serif;letter-spacing:-.04em;margin:0} p{margin:0;color:var(--muted);line-height:1.65} a{color:inherit;text-decoration:none} button,input{font:inherit}
        .container{width:min(100%,var(--max));margin:0 auto;padding:0 1.25rem}.header{position:sticky;top:0;z-index:30;background:rgba(6,17,26,.84);border-bottom:1px solid rgba(255,255,255,.06);backdrop-filter:blur(18px)}.header-row{min-height:84px;display:flex;align-items:center;justify-content:space-between;gap:1rem}.brand img{width:188px;height:54px;object-fit:contain;filter:drop-shadow(0 12px 28px rgba(37,99,235,.22))}.actions{display:flex;gap:.8rem;flex-wrap:wrap}.menu-toggle{display:none;align-items:center;justify-content:center;width:48px;height:48px;border:1px solid rgba(255,255,255,.14);border-radius:14px;background:rgba(255,255,255,.04);color:var(--text);cursor:pointer}.menu-toggle svg{width:22px;height:22px}.mobile-menu{display:none;padding:0 0 1rem}.mobile-menu.open{display:block}.mobile-panel{display:grid;gap:.8rem;padding:1rem;border-radius:22px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08)}.mobile-links{display:grid;gap:.65rem}.mobile-links a{display:flex;align-items:center;justify-content:center;min-height:48px;padding:.8rem 1rem;border-radius:16px;border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.03);color:var(--text);font-weight:600}
        .btn{display:inline-flex;align-items:center;justify-content:center;gap:.55rem;min-height:50px;padding:.9rem 1.25rem;border-radius:999px;border:1px solid transparent;cursor:pointer;font-weight:700;transition:transform .2s ease,background .2s ease}.btn:hover{transform:translateY(-1px)}.btn-primary{background:linear-gradient(135deg,var(--primary),var(--secondary));color:#06111f;box-shadow:0 16px 36px rgba(37,99,235,.24)}.btn-secondary{background:rgba(255,255,255,.04);color:var(--text);border-color:rgba(255,255,255,.14)}.theme-toggle{width:48px;min-width:48px;padding:0;border-radius:14px}.theme-toggle svg{width:20px;height:20px}.theme-icon-dark{display:none}html[data-theme="dark"] .theme-icon-light{display:none}html[data-theme="dark"] .theme-icon-dark{display:inline-block}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
        .hero{padding:4rem 0 2rem}.grid-2{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(320px,.95fr);gap:1.4rem}.card,.panel,.modal-panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);backdrop-filter:blur(16px)}.hero-copy,.meter-card,.panel,.modal-panel{padding:1.5rem}.eyebrow,.pill,.badge{display:inline-flex;align-items:center;gap:.55rem;padding:.7rem 1rem;border-radius:999px;font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.12em}
        .eyebrow{color:#dbeafe;background:var(--primary-soft);border:1px solid rgba(37,99,235,.22)}.eyebrow::before,.pill::before{content:"";width:.55rem;height:.55rem;border-radius:999px;background:currentColor}.pill{color:var(--secondary);background:rgba(34,211,238,.12);border:1px solid rgba(34,211,238,.18)}.badge{padding:.45rem .75rem;font-size:.72rem;letter-spacing:.08em}.ok{color:#dbeafe;background:rgba(37,99,235,.12)}.wait{color:var(--accent);background:rgba(255,209,102,.12)}
        .hero-copy{display:grid;gap:1.2rem}.hero-copy h1{font-size:clamp(2.7rem,5vw,4.8rem);line-height:.98}.stats,.summary,.station,.fields,.modal-stages{display:grid;gap:.9rem}.stats{grid-template-columns:repeat(3,minmax(0,1fr))}.stat,.mini,.summary-card,.reading,.timeline,.stage,.log,.certificate{padding:1rem;border-radius:18px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)}.stat strong,.mini strong,.summary-card strong,.certificate strong{display:block;margin-top:.3rem;font-size:1.45rem;color:var(--text)}.hero-copy .action-row .btn{white-space:nowrap}
        .meter-card{display:grid;gap:1rem;background:linear-gradient(180deg,rgba(12,25,39,.96),rgba(8,18,29,.96))}.split{display:grid;grid-template-columns:minmax(0,1.1fr) 220px;gap:1rem}.meter{padding:1.1rem;border-radius:28px;background:radial-gradient(circle at 50% 0%,rgba(255,255,255,.08),transparent 35%),linear-gradient(180deg,#192a3a 0%,#0d1822 100%);border:1px solid rgba(255,255,255,.08)}.meter-top,.row{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}.display{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:.35rem;padding:.8rem;border-radius:22px;background:linear-gradient(180deg,#080f16 0%,#111e2a 100%);border:1px solid rgba(255,255,255,.08);box-shadow:inset 0 0 22px rgba(0,0,0,.5);margin-top:1rem}.digit{min-height:70px;border-radius:14px;display:grid;place-items:center;font-size:clamp(2rem,4vw,3rem);background:linear-gradient(180deg,rgba(13,31,48,.92),rgba(4,12,18,.96));border:1px solid rgba(101,182,255,.2)}.side{padding:1rem;border-radius:24px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);display:grid;gap:.85rem;align-content:space-between}.bars{display:flex;align-items:flex-end;gap:.35rem;min-height:72px}.bars span{flex:1;border-radius:999px 999px 0 0;background:linear-gradient(180deg,rgba(101,182,255,.34),rgba(34,211,238,.96))}.bars span:nth-child(1){height:22%;opacity:.45}.bars span:nth-child(2){height:42%;opacity:.62}.bars span:nth-child(3){height:67%;opacity:.8}.bars span:nth-child(4){height:88%}
        .section{padding:0 0 4rem}.board{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(300px,.8fr);gap:1.4rem}.head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;margin-bottom:1rem}.head h2{font-size:clamp(1.8rem,3vw,2.6rem)}.station,.summary{grid-template-columns:repeat(2,minmax(0,1fr))}.range{display:grid;gap:.5rem;margin-top:1rem}.range input[type=range]{width:100%;accent-color:var(--primary)}.fields{grid-template-columns:repeat(2,minmax(0,1fr));margin-top:1rem}.field{display:grid;gap:.45rem}.field label,.helper{font-size:.92rem;color:var(--muted)}.field input{min-height:52px;border-radius:14px;border:1px solid rgba(255,255,255,.12);background:rgba(4,12,18,.7);color:var(--text);padding:.9rem 1rem}.action-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-top:1.1rem}
        .list{display:grid;gap:.9rem}.reading,.timeline,.log{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem}.reading strong,.timeline strong,.log strong{display:block;margin-bottom:.22rem}.timeline{position:relative;padding-left:1.2rem}.timeline::before{content:"";position:absolute;left:0;top:1.05rem;width:.55rem;height:.55rem;border-radius:999px;background:var(--primary);box-shadow:0 0 0 6px rgba(42,211,145,.12)}.empty{text-align:center;padding:1.25rem;border-radius:18px;border:1px dashed rgba(255,255,255,.18);color:var(--muted)}
        .modal{position:fixed;inset:0;background:rgba(4,10,16,.76);display:none;align-items:center;justify-content:center;padding:1.2rem;z-index:90}.modal.open{display:flex}.modal-panel{width:min(940px,100%);max-height:90vh;overflow:auto;background:var(--panel-2)}.modal-header,.modal-footer{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}.close{width:46px;height:46px;border-radius:14px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.04);color:var(--text);cursor:pointer}.progress{height:14px;border-radius:999px;background:rgba(255,255,255,.06);overflow:hidden;margin:1rem 0 .9rem}.bar{width:0;height:100%;background:linear-gradient(90deg,var(--secondary),var(--primary));transition:width .45s ease}.modal-stages{grid-template-columns:repeat(2,minmax(0,1fr))}.stage.active{border-color:rgba(42,211,145,.34);background:rgba(42,211,145,.08)}.stage.done{border-color:rgba(101,182,255,.28)}
        html[data-theme="light"]{--bg:#edf4fb;--panel:rgba(255,255,255,.9);--panel-2:rgba(255,255,255,.98);--line:rgba(16,34,53,.1);--text:#102235;--muted:#62778c;--primary-soft:rgba(37,99,235,.12);--shadow:0 24px 70px rgba(22,54,88,.12)}html[data-theme="light"] body{background:radial-gradient(circle at 10% 15%,rgba(37,99,235,.12),transparent 22%),radial-gradient(circle at 85% 15%,rgba(34,211,238,.12),transparent 24%),linear-gradient(180deg,#f9fcff 0%,#edf4fb 50%,#e7eff8 100%)}html[data-theme="light"] body::before{background-image:linear-gradient(rgba(16,34,53,.04) 1px,transparent 1px),linear-gradient(90deg,rgba(16,34,53,.04) 1px,transparent 1px);opacity:.82}html[data-theme="light"] .header{background:rgba(249,252,255,.84);border-bottom:1px solid rgba(16,34,53,.08)}html[data-theme="light"] .btn-secondary,html[data-theme="light"] .menu-toggle,html[data-theme="light"] .mobile-panel,html[data-theme="light"] .mobile-links a,html[data-theme="light"] .stat,html[data-theme="light"] .mini,html[data-theme="light"] .summary-card,html[data-theme="light"] .reading,html[data-theme="light"] .timeline,html[data-theme="light"] .stage,html[data-theme="light"] .log,html[data-theme="light"] .certificate,html[data-theme="light"] .side,html[data-theme="light"] .field input,html[data-theme="light"] .close,html[data-theme="light"] .progress{background:rgba(255,255,255,.78);border-color:rgba(16,34,53,.1)}html[data-theme="light"] .meter-card{background:linear-gradient(180deg,rgba(255,255,255,.98),rgba(239,246,252,.96))}html[data-theme="light"] .meter{background:radial-gradient(circle at 50% 0%,rgba(78,164,255,.14),transparent 35%),linear-gradient(180deg,#f6fbff 0%,#e9f2fb 100%);border-color:rgba(16,34,53,.1)}html[data-theme="light"] .display{background:linear-gradient(180deg,#edf4fb 0%,#dce8f3 100%);border-color:rgba(16,34,53,.1);box-shadow:inset 0 0 18px rgba(123,150,178,.22)}html[data-theme="light"] .digit{background:linear-gradient(180deg,rgba(255,255,255,.98),rgba(233,241,248,.96));border-color:rgba(101,182,255,.28)}html[data-theme="light"] .btn-secondary:hover,html[data-theme="light"] .mobile-links a:hover{background:rgba(16,34,53,.06)}
        @media (max-width:1080px){.grid-2,.board,.split{grid-template-columns:1fr}} @media (max-width:760px){.stats,.station,.summary,.fields,.modal-stages{grid-template-columns:1fr}.header-row{min-height:76px}.actions{display:none}.menu-toggle{display:inline-flex}.digit{min-height:56px;font-size:1.7rem}.hero,.section{padding-bottom:2rem}.hero{padding-top:1rem}.hero-copy,.meter-card,.panel,.modal-panel{padding:1.15rem}.action-row{align-items:stretch}.action-row .btn{width:100%}.mobile-menu{display:none}}
    </style>
</head>
<body>
<header class="header"><div class="container"><div class="header-row"><a class="brand" href="<?= site_url('/') ?>"><img src="<?= base_url('assets/quantum-wordmark.svg') ?>" alt="Quantum"></a><button class="menu-toggle" id="menuToggle" type="button" aria-expanded="false" aria-controls="mobileMenu" aria-label="Abrir menu"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M4 7h16"></path><path d="M4 12h16"></path><path d="M4 17h16"></path></svg></button><div class="actions"><button class="btn btn-secondary theme-toggle" type="button" data-theme-toggle aria-label="Ativar modo escuro" title="Ativar modo escuro"><span class="theme-icon-light" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z"></path></svg></span><span class="theme-icon-dark" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2.2M12 19.8V22M4.93 4.93l1.55 1.55M17.52 17.52l1.55 1.55M2 12h2.2M19.8 12H22M4.93 19.07l1.55-1.55M17.52 6.48l1.55-1.55"></path></svg></span><span class="sr-only">Alternar tema</span></button><a class="btn btn-secondary" href="<?= site_url('/') ?>">Landing</a><a class="btn btn-secondary" href="<?= site_url('audit') ?>">Auditoria</a></div></div><div class="mobile-menu" id="mobileMenu"><div class="mobile-panel"><div class="mobile-links"><button class="btn btn-secondary theme-toggle" type="button" data-theme-toggle aria-label="Ativar modo escuro" title="Ativar modo escuro"><span class="theme-icon-light" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z"></path></svg></span><span class="theme-icon-dark" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2.2M12 19.8V22M4.93 4.93l1.55 1.55M17.52 17.52l1.55 1.55M2 12h2.2M19.8 12H22M4.93 19.07l1.55-1.55M17.52 6.48l1.55-1.55"></path></svg></span><span class="sr-only">Alternar tema</span></button><a href="<?= site_url('/') ?>">Landing</a><a href="<?= site_url('audit') ?>">Auditoria</a><a href="#communicateButton">Registar evento</a></div></div></div></div></header>
<main>
    <section class="hero"><div class="container grid-2">
        <div class="card hero-copy">
            <span class="eyebrow">Demo - RASTREABILIDADE TECNICA</span>
            <h1>Simulador de manutencao para uma turbina eolica demo.</h1>
            <p>Esta pagina simula o lado operacional: uma equipa tecnica regista um evento de manutencao, valida o intervalo, atualiza a rastreabilidade e prepara a auditoria blockchain. Tudo acontece visualmente quando clicas em registar.</p>
            <div class="stats">
                <article class="stat"><span>Parque eolico</span><strong>Lusitania Wind LX-01</strong></article>
                <article class="stat"><span>Periodicidade</span><strong>10 min</strong></article>
                <article class="stat"><span>Modo</span><strong>Operacao Demo</strong></article>
            </div>
            <div class="action-row"><p>Usa o campo do evento para ajustar o impacto tecnico do intervalo e depois regista. O modal mostra o processo completo ate a auditoria.</p><button class="btn btn-primary" type="button" id="heroCommunicate">Registar agora</button></div>
        </div>
        <section class="card meter-card">
            <div class="row"><div><div class="helper">Turbina demo</div><h2>Turbine QN-WT-2026</h2></div><span class="eyebrow">Online</span></div>
            <div class="split">
                <div class="meter">
                    <div class="meter-top"><div><strong class="mono">Quantum Turbine</strong><p>Serie DEMO-88421</p></div><div class="helper">Horas acumuladas</div></div>
                    <div class="display" id="meterDisplay" aria-live="polite"></div>
                    <p style="text-align:right;margin-top:.75rem;color:var(--secondary);font-weight:700;letter-spacing:.1em;text-transform:uppercase">horas acumuladas</p>
                </div>
                <aside class="side">
                    <div><div class="helper">Sinal</div><div class="bars" aria-hidden="true"><span></span><span></span><span></span><span></span></div></div>
                    <div><div class="helper">Ultimo registo</div><strong class="mono" id="lastCommunicationLabel">Ainda sem envio</strong></div>
                    <div><div class="helper">Proximo intervalo</div><strong class="mono" id="nextIntervalLabel">09:10</strong></div>
                </aside>
            </div>
        </section>
    </div></section>

    <section class="section"><div class="container board">
        <section class="panel">
            <div class="head"><div><div class="helper">Operacao tecnica</div><h2>Inserir evento e registar</h2></div><span class="pill">A aguardar envio</span></div>
            <div class="station">
                <article class="mini"><span class="helper">Tecnologia</span><strong>Eolica onshore</strong><p>Turbina demo associada ao cliente para apresentacoes comerciais e testes visuais.</p></article>
                <article class="mini"><span class="helper">Impacto instantaneo</span><strong id="powerValue">128.4 kW</strong><p>Valor demo ajustado dinamicamente para sugerir intensidade tecnica ao longo dos registos.</p></article>
            </div>
            <div class="range"><label for="readingRange">Evento do intervalo de 10 minutos</label><input id="readingRange" type="range" min="8" max="42" step="0.1" value="21.4"></div>
            <div class="fields">
                <div class="field"><label for="readingValue">Impacto tecnico (kWh)</label><input id="readingValue" type="number" min="0" step="0.1" value="21.4"></div>
                <div class="field"><label for="sourceReference">Referencia do evento</label><input id="sourceReference" type="text" value="EVT-DEMO-0001"></div>
            </div>
            <div class="summary" style="margin-top:1rem">
                <article class="summary-card"><span class="helper">Intervalo pronto a registar</span><strong id="currentIntervalLabel">25 Mar 2026 09:00 - 09:10</strong></article>
                <article class="summary-card"><span class="helper">Estimativa de auditoria</span><strong id="estimatedCertificateEnergy">21.4 kWh</strong></article>
            </div>
            <div class="action-row"><p>Ao registar, a demo simula a recolha, validacao, rastreabilidade do evento, auditoria blockchain e atualizacao do estado da turbina.</p><button class="btn btn-primary" type="button" id="communicateButton">Registar evento</button></div>
        </section>
        <aside class="panel">
            <div class="head"><div><div class="helper">Resumo da demo</div><h2>Estado atual</h2></div><span class="badge ok" id="statusBadge">Pronto</span></div>
            <div class="summary">
                <article class="summary-card"><span class="helper">Eventos registados</span><strong id="readingCount">0</strong></article>
                <article class="summary-card"><span class="helper">Intervencoes demo</span><strong id="interventionCount">0</strong></article>
                <article class="summary-card"><span class="helper">Impacto rastreado</span><strong id="totalTechnicalImpact">0.0 kWh</strong></article>
                <article class="summary-card"><span class="helper">Hash demo</span><strong id="latestHash">-</strong></article>
            </div>
            <div style="margin-top:1rem"><div class="helper" style="margin-bottom:.6rem">Ultima intervencao auditada</div><article class="certificate" id="latestInterventionCard"><span class="helper">Ainda nao existe registo</span><strong>Sem intervencao</strong><p>Regista o primeiro evento para gerar a auditoria demo desta turbina.</p></article></div>
        </aside>
    </div>
    <div class="container board" style="margin-top:1.4rem">
        <section class="panel">
            <div class="head"><div><div class="helper">Historico tecnico</div><h2>Eventos registados</h2></div><span class="badge wait">Janela 10 min</span></div>
            <div class="list" id="readingList"><div class="empty">Sem eventos registados nesta sessao de demo.</div></div>
        </section>
        <section class="panel">
            <div class="head"><div><div class="helper">Timeline visual</div><h2>Processo Quantum</h2></div><span class="badge ok">Fluxo completo</span></div>
            <div class="list" id="timelineList">
                <article class="timeline"><div><strong>1. Preparar evento do intervalo</strong><span>O operador ou dispositivo define o impacto tecnico do periodo demo.</span></div></article>
                <article class="timeline"><div><strong>2. Registar no Quantum</strong><span>O clique em registar simula o envio do pacote tecnico da turbina para a plataforma.</span></div></article>
                <article class="timeline"><div><strong>3. Validar e auditar</strong><span>O modal apresenta a validacao, registo do evento e auditoria demo.</span></div></article>
            </div>
        </section>
    </div></section>
</main>

<div class="modal" id="processModal" aria-hidden="true"><section class="modal-panel" role="dialog" aria-modal="true" aria-labelledby="processTitle">
    <div class="modal-header"><div><div class="helper">Processo visivel ao cliente</div><h2 id="processTitle">Registo do evento em curso</h2></div><button class="close" type="button" id="closeModal" aria-label="Fechar modal">X</button></div>
    <div class="progress"><div class="bar" id="progressBar"></div></div>
    <div class="modal-stages" id="stageList"></div>
    <div style="margin-top:1rem"><div class="helper" style="margin-bottom:.65rem">Log tecnico demo</div><div class="list" id="logList"></div></div>
    <div class="modal-footer" style="margin-top:1rem"><p id="modalSummary">A preparar a simulacao do envio.</p><button class="btn btn-secondary" type="button" id="modalActionButton" disabled>A processar...</button></div>
</section></div>

<script>
const demoConfig = <?= json_encode($demoState ?? [], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) ?>;
(() => {
    const state = { currentStart:new Date(demoConfig.current_start || '2026-03-25T09:00:00'), intervalMinutes:10, totalMeterKwh:Number(demoConfig.total_meter_kwh || 48231.7), readingCount:Number(demoConfig.reading_count || 0), interventionCount:Number(demoConfig.intervention_count || 0), totalTechnicalImpact:Number(demoConfig.total_technical_impact || 0), communicationIndex:Number(demoConfig.next_sequence || 1), readings:[], interventions:[], isProcessing:false };
    const el = {
        menuToggle:document.getElementById('menuToggle'), mobileMenu:document.getElementById('mobileMenu'),
        meterDisplay:document.getElementById('meterDisplay'), readingRange:document.getElementById('readingRange'), readingValue:document.getElementById('readingValue'), sourceReference:document.getElementById('sourceReference'),
        powerValue:document.getElementById('powerValue'), currentIntervalLabel:document.getElementById('currentIntervalLabel'), estimatedCertificateEnergy:document.getElementById('estimatedCertificateEnergy'),
        nextIntervalLabel:document.getElementById('nextIntervalLabel'), lastCommunicationLabel:document.getElementById('lastCommunicationLabel'), readingCount:document.getElementById('readingCount'),
        interventionCount:document.getElementById('interventionCount'), totalTechnicalImpact:document.getElementById('totalTechnicalImpact'), latestHash:document.getElementById('latestHash'),
        latestInterventionCard:document.getElementById('latestInterventionCard'), readingList:document.getElementById('readingList'), timelineList:document.getElementById('timelineList'),
        statusBadge:document.getElementById('statusBadge'), communicateButton:document.getElementById('communicateButton'), heroCommunicate:document.getElementById('heroCommunicate'),
        processModal:document.getElementById('processModal'), closeModal:document.getElementById('closeModal'), progressBar:document.getElementById('progressBar'), stageList:document.getElementById('stageList'),
        logList:document.getElementById('logList'), modalSummary:document.getElementById('modalSummary'), modalActionButton:document.getElementById('modalActionButton')
    };
    const themeKey = 'quantum-public-theme';
    const themeButtons = document.querySelectorAll('[data-theme-toggle]');
    const applyTheme = (theme) => {
        document.documentElement.setAttribute('data-theme', theme);
        themeButtons.forEach((button) => {
            button.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
            button.setAttribute('aria-label', theme === 'light' ? 'Ativar modo escuro' : 'Ativar modo claro');
            button.setAttribute('title', theme === 'light' ? 'Ativar modo escuro' : 'Ativar modo claro');
        });
    };
    applyTheme(document.documentElement.getAttribute('data-theme') || 'light');
    themeButtons.forEach((button) => {
        button.addEventListener('click', () => {
            const nextTheme = (document.documentElement.getAttribute('data-theme') || 'light') === 'light' ? 'dark' : 'light';
            applyTheme(nextTheme);
            try {
                localStorage.setItem(themeKey, nextTheme);
            } catch (error) {
                // Ignore storage restrictions and keep the active theme.
            }
        });
    });
    const stageTemplates = [
        { key:'connect', title:'Ligacao a turbina', body:'A operacao demo abre a ligacao segura e prepara o pacote tecnico.' },
        { key:'validate', title:'Validacao do intervalo', body:'O evento e associado ao periodo de 10 minutos seguinte disponivel.' },
        { key:'insert', title:'Registo do evento', body:'A ocorrencia entra como evento validado para a turbina demo.' },
        { key:'certify', title:'Auditoria blockchain', body:'A plataforma compoe o registo, hash e referencia publica demo.' }
    ];
    const fmtNum = (value,d=1) => new Intl.NumberFormat('pt-PT',{minimumFractionDigits:d,maximumFractionDigits:d}).format(value);
    const fmtTime = (date) => new Intl.DateTimeFormat('pt-PT',{hour:'2-digit',minute:'2-digit'}).format(date);
    const fmtDateTime = (date) => new Intl.DateTimeFormat('pt-PT',{day:'2-digit',month:'short',year:'numeric',hour:'2-digit',minute:'2-digit'}).format(date);
    const wait = (ms) => new Promise((resolve) => window.setTimeout(resolve, ms));
    const meterDigits = (value) => Math.round(value * 10).toString().padStart(7,'0').slice(-7).split('');
    const renderMeter = () => { el.meterDisplay.innerHTML = ''; meterDigits(state.totalMeterKwh).forEach((digit) => { const node = document.createElement('div'); node.className = 'digit'; node.textContent = digit; el.meterDisplay.appendChild(node); }); };
    const updateInterval = () => { const start = new Date(state.currentStart); const end = new Date(start.getTime() + state.intervalMinutes * 60000); el.currentIntervalLabel.textContent = `${fmtDateTime(start)} - ${fmtTime(end)}`; el.nextIntervalLabel.textContent = fmtTime(end); };
    const syncReading = (source = 'range') => { const raw = Number(source === 'range' ? el.readingRange.value : el.readingValue.value) || 0; const value = Math.max(0, Number(raw.toFixed(1))); el.readingRange.value = value; el.readingValue.value = value.toFixed(1); el.estimatedCertificateEnergy.textContent = `${fmtNum(value)} kWh`; el.powerValue.textContent = `${fmtNum(value * 6)} kW`; };
    const normalizeReading = (reading) => ({ reference:reading.source_reference, intervalLabel:`${fmtDateTime(new Date(reading.interval_start))} - ${fmtTime(new Date(reading.interval_end))}`, energy:Number(reading.value_kwh || reading.energy_kwh || 0) });
    const normalizeIntervention = (intervention) => ({ publicId:intervention.public_id, intervalLabel:`${fmtDateTime(new Date(intervention.period_start))} - ${fmtTime(new Date(intervention.period_end))}`, energy:Number(intervention.energy_kwh || 0), hash:String(intervention.record_hash || '-') });
    const renderReadings = () => { if (state.readings.length === 0) { el.readingList.innerHTML = '<div class="empty">Sem eventos registados nesta sessao de demo.</div>'; return; } el.readingList.innerHTML = ''; state.readings.forEach((reading) => { const item = document.createElement('article'); item.className = 'reading'; item.innerHTML = `<div><strong>${reading.reference}</strong><span>${reading.intervalLabel}</span></div><div style="text-align:right"><strong>${fmtNum(reading.energy)} kWh</strong><span>Estado: validado</span></div>`; el.readingList.appendChild(item); }); };
    const renderTimeline = (entry) => { if (!entry) return; const item = document.createElement('article'); item.className = 'timeline'; item.innerHTML = `<div><strong>${entry.title}</strong><span>${entry.body}</span></div>`; el.timelineList.prepend(item); while (el.timelineList.children.length > 6) el.timelineList.removeChild(el.timelineList.lastElementChild); };
    const renderSummary = () => { el.readingCount.textContent = String(state.readingCount); el.interventionCount.textContent = String(state.interventionCount); el.totalTechnicalImpact.textContent = `${fmtNum(state.totalTechnicalImpact)} kWh`; const latest = state.interventions[state.interventions.length - 1]; if (!latest) { el.latestHash.textContent = '-'; return; } el.latestHash.textContent = latest.hash.slice(0,8).toUpperCase(); el.latestInterventionCard.innerHTML = `<span class="helper">${latest.publicId}</span><strong>${fmtNum(latest.energy)} kWh auditados</strong><p>Periodo ${latest.intervalLabel}. Hash demo ${latest.hash}.</p>`; };
    const resetModal = () => { el.stageList.innerHTML = ''; el.logList.innerHTML = ''; el.progressBar.style.width = '0%'; el.modalSummary.textContent = 'A preparar a simulacao do registo.'; el.modalActionButton.textContent = 'A processar...'; el.modalActionButton.disabled = true; stageTemplates.forEach((stage) => { const article = document.createElement('article'); article.className = 'stage'; article.dataset.stage = stage.key; article.innerHTML = `<div class="row"><div><strong>${stage.title}</strong><p>${stage.body}</p></div><span class="badge wait">Pendente</span></div>`; el.stageList.appendChild(article); }); };
    const setStage = (key,status,label) => { const article = el.stageList.querySelector(`[data-stage="${key}"]`); if (!article) return; article.classList.remove('active','done'); if (status === 'active') article.classList.add('active'); if (status === 'done') article.classList.add('done'); const badge = article.querySelector('.badge'); if (badge) { badge.className = `badge ${status === 'done' ? 'ok' : 'wait'}`; badge.textContent = label; } };
    const appendLog = (title, detail) => { const item = document.createElement('article'); item.className = 'log'; item.innerHTML = `<div><strong>${title}</strong><span>${detail}</span></div><span>${new Intl.DateTimeFormat('pt-PT',{hour:'2-digit',minute:'2-digit',second:'2-digit'}).format(new Date())}</span>`; el.logList.appendChild(item); };
    const openModal = () => { el.processModal.classList.add('open'); el.processModal.setAttribute('aria-hidden','false'); };
    const closeModal = () => { if (state.isProcessing) return; el.processModal.classList.remove('open'); el.processModal.setAttribute('aria-hidden','true'); };
    const payload = () => { const energy = Number(el.readingValue.value) || 0; const start = new Date(state.currentStart); const end = new Date(start.getTime() + state.intervalMinutes * 60000); const idx = String(state.communicationIndex).padStart(4,'0'); const reference = el.sourceReference.value.trim() || `EVT-DEMO-${idx}`; return { energy:Number(energy.toFixed(1)), start, end, reference, intervalLabel:`${fmtDateTime(start)} - ${fmtTime(end)}` }; };
    const busy = (value) => { state.isProcessing = value; el.communicateButton.disabled = value; el.heroCommunicate.disabled = value; el.communicateButton.textContent = value ? 'A registar...' : 'Registar evento'; el.heroCommunicate.textContent = value ? 'A registar...' : 'Registar agora'; el.statusBadge.className = `badge ${value ? 'wait' : 'ok'}`; el.statusBadge.textContent = value ? 'Em processamento' : 'Pronto'; };
    const applyServerState = (serverState) => {
        state.currentStart = new Date(serverState.current_start);
        state.totalMeterKwh = Number(serverState.total_meter_kwh || state.totalMeterKwh);
        state.readingCount = Number(serverState.reading_count || 0);
        state.interventionCount = Number(serverState.intervention_count || 0);
        state.totalTechnicalImpact = Number(serverState.total_technical_impact || 0);
        state.communicationIndex = Number(serverState.next_sequence || state.communicationIndex);
        state.readings = (serverState.latest_readings || []).map(normalizeReading).reverse();
        state.interventions = (serverState.latest_interventions || []).map(normalizeIntervention).reverse();
        el.sourceReference.value = serverState.next_source_reference || `EVT-DEMO-${String(state.communicationIndex).padStart(4,'0')}`;
        el.lastCommunicationLabel.textContent = serverState.last_communication_at ? fmtTime(new Date(serverState.last_communication_at)) : 'Ainda sem envio';
        renderMeter(); updateInterval(); renderReadings(); renderSummary();
    };
    const runSimulation = async () => {
        if (state.isProcessing) return;
        const data = payload(); resetModal(); openModal(); busy(true);
        const steps = [
            { key:'connect', summary:'Ligacao estabelecida com a turbina demo.', title:'Canal seguro aberto', detail:`Turbine QN-WT-2026 ligada para o pacote ${data.reference}.` },
            { key:'validate', summary:'Intervalo de 10 minutos validado.', title:'Intervalo validado', detail:`Janela ${data.intervalLabel} pronta para registo com ${fmtNum(data.energy)} kWh.` },
            { key:'insert', summary:'Evento inserido com sucesso.', title:'Evento criado', detail:`Evento validado com source_reference ${data.reference}.` },
            { key:'certify', summary:'Auditoria blockchain em curso na empresa demo.', title:'Auditoria em curso', detail:'A plataforma vai gravar a auditoria no tenant demo.' }
        ];
        el.modalSummary.textContent = `A registar ${fmtNum(data.energy)} kWh para ${data.intervalLabel}.`;
        for (let i = 0; i < steps.length; i += 1) { const step = steps[i]; setStage(step.key,'active','Em curso'); appendLog(step.title, step.detail); el.progressBar.style.width = `${((i + 1) / steps.length) * 100}%`; el.modalSummary.textContent = step.summary; await wait(700); setStage(step.key,'done','Concluido'); }
        try {
            const response = await fetch('/demo/meter/communicate', {
                method:'POST',
                headers:{'Content-Type':'application/json','Accept':'application/json'},
                body:JSON.stringify({ energy_kwh:data.energy, source_reference:data.reference })
            });
            const result = await response.json();
            if (!response.ok || !result.ok) {
                throw new Error(result.message || 'Falha ao gravar o registo demo.');
            }

            applyServerState(result.state || {});
            appendLog('Auditoria gerada', `Auditoria ${result.result.public_id} gravada na empresa demo com referencia ${result.result.reference_code}.`);
            renderTimeline({ title:`Evento ${result.result.source_reference} auditado`, body:`${fmtNum(result.result.energy_kwh)} kWh registados e rastreados no backoffice demo.` });
            el.modalSummary.textContent = `Evento registado com sucesso. Auditoria ${result.result.public_id} gerada na empresa demo.`;
            el.modalActionButton.textContent = 'Fechar';
            el.modalActionButton.disabled = false;
        } catch (error) {
            el.modalSummary.textContent = error.message;
            el.modalActionButton.textContent = 'Fechar';
            el.modalActionButton.disabled = false;
        } finally {
            busy(false);
            syncReading('input');
        }
    };
    el.readingRange.addEventListener('input', () => syncReading('range'));
    el.readingValue.addEventListener('input', () => syncReading('input'));
    el.communicateButton.addEventListener('click', runSimulation);
    el.heroCommunicate.addEventListener('click', () => { el.readingValue.scrollIntoView({ behavior:'smooth', block:'center' }); runSimulation(); });
    if (el.menuToggle && el.mobileMenu) {
        el.menuToggle.addEventListener('click', () => {
            const isOpen = el.mobileMenu.classList.toggle('open');
            el.menuToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false');
        });
        el.mobileMenu.querySelectorAll('a').forEach((link) => {
            link.addEventListener('click', () => {
                el.mobileMenu.classList.remove('open');
                el.menuToggle.setAttribute('aria-expanded', 'false');
            });
        });
    }
    el.closeModal.addEventListener('click', closeModal); el.modalActionButton.addEventListener('click', closeModal); el.processModal.addEventListener('click', (event) => { if (event.target === el.processModal) closeModal(); }); document.addEventListener('keydown', (event) => { if (event.key === 'Escape') closeModal(); });
    applyServerState(demoConfig); syncReading('input');
})();
</script>
</body>
</html>
