Skip to content

Commit 3f1af4c

Browse files
authored
Update index.html
1 parent 15550f7 commit 3f1af4c

1 file changed

Lines changed: 121 additions & 50 deletions

File tree

certify/seal/index.html

Lines changed: 121 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,19 @@
9292
.tt-cell{background:var(--bg2);padding:14px 18px;}
9393
.tt-sys{font-size:0.62rem;letter-spacing:0.15em;color:var(--gold-dim);text-transform:uppercase;margin-bottom:5px;}
9494
.tt-val{font-size:0.85rem;color:var(--gold);min-height:22px;}
95+
.json-key{color:var(--gold-dim);}
96+
.json-str{color:rgba(61,220,132,0.9);}
97+
.json-num{color:var(--frozen);}
98+
.json-bool{color:var(--warn);}
99+
.ledger-entry{background:var(--bg2);border:1px solid var(--border2);border-radius:3px;padding:16px 18px;margin-bottom:10px;}
100+
.le-header{display:flex;align-items:center;gap:10px;margin-bottom:8px;flex-wrap:wrap;}
101+
.le-id{font-family:var(--mono);font-size:0.72rem;color:var(--gold);}
102+
.le-template{font-size:0.6rem;padding:2px 8px;border-radius:2px;border:1px solid var(--border);color:var(--gold-dim);}
103+
.le-content{font-size:0.78rem;color:var(--text-dim);margin-bottom:8px;}
104+
.le-hash{font-size:0.62rem;color:var(--text-faint);font-family:var(--mono);word-break:break-all;}
105+
.le-github-link{font-size:0.62rem;color:var(--frozen);text-decoration:none;display:inline-block;margin:8px 0;}
106+
.le-btn{font-family:var(--mono);font-size:0.6rem;padding:5px 10px;border:1px solid var(--border2);background:none;color:var(--text-faint);cursor:pointer;border-radius:2px;}
107+
.ledger-empty{padding:48px;text-align:center;color:var(--text-faint);font-family:var(--serif);font-style:italic;}
95108
@media(max-width:760px){.seal-grid{grid-template-columns:1fr !important;}}
96109
</style>
97110
</head>
@@ -139,7 +152,7 @@
139152
<div class="panel-title">01 — TEMPLATE SELECTION</div>
140153
<div class="field-group">
141154
<div class="field-label">Template <span class="req">*</span></div>
142-
<select class="select-input" id="seal-template" onchange="onTemplateChange()">
155+
<select class="select-input" id="seal-template" onchange="updateSealButton()">
143156
<option value="">— select template —</option>
144157
<option value="01">01 — AI Failure</option>
145158
<option value="02">02 — Research Priority</option>
@@ -225,7 +238,7 @@
225238
</div>
226239
</div>
227240

228-
<!-- VERIFY TAB (simplified) -->
241+
<!-- VERIFY TAB -->
229242
<div id="tab-verify" class="tab-panel">
230243
<div class="panel">
231244
<div class="panel-title">VERIFY A SEAL</div>
@@ -240,7 +253,7 @@
240253

241254
<!-- LEDGER TAB -->
242255
<div id="tab-ledger" class="tab-panel">
243-
<div class="ledger-stats" style="display:flex;gap:16px;margin-bottom:20px;">
256+
<div style="display:flex;gap:16px;margin-bottom:20px;align-items:center;">
244257
<span>Session entries: <strong id="ledger-count">0</strong></span>
245258
<button class="action-btn" onclick="clearLedger()" style="font-size:0.62rem;">Clear Session</button>
246259
</div>
@@ -249,48 +262,110 @@
249262

