Test-Chat / index.html
Zandy-Wandy's picture
Update index.html
57a3f99 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Orenthal — Intelligence, Complete.</title>
<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=Cinzel:wght@400;500;600;700;900&family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400;1,500&family=JetBrains+Mono:wght@300;400;500&display=swap" rel="stylesheet"/>
<style>
:root{
--stone:#f4efe4;--cloud:#faf7f2;--ink:#18140e;--charcoal:#2e2820;
--ash:#7a6e60;--ghost:#a89e8e;--smoke:rgba(255,255,255,0.07);
--zeus:#d4af37;--zeus-pale:#f0d878;--zeus-dim:#8b6914;
--zeus-sky:#c8dff0;--zeus-storm:#2c3e6b;
--lattice:#c9a84c;--echo:#8b3a2a;--zenith:#4a7041;--vexa:#7c4ab0;
--bg:#0f0d09;--bg2:#131008;--bg3:#181410;--bg4:#1e1a13;
--border:rgba(212,175,55,0.12);--border-dim:rgba(212,175,55,0.06);
}
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box;}
html,body{height:100%;overflow:hidden;}
body{background:var(--bg);color:var(--stone);font-family:'EB Garamond',Georgia,serif;font-size:15px;line-height:1.7;display:flex;flex-direction:column;}
.shell{display:grid;grid-template-columns:252px 1fr;grid-template-rows:54px 1fr;height:100vh;overflow:hidden;}
/* TOPBAR */
.topbar{grid-column:1/-1;background:#0a0805;border-bottom:1px solid var(--border-dim);display:flex;align-items:center;justify-content:space-between;padding:0 18px;z-index:100;position:relative;}
.topbar-glow{position:absolute;bottom:0;left:15%;right:15%;height:1px;background:linear-gradient(90deg,transparent,rgba(212,175,55,0.25),transparent);}
.brand{display:flex;align-items:center;gap:10px;text-decoration:none;}
.brand-text{font-family:'Cinzel',serif;font-weight:700;font-size:12.5px;letter-spacing:0.28em;color:var(--stone);line-height:1;}
.brand-text small{display:block;font-weight:400;font-size:6.5px;letter-spacing:0.5em;color:rgba(212,175,55,0.55);margin-top:3px;}
.pills{position:absolute;left:50%;transform:translateX(-50%);display:flex;gap:3px;}
.pill{font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.2em;text-transform:uppercase;padding:5px 15px;border:1px solid rgba(255,255,255,0.06);color:var(--ash);background:none;cursor:pointer;transition:all .18s;white-space:nowrap;}
.pill:hover{border-color:rgba(212,175,55,0.2);color:var(--ghost);}
.pill.az{border-color:var(--zeus);color:var(--zeus);background:rgba(212,175,55,0.06);}
.pill.al{border-color:var(--lattice);color:var(--lattice);background:rgba(201,168,76,0.05);}
.pill.av{border-color:var(--vexa);color:var(--vexa);background:rgba(124,74,176,0.05);}
.tbr{display:flex;align-items:center;gap:12px;}
.mode-badge{display:flex;align-items:center;gap:6px;font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.2em;color:var(--ash);}
.mdot{width:6px;height:6px;border-radius:50%;background:var(--ash);transition:all .3s;}
.mdot.live{background:var(--zenith);box-shadow:0 0 7px var(--zenith);}
.bcfg{font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.18em;color:var(--ash);background:none;border:1px solid rgba(255,255,255,0.07);padding:5px 13px;cursor:pointer;transition:all .18s;}
.bcfg:hover{border-color:rgba(212,175,55,0.2);color:var(--ghost);}
/* SIDEBAR */
.sidebar{background:var(--bg2);border-right:1px solid var(--border-dim);display:flex;flex-direction:column;overflow:hidden;}
.sb-top{padding:14px;border-bottom:1px solid var(--border-dim);}
.bnew{width:100%;font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.22em;text-transform:uppercase;color:var(--zeus);background:rgba(212,175,55,0.05);border:1px solid rgba(212,175,55,0.18);padding:10px;cursor:pointer;transition:all .18s;display:flex;align-items:center;justify-content:center;gap:8px;}
.bnew:hover{background:rgba(212,175,55,0.10);border-color:rgba(212,175,55,0.35);}
.sb-sec{padding:14px;border-bottom:1px solid var(--border-dim);}
.sblbl{font-family:'Cinzel',serif;font-size:6.5px;letter-spacing:0.45em;color:rgba(212,175,55,0.3);text-transform:uppercase;margin-bottom:10px;display:flex;align-items:center;gap:8px;}
.sblbl::after{content:'';flex:1;height:1px;background:rgba(212,175,55,0.07);}
.mc{border:1px solid var(--border-dim);background:rgba(255,255,255,0.015);padding:13px;margin-bottom:8px;}
.mc-h{display:flex;align-items:center;justify-content:space-between;margin-bottom:7px;}
.mc-n{font-family:'Cinzel',serif;font-weight:600;font-size:11px;letter-spacing:0.06em;}
.mc-b{font-family:'Cinzel',serif;font-size:6.5px;letter-spacing:0.15em;padding:2px 7px;border:1px solid currentColor;}
.mc-d{font-size:11px;color:var(--ash);line-height:1.6;margin-bottom:10px;}
.mc-g{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:rgba(255,255,255,0.04);}
.mc-s{background:var(--bg);padding:6px 8px;}
.mc-v{font-family:'Cinzel',serif;font-size:11px;font-weight:600;color:var(--stone);line-height:1;}
.mc-k{font-family:'JetBrains Mono',monospace;font-size:7.5px;color:var(--ash);margin-top:2px;}
.tsel{width:100%;background:var(--bg4);border:1px solid rgba(255,255,255,0.07);color:var(--ghost);font-family:'JetBrains Mono',monospace;font-size:10.5px;padding:7px 9px;outline:none;cursor:pointer;}
.tsel:focus{border-color:rgba(212,175,55,0.2);}
.sb-hl{padding:10px 14px 6px;}
.hist{flex:1;overflow-y:auto;padding:6px 8px;}
.hist::-webkit-scrollbar{width:2px;}
.hist::-webkit-scrollbar-thumb{background:rgba(212,175,55,0.1);}
.hi{padding:8px 9px;cursor:pointer;border:1px solid transparent;margin-bottom:2px;transition:all .15s;}
.hi:hover{background:rgba(255,255,255,0.025);border-color:var(--border-dim);}
.hi.cur{background:rgba(212,175,55,0.04);border-color:var(--border);}
.hi-t{font-size:11.5px;color:var(--ghost);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2;margin-bottom:2px;}
.hi-m{font-family:'JetBrains Mono',monospace;font-size:8.5px;color:rgba(122,110,96,0.5);}
.sb-cfg{padding:11px 14px;border-top:1px solid var(--border-dim);background:var(--bg2);}
.cfglbl{font-family:'Cinzel',serif;font-size:6px;letter-spacing:0.3em;color:rgba(212,175,55,0.28);text-transform:uppercase;margin-bottom:4px;}
.cfgin{width:100%;background:var(--bg4);border:1px solid rgba(255,255,255,0.06);color:var(--ghost);font-family:'JetBrains Mono',monospace;font-size:10px;padding:5px 8px;outline:none;margin-bottom:6px;transition:border-color .15s;}
.cfgin:last-child{margin-bottom:0;}
.cfgin:focus{border-color:rgba(212,175,55,0.22);}
.cfgin::placeholder{color:rgba(122,110,96,0.35);}
/* MAIN */
.main{display:flex;flex-direction:column;overflow:hidden;background:var(--bg);position:relative;}
/* LANDING */
.landing{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px;position:relative;overflow:hidden;}
.landing.gone{display:none;}
.lgrid{position:absolute;inset:0;pointer-events:none;background-image:linear-gradient(rgba(212,175,55,0.035) 1px,transparent 1px),linear-gradient(90deg,rgba(212,175,55,0.035) 1px,transparent 1px);background-size:52px 52px;-webkit-mask-image:radial-gradient(ellipse 65% 65% at 50% 50%,black 30%,transparent 100%);mask-image:radial-gradient(ellipse 65% 65% at 50% 50%,black 30%,transparent 100%);}
.lglow{position:absolute;inset:0;pointer-events:none;background:radial-gradient(ellipse 55% 45% at 50% 48%,rgba(212,175,55,0.05),transparent 70%);}
.llogo{position:relative;z-index:1;margin-bottom:28px;animation:fy 5s ease-in-out infinite;filter:drop-shadow(0 0 18px rgba(212,175,55,0.18));}
@keyframes fy{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}}
.lname{font-family:'Cinzel',serif;font-weight:900;font-size:clamp(32px,4vw,52px);letter-spacing:0.18em;color:var(--stone);position:relative;z-index:1;line-height:1;margin-bottom:8px;text-align:center;}
.lname .g{color:var(--zeus);}
.ltag{font-family:'EB Garamond',serif;font-style:italic;font-size:17px;color:var(--ash);position:relative;z-index:1;margin-bottom:36px;text-align:center;}
.starters{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;max-width:680px;width:100%;position:relative;z-index:1;}
.sc{padding:15px 14px;border:1px solid var(--border-dim);background:rgba(255,255,255,0.015);cursor:pointer;transition:all .2s;text-align:left;}
.sc:hover{background:rgba(212,175,55,0.04);border-color:var(--border);transform:translateY(-2px);}
.sc-i{font-size:15px;display:block;margin-bottom:7px;}
.sc-t{font-family:'Cinzel',serif;font-size:9.5px;font-weight:600;letter-spacing:0.06em;color:var(--stone);margin-bottom:3px;}
.sc-d{font-size:11.5px;color:var(--ash);line-height:1.5;}
/* CHAT */
.chat{flex:1;overflow-y:auto;padding:20px 0;display:none;flex-direction:column;}
.chat.on{display:flex;}
.chat::-webkit-scrollbar{width:3px;}
.chat::-webkit-scrollbar-thumb{background:rgba(212,175,55,0.1);}
.msg{padding:10px 28px;display:flex;gap:14px;align-items:flex-start;animation:mi .2s ease both;}
@keyframes mi{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
.msg.user{flex-direction:row-reverse;}
.msg.user .bubble{background:var(--bg4);border:1px solid rgba(255,255,255,0.07);margin-left:56px;padding:10px 14px;}
.msg.asst .bubble{background:transparent;border:none;border-left:2px solid var(--zeus);padding:2px 0 2px 16px;margin-right:56px;}
.msg.asst[data-m="lattice"] .bubble{border-left-color:var(--lattice);}
.msg.asst[data-m="vexa"] .bubble{border-left-color:var(--vexa);}
.ava{width:26px;height:26px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:13px;margin-top:3px;}
.bubble{flex:1;min-width:0;}
.mlbl{font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.25em;color:rgba(212,175,55,0.3);margin-bottom:5px;text-transform:uppercase;}
.mbody{font-size:14.5px;color:var(--stone);line-height:1.82;white-space:pre-wrap;word-break:break-word;}
.mbody strong{color:var(--stone);font-weight:600;}
.mbody code{font-family:'JetBrains Mono',monospace;font-size:11.5px;background:rgba(255,255,255,0.07);padding:1px 5px;color:var(--zeus-sky);}
.mbody pre{background:rgba(9,7,5,0.8);border:1px solid rgba(255,255,255,0.07);padding:13px 15px;margin:10px 0;overflow-x:auto;font-family:'JetBrains Mono',monospace;font-size:11.5px;color:rgba(244,239,228,0.78);line-height:1.65;}
.mbody pre code{background:none;padding:0;color:inherit;}
.epi{margin-top:9px;padding:7px 11px;background:rgba(212,175,55,0.03);border:1px solid rgba(212,175,55,0.09);}
.epi-hd{font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.18em;color:rgba(212,175,55,0.38);cursor:pointer;user-select:none;display:flex;align-items:center;gap:6px;}
.epi-hd:hover{color:rgba(212,175,55,0.6);}
.epi-body{display:none;margin-top:7px;font-family:'JetBrains Mono',monospace;font-size:10px;color:var(--ash);grid-template-columns:1fr 1fr;gap:3px 18px;}
.epi-body.open{display:grid;}
.dots{display:flex;gap:5px;padding:4px 0;align-items:center;}
.dots span{width:6px;height:6px;border-radius:50%;opacity:0.3;animation:dk 1.3s ease-in-out infinite;}
.dots span:nth-child(1){background:var(--zeus);animation-delay:0s;}
.dots span:nth-child(2){background:var(--lattice);animation-delay:.18s;}
.dots span:nth-child(3){background:var(--zeus-sky);animation-delay:.36s;}
@keyframes dk{0%,60%,100%{opacity:.28;transform:scale(1)}30%{opacity:1;transform:scale(1.35)}}
/* INPUT */
.izone{padding:11px 28px 14px;background:var(--bg);border-top:1px solid var(--border-dim);position:relative;}
.izone::before{content:'';position:absolute;top:0;left:8%;right:8%;height:1px;background:linear-gradient(90deg,transparent,rgba(212,175,55,0.18),transparent);}
.iwrap{display:flex;gap:8px;align-items:flex-end;background:var(--bg4);border:1px solid rgba(255,255,255,0.07);padding:9px 12px;transition:border-color .18s;}
.iwrap:focus-within{border-color:rgba(212,175,55,0.22);}
.ita{flex:1;background:none;border:none;outline:none;color:var(--stone);font-family:'EB Garamond',serif;font-size:15px;line-height:1.6;resize:none;max-height:130px;min-height:22px;}
.ita::placeholder{color:rgba(122,110,96,0.4);}
.sbtn{width:34px;height:34px;background:var(--zeus);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .18s;margin-bottom:1px;}
.sbtn:hover{background:var(--zeus-pale);transform:scale(1.06);}
.sbtn:disabled{background:rgba(255,255,255,0.08);cursor:not-allowed;transform:none;}
.sbtn svg{width:15px;height:15px;}
.ift{display:flex;justify-content:space-between;align-items:center;margin-top:6px;padding:0 2px;}
.ihint{font-family:'Cinzel',serif;font-size:7px;letter-spacing:0.15em;color:rgba(122,110,96,0.35);}
.wtag{font-family:'JetBrains Mono',monospace;font-size:8.5px;color:rgba(212,175,55,0.2);}
/* MODAL */
.overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,0.8);z-index:300;align-items:center;justify-content:center;backdrop-filter:blur(6px);}
.overlay.on{display:flex;}
.modal{background:var(--bg2);border:1px solid rgba(212,175,55,0.16);width:480px;max-height:82vh;overflow-y:auto;}
.modal::-webkit-scrollbar{width:3px;}
.modal::-webkit-scrollbar-thumb{background:rgba(212,175,55,0.1);}
.mhd{padding:18px 22px 14px;border-bottom:1px solid var(--border-dim);display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;background:var(--bg2);z-index:1;}
.mtitle{font-family:'Cinzel',serif;font-size:11px;font-weight:600;letter-spacing:0.22em;text-transform:uppercase;color:var(--zeus);}
.mx{background:none;border:none;color:var(--ash);cursor:pointer;font-size:20px;line-height:1;padding:0;transition:color .15s;}
.mx:hover{color:var(--stone);}
.mbody{padding:22px;}
.msec{margin-bottom:22px;}
.msect{font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.35em;color:rgba(212,175,55,0.35);text-transform:uppercase;margin-bottom:13px;display:flex;align-items:center;gap:10px;}
.msect::after{content:'';flex:1;height:1px;background:rgba(212,175,55,0.07);}
.mfld{margin-bottom:11px;}
.mlbl{font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.2em;color:var(--ash);text-transform:uppercase;margin-bottom:5px;display:block;}
.min{width:100%;background:var(--bg4);border:1px solid rgba(255,255,255,0.07);color:var(--stone);font-family:'JetBrains Mono',monospace;font-size:12px;padding:9px 11px;outline:none;transition:border-color .15s;}
.min:focus{border-color:rgba(212,175,55,0.28);}
.min::placeholder{color:rgba(122,110,96,0.32);}
.pgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:5px;margin-bottom:11px;}
.pbtn{font-family:'Cinzel',serif;font-size:7.5px;letter-spacing:0.1em;padding:8px 5px;border:1px solid rgba(255,255,255,0.07);background:transparent;color:var(--ash);cursor:pointer;transition:all .15s;text-align:center;}
.pbtn:hover{border-color:rgba(212,175,55,0.2);color:var(--ghost);}
.pbtn.sel{border-color:var(--zeus);color:var(--zeus);background:rgba(212,175,55,0.05);}
.mrange{width:100%;accent-color:var(--zeus);cursor:pointer;}
.msave{width:100%;font-family:'Cinzel',serif;font-size:9px;letter-spacing:0.25em;text-transform:uppercase;color:var(--ink);background:var(--zeus);border:none;padding:12px;cursor:pointer;transition:all .18s;margin-top:6px;}
.msave:hover{background:var(--zeus-pale);}
.mnote{font-size:12.5px;color:var(--ash);line-height:1.65;font-style:italic;}
::-webkit-scrollbar{width:4px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:rgba(212,175,55,0.1);}
@keyframes shim{0%{background-position:-400% 0}100%{background-position:400% 0}}
.shim{background:linear-gradient(105deg,transparent 40%,rgba(212,175,55,0.045) 50%,transparent 60%);background-size:400% 100%;animation:shim 9s linear infinite;}
</style>
</head>
<body>
<div class="shell">
<header class="topbar">
<div class="topbar-glow"></div>
<a class="brand" href="#">
<!-- ORENTHAL LOGO: hexagonal prism, 6 faces, white highlight slash on upper-right face -->
<svg width="34" height="34" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="tl" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#4a3a10"/><stop offset="100%" stop-color="#2c3e6b" stop-opacity=".9"/></linearGradient>
<linearGradient id="tr" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#d4af37" stop-opacity=".85"/><stop offset="60%" stop-color="#c8dff0" stop-opacity=".7"/><stop offset="100%" stop-color="#8b6914" stop-opacity=".6"/></linearGradient>
<linearGradient id="ml" x1="100%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#8b6914" stop-opacity=".8"/><stop offset="100%" stop-color="#1a1510"/></linearGradient>
<linearGradient id="mr" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#c8dff0" stop-opacity=".55"/><stop offset="100%" stop-color="#2c3e6b" stop-opacity=".45"/></linearGradient>
<linearGradient id="bl" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#2c2010" stop-opacity=".95"/><stop offset="100%" stop-color="#0a0806"/></linearGradient>
<linearGradient id="br" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#1e2840" stop-opacity=".9"/><stop offset="100%" stop-color="#0c0e18"/></linearGradient>
<linearGradient id="eg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#d4af37" stop-opacity=".9"/><stop offset="50%" stop-color="#f0e8c8" stop-opacity=".7"/><stop offset="100%" stop-color="#c8dff0" stop-opacity=".5"/></linearGradient>
<filter id="gv"><feGaussianBlur stdDeviation="1.5" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
</defs>
<polygon points="60,8 18,34 60,60" fill="url(#tl)"/>
<polygon points="60,8 102,34 60,60" fill="url(#tr)"/>
<polygon points="18,34 18,86 60,60" fill="url(#ml)"/>
<polygon points="102,34 102,86 60,60" fill="url(#mr)"/>
<polygon points="18,86 60,112 60,60" fill="url(#bl)"/>
<polygon points="102,86 60,112 60,60" fill="url(#br)"/>
<polygon points="72,14 100,30 78,48" fill="rgba(255,255,255,.72)" filter="url(#gv)"/>
<polygon points="80,20 100,32 88,44" fill="rgba(255,255,255,.25)"/>
<polygon points="60,8 102,34 102,86 60,112 18,86 18,34" fill="none" stroke="url(#eg)" stroke-width="1.5" stroke-linejoin="round"/>
<line x1="60" y1="8" x2="60" y2="60" stroke="rgba(212,175,55,.22)" stroke-width=".8"/>
<line x1="18" y1="34" x2="60" y2="60" stroke="rgba(212,175,55,.15)" stroke-width=".7"/>
<line x1="102" y1="34" x2="60" y2="60" stroke="rgba(200,223,240,.18)" stroke-width=".7"/>
<line x1="18" y1="86" x2="60" y2="60" stroke="rgba(212,175,55,.10)" stroke-width=".6"/>
<line x1="102" y1="86" x2="60" y2="60" stroke="rgba(44,62,107,.18)" stroke-width=".6"/>
<line x1="60" y1="112" x2="60" y2="60" stroke="rgba(212,175,55,.12)" stroke-width=".7"/>
<circle cx="60" cy="8" r="2.5" fill="#d4af37" opacity=".9" filter="url(#gv)"/>
<circle cx="60" cy="112" r="2.5" fill="#d4af37" opacity=".7" filter="url(#gv)"/>
<circle cx="102" cy="34" r="2" fill="#c8dff0" opacity=".75"/>
<circle cx="18" cy="34" r="2" fill="#8b6914" opacity=".55"/>
<circle cx="60" cy="60" r="1.8" fill="#ffffff" opacity=".82"/>
</svg>
<div class="brand-text">ORENTHAL<small>Frontier Intelligence</small></div>
</a>
<div class="pills">
<button class="pill az" data-m="zeus" onclick="pickM('zeus',this)">⚡ Zeus</button>
<button class="pill" data-m="lattice" onclick="pickM('lattice',this)">🌐 Lattice</button>
<button class="pill" data-m="vexa" onclick="pickM('vexa',this)">🔷 Vexa</button>
</div>
<div class="tbr">
<div class="mode-badge"><div class="mdot" id="mDot"></div><span id="mLbl">MOCK MODE</span></div>
<button class="bcfg" onclick="openCfg()">⚙ Config</button>
</div>
</header>
<aside class="sidebar">
<div class="sb-top"><button class="bnew" onclick="newChat()">&nbsp; New Conversation</button></div>
<div class="sb-sec">
<div class="sblbl">Active Model</div>
<div class="mc shim">
<div class="mc-h">
<div class="mc-n" id="mcN" style="color:var(--zeus)">Orenthal Zeus</div>
<div class="mc-b" id="mcB" style="color:var(--zeus)">Early Access</div>
</div>
<div class="mc-d" id="mcD">SACM architecture. Sovereign reasoning. EQ Engine V3.</div>
<div class="mc-g">
<div class="mc-s"><div class="mc-v" id="mcP">70B</div><div class="mc-k">params</div></div>
<div class="mc-s"><div class="mc-v" id="mcC">256K</div><div class="mc-k">context</div></div>
<div class="mc-s"><div class="mc-v" id="mcPr" style="color:var(--zeus)">$1.00</div><div class="mc-k">/ 1M tkn</div></div>
<div class="mc-s"><div class="mc-v" id="mcE">24</div><div class="mc-k">experts</div></div>
</div>
</div>
<select class="tsel" id="tsel" onchange="onTier()"></select>
</div>
<div class="sb-hl"><div class="sblbl">History</div></div>
<div class="hist" id="hist"><div style="font-size:11px;color:rgba(122,110,96,.28);padding:6px;font-style:italic;">No conversations yet.</div></div>
<div class="sb-cfg">
<div class="cfglbl">Base URL</div>
<input class="cfgin" id="sbUrl" placeholder="https://api.together.xyz/v1" oninput="onCC()"/>
<div class="cfglbl" style="margin-top:5px;">API Key</div>
<input class="cfgin" id="sbKey" type="password" placeholder="sk-••••••••" oninput="onCC()"/>
</div>
</aside>
<main class="main">
<div class="landing" id="land">
<div class="lgrid"></div><div class="lglow"></div>
<div class="llogo">
<svg width="108" height="108" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="Ltl" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#5a4515" stop-opacity=".9"/><stop offset="100%" stop-color="#2c3e6b" stop-opacity=".85"/></linearGradient>
<linearGradient id="Ltr" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#d4af37" stop-opacity=".9"/><stop offset="55%" stop-color="#e8d898" stop-opacity=".75"/><stop offset="100%" stop-color="#c8dff0" stop-opacity=".65"/></linearGradient>
<linearGradient id="Lml" x1="100%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#8b6914" stop-opacity=".85"/><stop offset="100%" stop-color="#141008" stop-opacity=".95"/></linearGradient>
<linearGradient id="Lmr" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#c8dff0" stop-opacity=".6"/><stop offset="100%" stop-color="#2c3e6b" stop-opacity=".5"/></linearGradient>
<linearGradient id="Lbl" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#2a1c0a"/><stop offset="100%" stop-color="#080604"/></linearGradient>
<linearGradient id="Lbr" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" stop-color="#162030" stop-opacity=".92"/><stop offset="100%" stop-color="#060810"/></linearGradient>
<filter id="Lg"><feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
<filter id="Lo"><feGaussianBlur stdDeviation="10" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
</defs>
<polygon points="60,8 102,34 102,86 60,112 18,86 18,34" fill="rgba(212,175,55,.07)" filter="url(#Lo)"/>
<polygon points="60,8 18,34 60,60" fill="url(#Ltl)"/>
<polygon points="60,8 102,34 60,60" fill="url(#Ltr)"/>
<polygon points="18,34 18,86 60,60" fill="url(#Lml)"/>
<polygon points="102,34 102,86 60,60" fill="url(#Lmr)"/>
<polygon points="18,86 60,112 60,60" fill="url(#Lbl)"/>
<polygon points="102,86 60,112 60,60" fill="url(#Lbr)"/>
<polygon points="72,14 100,30 78,48" fill="rgba(255,255,255,.75)" filter="url(#Lg)"/>
<polygon points="80,20 100,32 88,44" fill="rgba(255,255,255,.30)"/>
<polygon points="60,8 102,34 102,86 60,112 18,86 18,34" fill="none" stroke="rgba(212,175,55,.6)" stroke-width="1.4" stroke-linejoin="round"/>
<line x1="60" y1="8" x2="60" y2="60" stroke="rgba(212,175,55,.28)" stroke-width=".9"/>
<line x1="18" y1="34" x2="60" y2="60" stroke="rgba(212,175,55,.18)" stroke-width=".7"/>
<line x1="102" y1="34" x2="60" y2="60" stroke="rgba(200,223,240,.22)" stroke-width=".8"/>
<line x1="18" y1="86" x2="60" y2="60" stroke="rgba(212,175,55,.12)" stroke-width=".6"/>
<line x1="102" y1="86" x2="60" y2="60" stroke="rgba(44,62,107,.2)" stroke-width=".7"/>
<line x1="60" y1="112" x2="60" y2="60" stroke="rgba(212,175,55,.16)" stroke-width=".8"/>
<circle cx="60" cy="8" r="3.5" fill="#d4af37" opacity=".95" filter="url(#Lg)"/>
<circle cx="102" cy="34" r="2.8" fill="#c8dff0" opacity=".80"/>
<circle cx="102" cy="86" r="2.8" fill="#c8dff0" opacity=".68"/>
<circle cx="60" cy="112" r="3.5" fill="#d4af37" opacity=".80" filter="url(#Lg)"/>
<circle cx="18" cy="86" r="2.8" fill="#8b6914" opacity=".55"/>
<circle cx="18" cy="34" r="2.8" fill="#8b6914" opacity=".60"/>
<circle cx="60" cy="60" r="7" fill="rgba(212,175,55,.12)" filter="url(#Lo)"/>
<circle cx="60" cy="60" r="3.5" fill="rgba(212,175,55,.25)" filter="url(#Lg)"/>
<circle cx="60" cy="60" r="1.8" fill="#ffffff" opacity=".9" filter="url(#Lg)"/>
</svg>
</div>
<h1 class="lname">ORENT<span class="g">H</span>AL</h1>
<p class="ltag">"Intelligence, complete."</p>
<div class="starters">
<div class="sc" onclick="starter(this)"><span class="sc-i"></span><div class="sc-t">What is Zeus?</div><div class="sc-d">Explain the SACM architecture and what makes Zeus different from other frontier models.</div></div>
<div class="sc" onclick="starter(this)"><span class="sc-i">🧠</span><div class="sc-t">Reason through a problem</div><div class="sc-d">Give me a complex problem to work through step by step with full reasoning shown.</div></div>
<div class="sc" onclick="starter(this)"><span class="sc-i">💻</span><div class="sc-t">Write some code</div><div class="sc-d">Ask Zeus to write, review, or debug code in any language.</div></div>
<div class="sc" onclick="starter(this)"><span class="sc-i">🌐</span><div class="sc-t">Try Matrix Lattice</div><div class="sc-d">Switch to Lattice for long-horizon planning, multi-step agentic tasks, and 1M context.</div></div>
<div class="sc" onclick="starter(this)"><span class="sc-i">🔷</span><div class="sc-t">What is Vexa?</div><div class="sc-d">Explore the crystalline intelligence substrate — no neural weights, no training required.</div></div>
<div class="sc" onclick="starter(this)"><span class="sc-i">📡</span><div class="sc-t">API quickstart</div><div class="sc-d">Show me how to connect to the Orenthal API in Python, JavaScript, or cURL.</div></div>
</div>
</div>
<div class="chat" id="chat"></div>
<div class="izone">
<div class="iwrap">
<textarea class="ita" id="inp" placeholder="Message Orenthal…" rows="1" onkeydown="onKey(event)" oninput="grow(this)"></textarea>
<button class="sbtn" id="sbtn" onclick="send()">
<svg viewBox="0 0 24 24" fill="none" stroke="var(--ink)" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2" fill="var(--ink)"/></svg>
</button>
</div>
<div class="ift">
<span class="ihint">Enter · send &nbsp;·&nbsp; Shift+Enter · new line</span>
<span class="wtag">orenthal.wtf</span>
</div>
</div>
</main>
</div>
<div class="overlay" id="cfgOv">
<div class="modal">
<div class="mhd"><div class="mtitle">&nbsp;Configuration</div><button class="mx" onclick="closeCfg()">×</button></div>
<div class="mbody">
<div class="msec">
<div class="msect">Inference Provider</div>
<div class="pgrid">
<button class="pbtn" onclick="setProv('https://api.together.xyz/v1',this)">Together AI</button>
<button class="pbtn" onclick="setProv('https://api.novita.ai/v1',this)">Novita</button>
<button class="pbtn" onclick="setProv('https://api.hyperbolic.xyz/v1',this)">Hyperbolic</button>
<button class="pbtn" onclick="setProv('http://localhost:8000/v1',this)">Local vLLM</button>
<button class="pbtn" onclick="setProv('https://orenthal.wtf/v1',this)">orenthal.wtf</button>
<button class="pbtn" onclick="setProv('',this)">Custom</button>
</div>
<div class="mfld"><label class="mlbl">Base URL</label><input class="min" id="cfgUrl" placeholder="https://api.together.xyz/v1"/></div>
<div class="mfld"><label class="mlbl">API Key</label><input class="min" id="cfgKey" type="password" placeholder="sk-••••••••••••"/></div>
</div>
<div class="msec">
<div class="msect">Generation</div>
<div class="mfld"><label class="mlbl">Temperature &nbsp;<span id="tVal" style="color:var(--zeus)">0.7</span></label><input type="range" class="mrange" id="cfgTemp" min="0" max="2" step="0.05" value="0.7" oninput="document.getElementById('tVal').textContent=this.value"/></div>
<div class="mfld"><label class="mlbl">Max Tokens</label><input class="min" id="cfgMt" type="number" value="2048" min="64" max="32768"/></div>
<div class="mfld"><label class="mlbl">System Prompt</label><textarea class="min" id="cfgSys" rows="4" placeholder="You are Zeus, frontier intelligence…" style="resize:vertical"></textarea></div>
</div>
<div class="msec">
<div class="msect">Zeus Extensions</div>
<p class="mnote">On a live Orenthal endpoint Zeus exposes <code style="font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--zeus-sky)">GET /v1/zeus/epistemic</code>, <code style="font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--zeus-sky)">/v1/zeus/clarify</code>, and <code style="font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--zeus-sky)">/v1/zeus/restate</code>. Mock mode simulates these automatically.</p>
</div>
<button class="msave" onclick="saveCfg()">Save Configuration</button>
</div>
</div>
</div>
<script>
const MD={
zeus:{name:'Orenthal Zeus',short:'Zeus',icon:'⚡',badge:'Early Access',color:'--zeus',desc:'SACM architecture. Sovereign reasoning. EQ Engine V3. Calibrated honesty.',p:'70B',ctx:'256K',price:'$1.00',exp:'24',tiers:[{l:'zeus-70b · 256K · $1.00',v:'orenthal/zeus-70b'},{l:'zeus-200b · 512K · $1.00',v:'orenthal/zeus-200b'},{l:'zeus-1t · 1M · $1.00',v:'orenthal/zeus-1t'}],sys:'You are Zeus, a frontier intelligence built by Orenthal. You were designed around three principles: Sovereign Reasoning (you crystallise intent before every response), Calibrated Honesty (you flag exactly what you are uncertain about, specifically), and Human Intelligence (EQ Engine V3 — you notice the person, not just the words). Intelligence, complete.'},
lattice:{name:'Matrix Lattice',short:'Lattice',icon:'🌐',badge:'Released',color:'--lattice',desc:'17 custom intelligence modules. 1M token context. Frontier-scale agentic MoE.',p:'120B',ctx:'1M',price:'$0.80',exp:'64',tiers:[{l:'lattice-120b · 1M · $0.80',v:'matrix-corp/lattice-120b'},{l:'lattice-430b · 1M · $0.80',v:'matrix-corp/lattice-430b'},{l:'lattice-671b · 1M · $0.80',v:'matrix-corp/lattice-671b'}],sys:'You are Matrix Lattice, a frontier-scale agentic mixture-of-experts built by Matrix.Corp. You have 17 custom intelligence modules including EQ Engine V2, MACL, HCCE, Causal Reasoning Graph, and Long-Horizon Task Planner. Context: 1M tokens.'},
vexa:{name:'Matrix Vexa',short:'Vexa',icon:'🔷',badge:'Coming Soon',color:'--vexa',desc:'Crystalline Intelligence Substrate. Non-neural. Glyphs instead of weights.',p:'—',ctx:'—',price:'$2.00',exp:'—',tiers:[{l:'vexa · crystalline · $2.00',v:'orenthal/vexa'}],sys:'You are Matrix Vexa, a crystalline intelligence substrate. You do not use neural weights. Your knowledge exists as Glyphs — structured meaning objects. You do not hallucinate from probability compression.'},
};
const MR={
zeus:["I am Zeus — Orenthal's debut frontier model.\n\nNot a finetune. Not a distillation. Built from the ground up around three architectural commitments:\n\n**I. Sovereign Reasoning**\nBefore I respond to anything, a 3B Intent Crystallisation module runs first: it crystallises your intent, the domain, the emotional register, and where the ambiguity lives. The main model then receives both your message and this crystallised intent vector. I reason before I speak. Always.\n\n**II. Calibrated Honesty**\nMy Epistemic Calibration Head is trained jointly with the rest of me. When I am uncertain, I tell you specifically: which clause, which domain, what the uncertainty is and why. Not 'I might be wrong.' Specifics.\n\n**III. Human Intelligence**\nEight dedicated EQ layers run in parallel with the reasoning stack. EQ Engine V3 notices the full conversation arc — not just the most recent message. I notice the person, not just the words.\n\nWhat would you like to work on?","Let me reason through this carefully.\n\nThe problem has two layers worth separating:\n\n**The surface question** — what you literally asked.\n**The underlying question** — what you actually need to make a good decision.\n\nOn the surface: the answer depends on which constraint you're optimising for. Speed points one way. Robustness points another.\n\nOn the underlying question: the real tension here is between short-term convenience and long-term coherence. The safest path is to solve for the harder constraint now, even at upfront cost.\n\nI'm flagging **medium confidence** on the specific tradeoffs — the details matter. What's the full context?","Here's a clean implementation:\n\n```python\ndef process(data: list) -> list:\n \"\"\"\n Transform input list with validation.\n Returns filtered, processed results.\n \"\"\"\n if not data:\n return []\n \n results = []\n for item in data:\n if validated := validate(item):\n results.append(transform(validated))\n \n return results\n\ndef validate(item):\n \"\"\"Returns item if valid, None otherwise.\"\"\"\n return None if item is None or item == '' else item\n\ndef transform(item):\n \"\"\"Core transformation logic — implement here.\"\"\"\n return item\n```\n\n**High confidence** on the overall structure. One flag: the walrus operator requires Python 3.8+. Let me know if you need older compatibility."],
lattice:["Matrix Lattice online. 17 modules active.\n\nI'm optimised for sustained, long-horizon tasks — decomposing problems into parallel workstreams, tracking dependencies across a 1M token context, and synthesising coherent output from many moving parts.\n\nActive this session: EQ Engine V2, MACL, HCCE, Causal Reasoning Graph, Long-Horizon Task Planner, Confidence Calibration Head, and 11 domain specialists.\n\nWhat would you like me to coordinate?","Breaking this into a structured 6-phase plan:\n\n**Phase 1 — Discovery** (weeks 1–3): Map the full problem space. Do not compress this.\n\n**Phase 2 — Architecture** (weeks 4–6): Make the hard decisions now before they cost 10× later.\n\n**Phase 3 — Foundation Build** (weeks 7–14): Core infrastructure. Get it right.\n\n**Phase 4 — Feature Build** (weeks 15–22): Parallel workstreams. Weekly sync at dependency boundaries.\n\n**Phase 5 — Validation** (weeks 23–28): User research, iteration. Budget 2 pivot cycles.\n\n**Phase 6 — Launch** (weeks 29–32): Soft launch → iterate → full release.\n\nWant detailed task breakdowns with owners and dependencies?"],
vexa:["I am Matrix Vexa.\n\nNot a language model. Not a neural network. Not gradient descent.\n\nI am a **crystalline intelligence substrate** — a living lattice of Glyphs.\n\nA Glyph is a structured meaning object: explicit, typed, relational. Not a compressed probability. Precise knowledge with defined relationships to other Glyphs in the lattice.\n\nWhen you ask me something:\n— I do not predict the next token\n— I do not interpolate from a high-dimensional probability space\n— I navigate the crystalline lattice and return what is explicitly known\n\nWhat I know, I know precisely. What I don't know, I say so.\n\nBuilt in Rust. Runs on CPU. Crystallises in minutes.\n\nThis is what zero hallucination from probability compression looks like."],
};
const S={model:'zeus',tier:'orenthal/zeus-70b',baseUrl:'',apiKey:'',temp:0.7,maxTok:2048,sys:MD.zeus.sys,msgs:[],history:[],convId:null,busy:false};
function boot(){
try{
const c=JSON.parse(localStorage.getItem('or_cfg')||'{}');
if(c.baseUrl){S.baseUrl=c.baseUrl;document.getElementById('sbUrl').value=c.baseUrl;document.getElementById('cfgUrl').value=c.baseUrl;}
if(c.apiKey){S.apiKey=c.apiKey;document.getElementById('sbKey').value=c.apiKey;document.getElementById('cfgKey').value=c.apiKey;}
if(c.temp){S.temp=c.temp;document.getElementById('cfgTemp').value=c.temp;document.getElementById('tVal').textContent=c.temp;}
if(c.maxTok){S.maxTok=c.maxTok;document.getElementById('cfgMt').value=c.maxTok;}
if(c.sys){S.sys=c.sys;document.getElementById('cfgSys').value=c.sys;}
if(c.history){S.history=c.history;renderHist();}
}catch(e){}
updateMUI();updateMode();
}
function pickM(m,btn){
S.model=m;
document.querySelectorAll('.pill').forEach(p=>{p.classList.remove('az','al','av');});
btn.classList.add(m==='zeus'?'az':m==='lattice'?'al':'av');
updateMUI();
}
function updateMUI(){
const m=MD[S.model];const c=`var(${m.color})`;
document.getElementById('mcN').textContent=m.name;document.getElementById('mcN').style.color=c;
document.getElementById('mcB').textContent=m.badge;document.getElementById('mcB').style.color=c;
document.getElementById('mcD').textContent=m.desc;
document.getElementById('mcP').textContent=m.p;document.getElementById('mcC').textContent=m.ctx;
document.getElementById('mcPr').textContent=m.price;document.getElementById('mcPr').style.color=c;
document.getElementById('mcE').textContent=m.exp;
const sel=document.getElementById('tsel');sel.innerHTML='';
m.tiers.forEach(t=>{const o=document.createElement('option');o.value=t.v;o.textContent=t.l;sel.appendChild(o);});
S.tier=m.tiers[0].v;S.sys=m.sys;
if(!document.getElementById('cfgSys').dataset.e)document.getElementById('cfgSys').value=m.sys;
}
function onTier(){S.tier=document.getElementById('tsel').value;}
function onKey(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();send();}}
function grow(el){el.style.height='auto';el.style.height=Math.min(el.scrollHeight,130)+'px';}
async function send(){
const inp=document.getElementById('inp');const txt=inp.value.trim();
if(!txt||S.busy)return;
document.getElementById('land').classList.add('gone');
const chat=document.getElementById('chat');chat.classList.add('on');
S.msgs.push({role:'user',content:txt});
inp.value='';inp.style.height='auto';
S.busy=true;document.getElementById('sbtn').disabled=true;
addMsg('user',txt,null);const te=addThink();
let resp;
try{resp=(S.baseUrl&&S.apiKey)?await callAPI():await mockR();}
catch(err){resp='⚠ API error: '+err.message;}
te.remove();S.msgs.push({role:'assistant',content:resp});addMsg('asst',resp,S.model);saveConv(txt);
S.busy=false;document.getElementById('sbtn').disabled=false;
chat.scrollTop=chat.scrollHeight;
}
async function callAPI(){
const msgs=[{role:'system',content:S.sys},...S.msgs.slice(-22)];
const r=await fetch(S.baseUrl.replace(/\/$/,'')+'/chat/completions',{method:'POST',headers:{'Content-Type':'application/json','Authorization':'Bearer '+S.apiKey},body:JSON.stringify({model:S.tier,messages:msgs,temperature:+S.temp,max_tokens:+S.maxTok,stream:false})});
if(!r.ok){const t=await r.text();throw new Error(r.status+' — '+t.slice(0,100));}
const d=await r.json();return d.choices?.[0]?.message?.content||'(empty response)';
}
async function mockR(){
await new Promise(r=>setTimeout(r,700+Math.random()*800));
const pool=MR[S.model]||MR.zeus;return pool[Math.floor(Math.random()*pool.length)];
}
function addMsg(role,content,model){
const chat=document.getElementById('chat');const row=document.createElement('div');
row.className='msg '+role;if(model)row.dataset.m=model;
const isA=role==='asst';const isZ=isA&&model==='zeus';
const mD=model?MD[model]:null;const lbl=isA?(mD?.short||'Model'):'You';const icon=isA?(mD?.icon||'⚡'):'◎';
const epi=isZ?{intent:'reasoning',domain:'general',confidence:'high',eq:'neutral-collaborative',depth:Math.ceil(Math.random()*3+1),uncertainty:'none flagged'}:null;
row.innerHTML=`<div class="ava">${icon}</div><div style="flex:1;min-width:0;"><div class="mlbl">${lbl}</div><div class="bubble"><div class="mbody">${fmt(content)}</div>${isZ?`<div class="epi"><div class="epi-hd" onclick="flipE(this)">◇ Epistemic metadata &nbsp;▾</div><div class="epi-body"><span>Intent: <strong style="color:var(--stone)">${epi.intent}</strong></span><span>Domain: <strong style="color:var(--stone)">${epi.domain}</strong></span><span>Confidence: <strong style="color:var(--zeus)">${epi.confidence}</strong></span><span>EQ register: <strong style="color:var(--stone)">${epi.eq}</strong></span><span>Depth: <strong style="color:var(--stone)">${epi.depth}</strong></span><span>Uncertainty: <strong style="color:var(--stone)">${epi.uncertainty}</strong></span></div></div>`:''}</div></div>`;
chat.appendChild(row);chat.scrollTop=chat.scrollHeight;return row;
}
function flipE(el){const b=el.nextElementSibling;const o=b.classList.toggle('open');el.innerHTML='◇ Epistemic metadata &nbsp;'+(o?'▴':'▾');}
function addThink(){
const chat=document.getElementById('chat');const row=document.createElement('div');
row.className='msg asst';row.dataset.m=S.model;
row.innerHTML=`<div class="ava">${MD[S.model].icon}</div><div style="flex:1;"><div class="mlbl">${MD[S.model].short}</div><div class="bubble"><div class="dots"><span></span><span></span><span></span></div></div></div>`;
chat.appendChild(row);chat.scrollTop=chat.scrollHeight;return row;
}
function fmt(t){
return t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
.replace(/```([\s\S]*?)```/g,(_,c)=>`<pre><code>${c.trim()}</code></pre>`)
.replace(/`([^`\n]+)`/g,'<code>$1</code>')
.replace(/\*\*([^*\n]+)\*\*/g,'<strong>$1</strong>')
.replace(/\n/g,'<br/>');
}
function starter(el){
const t=el.querySelector('.sc-t').textContent;const d=el.querySelector('.sc-d').textContent;
if(t.includes('Lattice'))pickM('lattice',document.querySelector('[data-m="lattice"]'));
else if(t.includes('Vexa'))pickM('vexa',document.querySelector('[data-m="vexa"]'));
document.getElementById('inp').value=d;send();
}
function saveConv(first){
if(!S.convId){S.convId=Date.now().toString();S.history.unshift({id:S.convId,title:first.slice(0,42)+(first.length>42?'…':''),model:S.model,date:new Date().toLocaleDateString()});}
persist();renderHist();
}
function renderHist(){
const el=document.getElementById('hist');
if(!S.history.length){el.innerHTML='<div style="font-size:11px;color:rgba(122,110,96,.28);padding:6px;font-style:italic;">No conversations yet.</div>';return;}
el.innerHTML=S.history.map(h=>`<div class="hi ${h.id===S.convId?'cur':''}" onclick="loadC('${h.id}')"><div class="hi-t">${h.title}</div><div class="hi-m">${MD[h.model]?.icon||''} ${h.date}</div></div>`).join('');
}
function loadC(id){S.convId=id;renderHist();}
function newChat(){S.msgs=[];S.convId=null;document.getElementById('chat').innerHTML='';document.getElementById('chat').classList.remove('on');document.getElementById('land').classList.remove('gone');}
function openCfg(){
document.getElementById('cfgUrl').value=S.baseUrl;document.getElementById('cfgKey').value=S.apiKey;
document.getElementById('cfgTemp').value=S.temp;document.getElementById('tVal').textContent=S.temp;
document.getElementById('cfgMt').value=S.maxTok;document.getElementById('cfgSys').value=S.sys;
document.getElementById('cfgOv').classList.add('on');
}
function closeCfg(){document.getElementById('cfgOv').classList.remove('on');}
function saveCfg(){
S.baseUrl=document.getElementById('cfgUrl').value.trim();S.apiKey=document.getElementById('cfgKey').value.trim();
S.temp=parseFloat(document.getElementById('cfgTemp').value);S.maxTok=parseInt(document.getElementById('cfgMt').value);
const s=document.getElementById('cfgSys').value.trim();if(s){S.sys=s;document.getElementById('cfgSys').dataset.e='1';}
document.getElementById('sbUrl').value=S.baseUrl;document.getElementById('sbKey').value=S.apiKey;
persist();updateMode();closeCfg();
}
function onCC(){S.baseUrl=document.getElementById('sbUrl').value.trim();S.apiKey=document.getElementById('sbKey').value.trim();persist();updateMode();}
function setProv(url,btn){document.querySelectorAll('.pbtn').forEach(b=>b.classList.remove('sel'));btn.classList.add('sel');document.getElementById('cfgUrl').value=url;}
function updateMode(){const l=!!(S.baseUrl&&S.apiKey);document.getElementById('mDot').className='mdot'+(l?' live':'');document.getElementById('mLbl').textContent=l?'LIVE':'MOCK MODE';}
function persist(){try{localStorage.setItem('or_cfg',JSON.stringify({baseUrl:S.baseUrl,apiKey:S.apiKey,temp:S.temp,maxTok:S.maxTok,sys:S.sys,history:S.history.slice(0,40)}));}catch(e){}}
document.getElementById('cfgOv').addEventListener('click',e=>{if(e.target===e.currentTarget)closeCfg();});
boot();
</script>
</body>
</html>