← back to Ken
auto-save: 2026-07-15T12:06:24 (1 files) — kalshi-dash/risk-knob.html
4d35550184e8a19c47b098d329cacf26e5844c7a · 2026-07-15 12:06:33 -0700 · Steve Abrams
Files touched
A kalshi-dash/risk-knob.html
Diff
commit 4d35550184e8a19c47b098d329cacf26e5844c7a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Jul 15 12:06:33 2026 -0700
auto-save: 2026-07-15T12:06:24 (1 files) — kalshi-dash/risk-knob.html
---
kalshi-dash/risk-knob.html | 174 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 174 insertions(+)
diff --git a/kalshi-dash/risk-knob.html b/kalshi-dash/risk-knob.html
new file mode 100644
index 0000000..e7a2c97
--- /dev/null
+++ b/kalshi-dash/risk-knob.html
@@ -0,0 +1,174 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Ken · Risk Level Knob</title>
+<style>
+ :root{ --bg:#0a0e14; --panel:#0f1622; --ink:#e6edf3; --muted:#7d8da3; --cyan:#22d3ee; }
+ *{box-sizing:border-box}
+ html,body{margin:0;height:100%}
+ body{background:radial-gradient(1200px 700px at 50% -10%,#12202e 0%,var(--bg) 60%);
+ color:var(--ink);font:15px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,sans-serif;
+ display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;gap:22px;overflow:hidden}
+ h1{font-size:13px;letter-spacing:3px;color:var(--muted);text-transform:uppercase;margin:0;font-weight:700}
+ .stage{position:relative;width:340px;height:340px;display:grid;place-items:center;touch-action:none;user-select:none;cursor:grab}
+ .stage:active{cursor:grabbing}
+ svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}
+ /* ambient glow behind the knob */
+ .halo{position:absolute;width:250px;height:250px;border-radius:50%;filter:blur(38px);opacity:.55;
+ transition:background .6s ease;animation:breathe 3.4s ease-in-out infinite}
+ @keyframes breathe{0%,100%{transform:scale(.96);opacity:.42}50%{transform:scale(1.04);opacity:.6}}
+ /* knob face */
+ .knob{position:absolute;width:190px;height:190px;border-radius:50%;
+ background:radial-gradient(120px 120px at 38% 30%,#1c2836,#0c131c 70%);
+ border:1px solid rgba(255,255,255,.08);
+ box-shadow:0 18px 40px rgba(0,0,0,.55),inset 0 2px 6px rgba(255,255,255,.06),inset 0 -18px 30px rgba(0,0,0,.5);
+ display:grid;place-items:center;transition:transform .05s linear}
+ .knob::before{content:"";position:absolute;inset:14px;border-radius:50%;
+ background:conic-gradient(from 0deg,rgba(255,255,255,.03),rgba(255,255,255,0) 25%,rgba(255,255,255,.05) 50%,rgba(255,255,255,0) 75%,rgba(255,255,255,.03))}
+ /* pointer notch that rotates with the knob */
+ .pointer{position:absolute;top:12px;left:50%;width:6px;height:34px;border-radius:4px;margin-left:-3px;
+ background:linear-gradient(#fff,#9fe8ff);box-shadow:0 0 14px var(--cyan),0 0 4px #fff}
+ /* center readout (counter-rotated so it stays upright) */
+ .readout{position:absolute;text-align:center;pointer-events:none}
+ .val{font-size:62px;font-weight:800;letter-spacing:-1px;line-height:1;font-variant-numeric:tabular-nums;
+ text-shadow:0 0 22px rgba(34,211,238,.25)}
+ .unit{font-size:12px;color:var(--muted);letter-spacing:2px;margin-top:2px}
+ .risk{margin-top:8px;font-size:13px;font-weight:800;letter-spacing:2px;transition:color .5s ease}
+ .hint{font-size:12px;color:var(--muted);max-width:420px;text-align:center}
+ .row{display:flex;gap:10px;align-items:center}
+ button{background:#13202e;color:var(--ink);border:1px solid rgba(255,255,255,.14);border-radius:10px;
+ padding:9px 16px;font-size:13px;font-weight:600;letter-spacing:.4px;cursor:pointer;transition:.15s}
+ button:hover{border-color:var(--cyan);color:var(--cyan)}
+ .cmd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:#9fe8ff;
+ background:#0c1420;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:8px 12px;letter-spacing:.2px}
+ .legend{display:flex;gap:16px;font-size:11px;color:var(--muted);letter-spacing:.5px}
+ .legend b{display:inline-block;width:9px;height:9px;border-radius:50%;margin-right:5px;vertical-align:middle}
+</style>
+</head>
+<body>
+ <h1>Ken · Risk Level</h1>
+
+ <div class="stage" id="stage">
+ <div class="halo" id="halo"></div>
+ <!-- arc gauge -->
+ <svg viewBox="0 0 340 340" aria-hidden="true">
+ <defs>
+ <linearGradient id="arc" x1="0" y1="1" x2="1" y2="0">
+ <stop offset="0" stop-color="#ef4444"/>
+ <stop offset=".38" stop-color="#f59e0b"/>
+ <stop offset=".62" stop-color="#eab308"/>
+ <stop offset="1" stop-color="#22c55e"/>
+ </linearGradient>
+ </defs>
+ <!-- track -->
+ <path id="track" fill="none" stroke="rgba(255,255,255,.07)" stroke-width="10" stroke-linecap="round"/>
+ <!-- value arc -->
+ <path id="fill" fill="none" stroke="url(#arc)" stroke-width="10" stroke-linecap="round"
+ style="filter:drop-shadow(0 0 6px rgba(34,211,238,.35))"/>
+ <g id="ticks" stroke="rgba(255,255,255,.18)" stroke-width="2"></g>
+ </svg>
+
+ <div class="knob" id="knob"><div class="pointer"></div></div>
+ <div class="readout">
+ <div class="val" id="val">75</div>
+ <div class="unit">MIN CONFIDENCE</div>
+ <div class="risk" id="risk">BALANCED</div>
+ </div>
+ </div>
+
+ <div class="legend">
+ <span><b style="background:#ef4444"></b>50–64 High risk</span>
+ <span><b style="background:#f59e0b"></b>65–74 Elevated</span>
+ <span><b style="background:#eab308"></b>75–84 Balanced</span>
+ <span><b style="background:#22c55e"></b>85–99 Conservative</span>
+ </div>
+
+ <div class="hint" id="hint">Drag the knob to set how selective Ken is. Higher = fewer, higher-conviction real trades (lower risk). Lower = more trades on thinner edges (higher risk).</div>
+
+ <div class="row">
+ <button id="demo">▶ Demo sweep</button>
+ <span class="cmd" id="cmd">set-confidence.sh 75</span>
+ </div>
+
+<script>
+(() => {
+ // gauge geometry: 270° arc, from 135° (bottom-left) sweeping clockwise to 45° (bottom-right)
+ const MIN=50, MAX=99, A0=135, A1=405; // degrees (A1=45+360)
+ const CX=170, CY=170, R=132;
+ const rad = d => (d-90) * Math.PI/180;
+ const ptOn = (d,r=R) => [CX + r*Math.cos(rad(d)), CY + r*Math.sin(rad(d))];
+ const arcPath = (from,to,r=R) => {
+ const [x0,y0]=ptOn(from,r), [x1,y1]=ptOn(to,r);
+ const large = (to-from) > 180 ? 1 : 0;
+ return `M${x0} ${y0} A${r} ${r} 0 ${large} 1 ${x1} ${y1}`;
+ };
+ const val2ang = v => A0 + (v-MIN)/(MAX-MIN)*(A1-A0);
+
+ document.getElementById('track').setAttribute('d', arcPath(A0, A1));
+ // ticks
+ const ticks=document.getElementById('ticks');
+ for(let v=MIN; v<=MAX; v+=(v%5===0?5:5)){ if(v%5) continue;
+ const a=val2ang(v); const [x0,y0]=ptOn(a,R+9),[x1,y1]=ptOn(a, v%25===0? R+20 : R+15);
+ const ln=document.createElementNS('http://www.w3.org/2000/svg','line');
+ ln.setAttribute('x1',x0);ln.setAttribute('y1',y0);ln.setAttribute('x2',x1);ln.setAttribute('y2',y1);
+ ticks.appendChild(ln);
+ }
+
+ const fill=document.getElementById('fill'), knob=document.getElementById('knob'),
+ valEl=document.getElementById('val'), riskEl=document.getElementById('risk'),
+ halo=document.getElementById('halo'), cmd=document.getElementById('cmd');
+
+ const zone = v => v<65 ? {t:'HIGH RISK',c:'#ef4444'} : v<75 ? {t:'ELEVATED',c:'#f59e0b'}
+ : v<85 ? {t:'BALANCED',c:'#eab308'} : {t:'CONSERVATIVE',c:'#22c55e'};
+
+ let cur=75;
+ function render(v){
+ v=Math.round(v);
+ const a=val2ang(v);
+ fill.setAttribute('d', arcPath(A0, a));
+ knob.style.transform = `rotate(${a-270}deg)`; // pointer starts at top (270°→0 offset)
+ valEl.textContent=v;
+ const z=zone(v); riskEl.textContent=z.t; riskEl.style.color=z.c;
+ halo.style.background=`radial-gradient(circle,${z.c}66,transparent 70%)`;
+ cmd.textContent=`set-confidence.sh ${v}`;
+ }
+ render(cur);
+
+ // ── entrance "motion graphic": needle sweeps min→current with ease-out ──
+ function sweep(to, from=MIN, dur=1400){
+ const t0=performance.now();
+ (function step(now){
+ const t=Math.min(1,(now-t0)/dur), e=1-Math.pow(1-t,3);
+ render(from + (to-from)*e);
+ if(t<1) requestAnimationFrame(step); else { cur=to; render(cur); }
+ })(t0);
+ }
+ requestAnimationFrame(()=>sweep(cur));
+ document.getElementById('demo').onclick=()=>{ sweep(cur, MIN, 1300); };
+
+ // ── drag to turn ──
+ const stage=document.getElementById('stage');
+ let dragging=false;
+ const angOf = (cx,cy,x,y) => { let d=Math.atan2(y-cy, x-cx)*180/Math.PI + 90; if(d<0)d+=360; return d; };
+ function fromEvent(ev){
+ const r=stage.getBoundingClientRect();
+ const cx=r.left+r.width/2, cy=r.top+r.height/2;
+ const p = ev.touches ? ev.touches[0] : ev;
+ let a=angOf(cx,cy,p.clientX,p.clientY);
+ // map pointer angle onto the 135→405 sweep
+ if(a<A0-10 && a<90) a+=360;
+ a=Math.max(A0,Math.min(A1,a));
+ const v=MIN+(a-A0)/(A1-A0)*(MAX-MIN);
+ cur=v; render(v);
+ }
+ const down=e=>{dragging=true; fromEvent(e); e.preventDefault();};
+ const move=e=>{ if(dragging) fromEvent(e); };
+ const up=()=>dragging=false;
+ stage.addEventListener('mousedown',down); window.addEventListener('mousemove',move); window.addEventListener('mouseup',up);
+ stage.addEventListener('touchstart',down,{passive:false}); window.addEventListener('touchmove',move,{passive:false}); window.addEventListener('touchend',up);
+})();
+</script>
+</body>
+</html>
← 0331471 Ken: set-confidence.sh fails loud (exit 1 + stderr) on any n
·
back to Ken
·
Ken: live Risk Level knob in Settings — drag to preview, App 5a71f56 →