250263
<!-- ABOUT TAB -->
251264
<div id="tab-about" class="tab-panel">
252-
<div class="about-section">
253-
<div class="panel">
254-
<div class="panel-title">FROZEN-2.0 — SOVEREIGN TRACE PROTOCOL</div>
255-
<p style="font-size:0.8rem;line-height:1.6;font-family:var(--serif);">SHA-256 triple-time seal. Browser-native SubtleCrypto. Backend creates GitHub issue + ledger file automatically. No GitHub account required.</p>
256-
</div>
265+
<div class="panel">
266+
<div class="panel-title">FROZEN-2.0 — SOVEREIGN TRACE PROTOCOL</div>
267+
<p style="font-size:0.8rem;line-height:1.6;font-family:var(--serif);">SHA-256 triple-time seal. Browser-native SubtleCrypto. Backend creates GitHub issue + ledger file automatically. No GitHub account required.</p>
257268
</div>
258269
</div>
259270

260271
</div>
261272

262273
<script>
263274
// ============================================================
264-
// STP SEAL TOOL v3.0 – Backend-Connected Version
265-
// Calls /api/stp-seal on your Vercel backend
275+
// STP SEAL TOOL v3.0 – Full Calendar + Backend Integration
266276
// ============================================================
267277

268-
const BACKEND_URL = '/api/stp-seal'; // Your existing endpoint
278+
const BACKEND_URL = '/api/stp-seal';
269279

270280
let CURRENT_ENTRY = null;
271281
let sessionLedger = [];
272282

273-
// Calendar helpers (local for live time display)
283+
// ========== FULL CALENDAR FUNCTIONS (Local) ==========
274284
const GREGORIAN_MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
275285
const MOON_NAMES = ['Magnetic','Lunar','Electric','Self-Existing','Overtone','Rhythmic','Resonant','Galactic','Solar','Planetary','Spectral','Crystal','Cosmic'];
276286

