File size: 7,108 Bytes
78cc96f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>HearthNet — Browser Agent + Mesh</title>
    <style>
      :root {
        --bg:#0b1020; --card:#111827; --line:#334155; --fg:#eef2ff; --muted:#94a3b8;
        --accent:#6366f1; --accent-soft:#1e1b4b; --ok:#34d399; --warn:#fbbf24; --err:#f87171;
      }
      * { box-sizing:border-box; }
      body { margin:0; font-family:system-ui,-apple-system,Segoe UI,sans-serif; background:var(--bg); color:var(--fg); }
      a { color:#a5b4fc; }
      .shell { max-width:1400px; margin:0 auto; padding:16px; }
      header { display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
      header h1 { font-size:18px; margin:0; font-weight:600; }
      header .spacer { flex:1; }
      select, input, button { font-family:inherit; font-size:14px; }
      select, input { background:var(--card); color:var(--fg); border:1px solid var(--line); border-radius:8px; padding:8px 10px; }
      button { background:#1f2937; color:var(--fg); border:1px solid var(--line); border-radius:8px; padding:8px 14px; cursor:pointer; }
      button:hover:not(:disabled) { border-color:var(--accent); }
      button.primary { background:var(--accent); border-color:var(--accent); color:#fff; }
      button:disabled { opacity:.5; cursor:not-allowed; }
      #model-progress { font-size:12px; color:var(--muted); }
      #model-progress.ok { color:var(--ok); } #model-progress.warn { color:var(--warn); }
      .tabs { display:flex; gap:6px; margin-bottom:12px; flex-wrap:wrap; }
      .tab { padding:8px 14px; border-radius:10px; background:var(--card); border:1px solid var(--line); cursor:pointer; }
      .tab.active { background:var(--accent-soft); border-color:var(--accent); }
      .pane { display:none; }
      .pane.active { display:block; }
      .panel { border:1px solid var(--line); background:var(--card); border-radius:14px; padding:14px; margin-bottom:12px; }
      .panel-title { font-weight:700; margin-bottom:10px; color:#a5b4fc; }
      .muted { color:var(--muted); }
      .mono { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }
      pre { white-space:pre-wrap; word-break:break-word; margin:0; }
      .pill { display:inline-block; padding:2px 8px; border-radius:10px; font-size:12px; background:var(--accent-soft); color:#c7d2fe; }
      .pill.ok { background:#064e3b; color:var(--ok); } .pill.warn { background:#451a03; color:var(--warn); } .pill.err { background:#450a0a; color:var(--err); }
      .row { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
      .row input { flex:1; min-width:120px; }
      /* agent */
      .agent-top { display:flex; gap:8px; margin-bottom:12px; }
      .agent-top input { flex:1; }
      .agent-grid { display:grid; grid-template-columns:1fr 320px; gap:12px; }
      .agent-main, .agent-side .panel { min-height:60vh; }
      .agent-main { border:1px solid var(--line); background:var(--card); border-radius:14px; padding:14px; }
      /* news */
      .news-ticker { overflow:hidden; white-space:nowrap; border:1px solid var(--line); background:var(--card); border-radius:10px; padding:8px 0; margin-bottom:12px; }
      .news-ticker-track { display:inline-block; padding-left:100%; animation:scroll 60s linear infinite; }
      .news-ticker-track:hover { animation-play-state:paused; }
      @keyframes scroll { to { transform:translateX(-100%); } }
      .tick { padding:0 14px; } .tick-sep { color:var(--muted); }
      .news-grid { display:grid; grid-template-columns:1fr 340px; gap:12px; }
      .news-item { padding:10px 0; border-bottom:1px solid var(--line); }
      .news-item a { font-weight:600; text-decoration:none; }
      .news-meta { font-size:12px; color:var(--muted); margin:2px 0; }
      .news-sum { font-size:13px; color:#cbd5e1; }
      .signal { padding:6px 0; border-bottom:1px solid var(--line); }
      .signal.on { } .signal-hits { font-size:11px; color:var(--muted); margin-top:4px; }
      .alert-row, .peer-row { padding:6px 0; border-bottom:1px solid var(--line); font-size:13px; }
      /* mesh */
      .mesh-grid { display:grid; grid-template-columns:240px 1fr; gap:12px; }
      .mesh-chat { height:300px; overflow:auto; border:1px solid var(--line); border-radius:8px; padding:8px; background:#0f1729; font-size:13px; }
      .msg { padding:2px 0; } .msg.self b { color:var(--ok); } .msg.sys { color:var(--muted); font-style:italic; }
      /* easter-egg live ticker (press "e") */
      .egg-ticker { position:fixed; left:0; right:0; bottom:0; z-index:9999; display:flex; align-items:center;
        background:linear-gradient(90deg,#111827,#1e1b4b); border-top:2px solid var(--accent);
        box-shadow:0 -8px 24px rgba(0,0,0,.5); overflow:hidden; transform:translateY(0); transition:transform .25s ease; }
      .egg-ticker.hidden { transform:translateY(110%); }
      .egg-label { flex:0 0 auto; padding:8px 14px; font-weight:800; font-size:12px; letter-spacing:.08em;
        color:#fff; background:var(--accent); }
      .egg-ticker-track { white-space:nowrap; padding:8px 0; animation:scroll 50s linear infinite; }
      .egg-ticker:hover .egg-ticker-track { animation-play-state:paused; }
      .etk { padding:0 16px; } .etk b { color:#a5b4fc; } .esep { color:var(--muted); }
      @media (max-width:900px) { .agent-grid,.news-grid,.mesh-grid { grid-template-columns:1fr; } }
    </style>
  </head>
  <body>
    <div class="shell">
      <header>
        <h1>🔥 HearthNet</h1>
        <span class="muted">browser-local agent · news · WebRTC mesh</span>
        <span class="spacer"></span>
        <span class="muted" style="opacity:.55;font-size:11px">press <kbd>e</kbd> for live ticker</span>
        <label class="muted">Model</label>
        <select id="model"></select>
        <span id="model-progress">select a model — it loads on first chat</span>
      </header>

      <div class="tabs">
        <div class="tab active" data-tab="agent">Agent</div>
        <div class="tab" data-tab="news">News</div>
        <div class="tab" data-tab="mesh">Mesh</div>
      </div>

      <div id="pane-agent" class="pane active"></div>
      <div id="pane-news" class="pane"></div>
      <div id="pane-mesh" class="pane">
        <div class="row" style="margin-bottom:12px">
          <button id="share-signals">Share active signals to mesh</button>
          <span class="muted">broadcasts News-tab signals to all connected browsers</span>
        </div>
        <div id="mesh-mount"></div>
      </div>
    </div>

    <!-- easter egg: press "e" to toggle a global live news ticker -->
    <div id="egg-ticker" class="egg-ticker hidden">
      <span class="egg-label">⚡ LIVE</span>
      <div class="egg-ticker-track" id="egg-track">press “e” again to hide…</div>
    </div>

    <!-- PeerJS (WebRTC signaling broker) — JavaScript only, no server of ours -->
    <script src="https://unpkg.com/peerjs@1.5.4/dist/peerjs.min.js"></script>
    <script type="module" src="./index.js"></script>
  </body>
</html>