277-
function gregorianString(d) { return `${GREGORIAN_MONTHS[d.getUTCMonth()]} ${d.getUTCDate()}, ${d.getUTCFullYear()}`; }
278-
function dreamspellString(d) {
279-
const month = d.getUTCMonth() + 1, day = d.getUTCDate(), year = d.getUTCFullYear();
287+
// Hebrew calendar constants
288+
const HEBREW_EPOCH_JD = 347998;
289+
const COMMON_MONTHS = ['Tishri','Cheshvan','Kislev','Tevet','Shevat','Adar','Nisan','Iyar','Sivan','Tammuz','Av','Elul'];
290+
const LEAP_MONTHS = ['Tishri','Cheshvan','Kislev','Tevet','Shevat','Adar I','Adar II','Nisan','Iyar','Sivan','Tammuz','Av','Elul'];
291+
292+
function jdFromGregorian(year, month, day) {
293+
const a = Math.floor((14 - month) / 12);
294+
const y = year + 4800 - a;
295+
const m = month + 12 * a - 3;
296+
return day + Math.floor((153 * m + 2) / 5) + 365 * y + Math.floor(y / 4) - Math.floor(y / 100) + Math.floor(y / 400) - 32045;
297+
}
298+
299+
function isHebrewLeap(year) { return (7 * year + 1) % 19 < 7; }
300+
301+
function elapsedDays(year) {
302+
const months = Math.floor((235 * year - 234) / 19);
303+
const parts = 12084 + 13753 * months;
304+
let day = months * 29 + Math.floor(parts / 25920);
305+
if ((3 * (day + 1)) % 7 < 3) day++;
306+
return day;
307+
}
308+
309+
function newYearDelay(year) {
310+
const ny0 = elapsedDays(year - 1);
311+
const ny1 = elapsedDays(year);
312+
const ny2 = elapsedDays(year + 1);
313+
if (ny2 - ny1 === 356) return 2;
314+
if (ny1 - ny0 === 382) return 1;
315+
return 0;
316+
}
317+
318+
function tishri1JD(year) { return elapsedDays(year) + newYearDelay(year) + HEBREW_EPOCH_JD; }
319+
320+
function monthLengths(year) {
321+
const ylen = tishri1JD(year + 1) - tishri1JD(year);
322+
const leap = isHebrewLeap(year);
323+
const months = [30, (ylen % 10 === 5) ? 30 : 29, (ylen % 10 === 3) ? 29 : 30, 29, 30, leap ? 30 : 29];
324+
if (leap) months.push(29);
325+
months.push(30, 29, 30, 29, 30, 29);
326+
return months;
327+
}
328+
329+
function gregorianToHebrew(year, month, day) {
330+
const jd = jdFromGregorian(year, month, day);
331+
let hy = Math.floor((jd - HEBREW_EPOCH_JD) * 19 / 6935) + 1;
332+
while (tishri1JD(hy + 1) <= jd) hy++;
333+
while (tishri1JD(hy) > jd) hy--;
334+
const mLens = monthLengths(hy);
335+
const mNames = isHebrewLeap(hy) ? LEAP_MONTHS : COMMON_MONTHS;
336+
let remaining = jd - tishri1JD(hy);
337+
for (let i = 0; i < mLens.length; i++) {
338+
if (remaining < mLens[i]) return { year: hy, month: mNames[i], day: remaining + 1 };
339+
remaining -= mLens[i];
340+
}
341+
return { year: hy, month: 'Tishri', day: 1 };
342+
}
343+
344+
function hebrewString(year, month, day) {
345+
const h = gregorianToHebrew(year, month, day);
346+
return `${h.day} ${h.month} ${h.year}`;
347+
}
348+
349+
function dreamspellString(year, month, day) {
280350
if (month === 7 && day === 25) return 'Day Out of Time';
281-
const yearStart = (month > 7 || (month === 7 && day >= 26)) ? Date.UTC(year, 6, 26) : Date.UTC(year - 1, 6, 26);
282-
const delta = Math.floor((d.getTime() - yearStart) / 86400000);
351+
const yearStart = (month > 7 || (month === 7 && day >= 26)) ? new Date(Date.UTC(year, 6, 26)) : new Date(Date.UTC(year - 1, 6, 26));
352+
const cur = new Date(Date.UTC(year, month - 1, day));
353+
const delta = Math.floor((cur - yearStart) / 86400000);
283354
if (delta < 0 || delta >= 364) return 'Day Out of Time';
284355
const moon = Math.floor(delta / 28) + 1;
285356
return `Day ${(delta % 28) + 1}, ${MOON_NAMES[moon - 1]} Moon ${moon}/13`;
286357
}
287-
function hebrewString(d) { return `${d.getUTCMonth()+1}/${d.getUTCDate()}/${d.getUTCFullYear()} (API) – full Hebrew via backend`; }
358+
359+
function gregorianStringFull(year, month, day) {
360+
return `${GREGORIAN_MONTHS[month - 1]} ${day}, ${year}`;
361+
}
288362

289363
function updateLiveTime() {
290364
const now = new Date();
291-
document.getElementById('live-gregorian').textContent = gregorianString(now);
292-
document.getElementById('live-dreamspell').textContent = dreamspellString(now);
293-
document.getElementById('live-hebrew').textContent = `${now.getUTCMonth()+1}/${now.getUTCDate()}/${now.getUTCFullYear()}`;
365+
const y = now.getUTCFullYear(), m = now.getUTCMonth() + 1, d = now.getUTCDate();
366+
document.getElementById('live-gregorian').textContent = gregorianStringFull(y, m, d);
367+
document.getElementById('live-dreamspell').textContent = dreamspellString(y, m, d);
368+
document.getElementById('live-hebrew').textContent = hebrewString(y, m, d);
294369
}
295370
setInterval(updateLiveTime, 1000);
296371
updateLiveTime();
@@ -303,24 +378,23 @@
303378
document.getElementById('char-count').textContent = `${document.getElementById('seal-content').value.length} characters`;
304379
}
305380

306-
function onTemplateChange() { updateSealButton(); }
307-
308381
async function generateSeal() {
309382
const template = document.getElementById('seal-template').value;
310383
const content = document.getElementById('seal-content').value.trim();
311384
const author = document.getElementById('seal-author').value.trim();
312-
const declaration = document.getElementById('seal-declaration').checked;
313385

314-
if (!template || !content || !declaration) return;
386+
if (!template || !content) return;
315387

316388
const btn = document.getElementById('seal-btn');
317389
btn.disabled = true;
318390
btn.textContent = '⟳ SEALING…';
319391
document.getElementById('seal-error').classList.remove('active');
320392
document.getElementById('seal-placeholder').style.display = 'none';
321393
document.getElementById('seal-result').classList.add('active');
322-
document.getElementById('ledger-status-card').className = 'ledger-status-card pending';
323-
document.getElementById('ledger-status-card').innerHTML = '<div class="lsc-icon">⟳</div><div class="lsc-body"><div class="lsc-label">Creating Ledger Entry…</div><div class="lsc-sub">Contacting backend</div></div>';
394+
395+
const statusCard = document.getElementById('ledger-status-card');
396+
statusCard.className = 'ledger-status-card pending';
397+
statusCard.innerHTML = '<div class="lsc-icon">⟳</div><div class="lsc-body"><div class="lsc-label">Creating Ledger Entry…</div><div class="lsc-sub">Contacting backend</div></div>';
324398

325399
try {
326400
const response = await fetch(BACKEND_URL, {
@@ -335,20 +409,21 @@
335409
throw new Error(data.error || data.message || 'Backend error');
336410
}
337411

338-
// Backend returned successful seal with GitHub issue URL
339412
const now = new Date();
413+
const y = now.getUTCFullYear(), m = now.getUTCMonth() + 1, d = now.getUTCDate();
414+
340415
CURRENT_ENTRY = {
341-
ledger_id: `STP-${data.template_name || template}-${gregorianString(now).replace(/[,\s]+/g, '-')}-${data.seal.substring(0,6).toUpperCase()}`,
416+
ledger_id: `STP-${data.template_name || template}-${gregorianStringFull(y, m, d).replace(/[,\s]+/g, '-')}-${data.seal.substring(0,6).toUpperCase()}`,
342417
template: template,
343418
template_name: data.template_name,
344419
content: content,
345420
author: author || null,
346421
content_hash: `sha256:${data.seal}`,
347422
seal: {
348-
gregorian: data.gregorian,
349-
hebrew: data.hebrew,
350-
dreamspell: data.dreamspell,
351-
unix_utc: data.unix_utc,
423+
gregorian: data.gregorian || gregorianStringFull(y, m, d),
424+
hebrew: data.hebrew || hebrewString(y, m, d),
425+
dreamspell: data.dreamspell || dreamspellString(y, m, d),
426+
unix_utc: data.unix_utc || Math.floor(now.getTime() / 1000),
352427
seal_method: 'SHA-256-SubtleCrypto-FROZEN-2.0'
353428
},
354429
github_issue_url: data.issue_url || null,
@@ -357,16 +432,13 @@
357432
sealed_at: now.toISOString()
358433
};
359434

360-
// Update display
361435
document.getElementById('result-ledger-id').textContent = CURRENT_ENTRY.ledger_id;
362-
document.getElementById('result-gregorian').textContent = data.gregorian;
363-
document.getElementById('result-hebrew').textContent = data.hebrew;
364-
document.getElementById('result-dreamspell').textContent = data.dreamspell;
436+
document.getElementById('result-gregorian').textContent = CURRENT_ENTRY.seal.gregorian;
437+
document.getElementById('result-hebrew').textContent = CURRENT_ENTRY.seal.hebrew;
438+
document.getElementById('result-dreamspell').textContent = CURRENT_ENTRY.seal.dreamspell;
365439
document.getElementById('result-hash-display').textContent = data.seal;
366440
document.getElementById('result-json').innerHTML = syntaxHighlight(JSON.stringify(CURRENT_ENTRY, null, 2));
367441

368-
// Update ledger status
369-
const statusCard = document.getElementById('ledger-status-card');
370442
if (data.issue_url) {
371443
statusCard.className = 'ledger-status-card';
372444
statusCard.innerHTML = `<div class="lsc-icon">✓</div><div class="lsc-body"><div class="lsc-label">Ledger Entry Created</div><div class="lsc-sub">GitHub issue sealed</div><a href="${data.issue_url}" target="_blank" class="lsc-link">View GitHub Issue ↗</a></div>`;
@@ -378,12 +450,10 @@
378450
statusCard.innerHTML = `<div class="lsc-icon">⟳</div><div class="lsc-body"><div class="lsc-label">Ledger Pending</div><div class="lsc-sub">Seal recorded locally</div></div>`;
379451
}
380452

381-
// Save to session ledger
382453
sessionLedger.unshift(CURRENT_ENTRY);
383454
if (sessionLedger.length > 50) sessionLedger.pop();
384455
localStorage.setItem('stp-session-ledger', JSON.stringify(sessionLedger));
385456
renderLedger();
386-
387457
document.getElementById('reset-btn').classList.add('visible');
388458

389459
} catch (err) {
@@ -426,8 +496,8 @@
426496
function copyJSON() {
427497
if (!CURRENT_ENTRY) return;
428498
navigator.clipboard.writeText(JSON.stringify(CURRENT_ENTRY, null, 2));
429-
const btn = document.querySelector('#seal-result .action-btn:last-child');
430-
if (btn) { btn.textContent = '✓ Copied'; setTimeout(() => { btn.textContent = 'Copy JSON'; }, 2000); }
499+
const btns = document.querySelectorAll('#seal-result .action-btn');
500+
btns.forEach(btn => { if (btn.textContent.includes('Copy')) { btn.textContent = '✓ Copied'; setTimeout(() => { btn.textContent = 'Copy JSON'; }, 2000); } });
431501
}
432502

433503
async function runVerify() {
@@ -459,12 +529,11 @@
459529
document.getElementById('ledger-count').textContent = sessionLedger.length;
460530
container.innerHTML = sessionLedger.map(e => `
461531
<div class="ledger-entry">
462-
<div class="le-header"><span class="le-id">${e.ledger_id}</span><span class="le-template">${e.template_name}</span></div>
532+
<div class="le-header"><span class="le-id">${e.ledger_id}</span><span class="le-template">${e.template_name || e.template}</span></div>
463533
<div class="le-content">${(e.content || '').substring(0, 120)}${e.content?.length > 120 ? '…' : ''}</div>
464-
<div class="le-times"><span class="le-time">${e.seal?.gregorian || ''}</span></div>
465534
<div class="le-hash">${e.content_hash?.substring(0, 50)}…</div>
466535
${e.github_issue_url ? `<a href="${e.github_issue_url}" target="_blank" class="le-github-link">✓ GitHub Issue ↗</a>` : ''}
467-
<div class="le-actions"><button class="le-btn" onclick="downloadEntry('${e.ledger_id}')">↓ JSON</button></div>
536+
<div><button class="le-btn" onclick="downloadEntry('${e.ledger_id}')">↓ Download JSON</button></div>
468537
</div>
469538
`).join('');
470539
}
@@ -483,9 +552,11 @@
483552
}
484553

485554
function clearLedger() {
486-
sessionLedger = [];
487-
localStorage.removeItem('stp-session-ledger');
488-
renderLedger();
555+
if (confirm('Clear all session seals? (JSON files on disk remain)')) {
556+
sessionLedger = [];
557+
localStorage.removeItem('stp-session-ledger');
558+
renderLedger();
559+
}
489560
}
490561

491562
function syntaxHighlight(json) {
@@ -512,7 +583,7 @@
512583
document.getElementById('theme-btn').textContent = isLight ? 'LIGHT' : 'DARK';
513584
}
514585

515-
// Load session ledger from localStorage
586+
// Load session ledger
516587
try {
517588
const saved = localStorage.getItem('stp-session-ledger');
518589
if (saved) sessionLedger = JSON.parse(saved);

0 commit comments

Comments
 (0)