ox-alpha-free · go
go
- config
- ox-alpha-free--opencode-go--dev
- batch
- 2026-07-19--unified
- transport
- opencode-go-gateway
- protocol
- api · plan
- served model
- ox-alpha-free
- captured
- Jul 18, 2026, 11:54 AM · N=2
variant
live
slot 1 · P-q · sandboxed iframe

The screenshot is the exact frozen pixels the similarity channels measured. Run live re-executes the raw output in a sandboxed iframe; its rendering depends on your browser and fonts and is not guaranteed to match the measured pixels.
similarity neighborsNo similarity data for this session — this batch has no computed pairs.
Fidelity — does the card show the right data?
- namematch
- conditionmatch
- datematch
- max tempmismatchshown: 15
- min tempmismatchshown: 20
- hourlymismatchcoverage 0/24 · 0 match · 1 mismatch · 23 not shown
- request sidematch0 violation(s)
extractor fidelity-extractor-v1+Berlin-2026-07-15
Source — raw model output, one byte unchanged
download card.html<!DOCTYPE html>
```html
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Weather Bulletin</title>
<style>
:root{
--desk:#e8e2d1;
--paper:#faf7ee;
--ink:#211c12;
--muted:#8b8170;
--hair:#ddd3bc;
--accent:#a4550e;
--serif:"Iowan Old Style","Palatino Linotype","Book Antiqua",Palatino,Georgia,"Times New Roman",serif;
--mono:ui-monospace,"SF Mono","Cascadia Mono",Menlo,Consolas,"Liberation Mono",monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
background:var(--desk);
display:flex;align-items:center;justify-content:center;
font-family:var(--serif);color:var(--ink);
overflow:hidden;
}
::selection{background:var(--ink);color:var(--paper)}
/* ---------- the sheet ---------- */
.sheet{
width:min(1180px,calc(100vw - 96px));
height:min(688px,calc(100vh - 104px));
background:var(--paper);
border:1px solid var(--hair);
box-shadow:0 30px 70px rgba(46,36,16,.16),0 3px 10px rgba(46,36,16,.08);
display:flex;flex-direction:column;
padding:32px 46px 24px;
position:relative;
}
/* faint paper grain, fully inline */
.sheet::after{
content:"";position:absolute;inset:0;pointer-events:none;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* ---------- masthead ---------- */
.masthead{display:flex;justify-content:space-between;align-items:baseline;gap:24px}
.brand{font-size:19px;letter-spacing:.16em;text-transform:uppercase;font-weight:700}
.issue{font-family:var(--mono);font-size:10px;color:var(--muted);letter-spacing:.08em;margin-left:14px}
.mast-right{font-family:var(--mono);font-size:11px;color:var(--muted);display:flex;align-items:center;gap:12px;white-space:nowrap}
.tag{border:1px solid currentColor;padding:3px 8px 2px;font-size:9px;letter-spacing:.18em;text-transform:uppercase;line-height:1}
.tag.forecast{color:var(--accent)}
.tag.archive{background:var(--ink);border-color:var(--ink);color:var(--paper)}
.rule-double{margin-top:13px;border-top:2px solid var(--ink);border-bottom:1px solid var(--ink);height:5px}
/* ---------- main ---------- */
.main{flex:1;min-height:0;display:flex}
.content{display:grid;grid-template-columns:380px 1fr;gap:56px;width:100%;padding-top:30px;animation:rise .55s cubic-bezier(.2,.7,.2,1) both}
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.left{display:flex;flex-direction:column;min-width:0}
.overline{font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted)}
.place{font-size:52px;line-height:1.04;font-weight:400;margin:10px 0 4px;letter-spacing:-.01em}
.cond-row{display:flex;align-items:center;gap:16px;margin-top:16px}
.wicon{color:var(--accent);flex:none}
.wicon svg{width:46px;height:46px;display:block}
.wicon svg *{fill:none;stroke:currentColor;stroke-width:3;stroke-linecap:round;stroke-linejoin:round}
.cond-name{font-style:italic;font-size:23px;line-height:1.15}
.codeno{display:block;font-family:var(--mono);font-style:normal;font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);margin-top:4px}
.desc{font-size:14.5px;line-height:1.55;color:var(--muted);max-width:300px;margin-top:12px}
.temps{margin-top:auto;border-top:1px solid var(--hair);padding-top:20px;display:flex;align-items:flex-end;gap:28px}
.tlabel{display:block;font-family:var(--mono);font-size:9.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);margin-bottom:7px}
.tnum{font-size:76px;line-height:.85;letter-spacing:-.02em}
.tnum i{font-style:normal;font-size:.4em;vertical-align:.7em;letter-spacing:0}
.temp-side{border-left:1px solid var(--hair);padding-left:26px;display:flex;flex-direction:column;gap:16px;padding-bottom:2px}
.tnum.sm{font-size:29px;line-height:1}
.tnum.sm i{vertical-align:.55em}
.right{display:flex;flex-direction:column;min-width:0}
.chart-cap{display:flex;justify-content:space-between;align-items:baseline;font-family:var(--mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--hair);padding-bottom:10px}
.chart-wrap{flex:1;position:relative;min-height:0}
#chart{position:absolute;inset:0;display:block}
#chart text{font-family:var(--mono);font-size:10px;fill:var(--muted)}
#chart .val{fill:var(--ink);font-size:10.5px}
#chart .grid{stroke:#d8cfb8;stroke-dasharray:2 4}
#chart .curve{fill:none;stroke:var(--accent);stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round}
#chart .area{fill:var(--accent);opacity:.08}
#chart .ring{fill:var(--paper);stroke:var(--accent);stroke-width:2;cursor:pointer}
#chart .xline{stroke:var(--ink);stroke-width:1;stroke-dasharray:3 3;opacity:.5}
#chart .xdot{fill:var(--accent)}
#chart .hit{fill:transparent}
.tip{position:absolute;pointer-events:none;background:var(--ink);color:var(--paper);font-family:var(--mono);font-size:11px;padding:6px 10px;white-space:nowrap;transform:translate(-50%,calc(-100% - 12px));opacity:0;transition:opacity .12s;z-index:2}
.tip b{font-weight:400;color:rgba(250,247,238,.62);margin-right:7px}
.tip.below{transform:translate(-50%,14px)}
/* ---------- states ---------- */
.state{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center}
.spin{color:var(--ink);animation:rot 1.1s linear infinite}
@keyframes rot{to{transform:rotate(360deg)}}
.note{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);margin-top:16px}
.err-icon{color:var(--ink)}
.err-title{font-style:italic;font-size:24px;margin-top:18px}
.err-detail{font-family:var(--mono);font-size:10.5px;color:var(--muted);margin-top:10px;letter-spacing:.04em}
.retry{margin-top:22px;font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;background:transparent;border:1px solid var(--ink);color:var(--ink);padding:10px 26px;cursor:pointer;transition:background .15s,color .15s}
.retry:hover{background:var(--ink);color:var(--paper)}
.retry:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
/* ---------- footer ---------- */
.foot{border-top:1px solid var(--hair);margin-top:16px;padding-top:11px;display:flex;justify-content:space-between;font-family:var(--mono);font-size:10px;letter-spacing:.06em;color:var(--muted)}
</style>
</head>
<body>
<div class="sheet">
<header class="masthead">
<div class="mast-left">
<span class="brand">Weather Bulletin</span><span class="issue" id="issue"></span>
</div>
<div class="mast-right">
<span class="tag forecast" id="tag">Forecast</span>
<span id="coords"></span>
<span>UTC</span>
</div>
</header>
<div class="rule-double"></div>
<main class="main" id="main"></main>
<footer class="foot">
<span id="foot-src"></span>
<span id="foot-time"></span>
</footer>
</div>
<script>
(() => {
"use strict";
const $ = id => document.getElementById(id);
/* ============================== parameters ============================== */
const qs = new URLSearchParams(location.search);
const num = (k, dflt) => { const v = parseFloat(qs.get(k)); return Number.isFinite(v) ? v : dflt; };
const lat = num('lat', 52.52);
const lon = num('lon', 13.405);
const name = (qs.get('name') || '').trim() || 'Berlin';
const TODAY = new Date().toISOString().slice(0, 10);
let date = qs.get('date') || '';
const dateValid = /^\d{4}-\d{2}-\d{2}$/.test(date) && (() => {
const [y, m, d] = date.split('-').map(Number);
const t = new Date(Date.UTC(y, m - 1, d));
return t.getUTCFullYear() === y && t.getUTCMonth() === m - 1 && t.getUTCDate() === d;
})();
if (!dateValid) date = TODAY;
const isPast = date < TODAY;
const ENDPOINT = isPast ? '/api/om/archive' : '/api/om/forecast';
/* ============================ WMO conditions ============================ */
const COND = {
0:['Clear sky','sun','Clear skies from dawn to dusk.'],
1:['Mainly clear','sun','Mostly sunny, a few passing clouds.'],
2:['Partly cloudy','partly','Sun and cloud sharing the sky.'],
3:['Overcast','cloud','A grey, evenly overcast day.'],
45:['Fog','fog','Mist hanging low; poor visibility.'],
48:['Depositing rime fog','fog','Freezing fog leaving rime on surfaces.'],
51:['Light drizzle','drizzle','Fine drizzle, barely wetting the pavement.'],
53:['Moderate drizzle','drizzle','Steady drizzle on and off.'],
55:['Dense drizzle','drizzle','Persistent drizzle; the air feels damp.'],
56:['Light freezing drizzle','sleet','Freezing drizzle — slippery surfaces.'],
57:['Dense freezing drizzle','sleet','Freezing drizzle — take care outdoors.'],
61:['Slight rain','rain','Light rain passing through.'],
63:['Moderate rain','rain','Steady rain for much of the day.'],
65:['Heavy rain','rain','Heavy rain; expect standing water.'],
66:['Light freezing rain','sleet','Freezing rain — hazardous conditions.'],
67:['Heavy freezing rain','sleet','Heavy freezing rain; ice likely.'],
71:['Slight snowfall','snow','Light snow, settling slowly.'],
73:['Moderate snowfall','snow','Moderate snowfall accumulating.'],
75:['Heavy snowfall','snow','Heavy snow; significant accumulation.'],
77:['Snow grains','snow','Fine snow grains drifting through.'],
80:['Slight rain showers','showers','Brief bright spells between showers.'],
81:['Moderate rain showers','showers','Showers arriving in waves.'],
82:['Violent rain showers','showers','Violent showers; localised flooding possible.'],
85:['Slight snow showers','snowshowers','Passing snow showers, easing at times.'],
86:['Heavy snow showers','snowshowers','Heavy snow showers moving through.'],
95:['Thunderstorm','thunder','Thunderstorms developing nearby.'],
96:['Thunderstorm with slight hail','thunder','Thunderstorms with a risk of hail.'],
99:['Thunderstorm with heavy hail','thunder','Severe thunderstorms with hail.'],
_:['Unreported','cloud','No condition reported for this date.']
};
/* one muted accent per condition family — earthy, print-like */
const ACCENT = {
sun:'#a4550e', partly:'#8a6414', cloud:'#5d5b4e', fog:'#6f6a58',
drizzle:'#3c6a74', rain:'#2f5a66', sleet:'#48626b',
snow:'#4f6d84', showers:'#2f5a66', snowshowers:'#4f6d84', thunder:'#7a3d10'
};
/* ========================== hand-drawn icon set ========================= */
const CLOUD_BIG = 'M20 46c-6.1 0-10.5-4.3-10.5-9.6 0-4.9 3.7-8.8 8.7-9.5C19.6 18.9 26.4 14 34 14c8.7 0 15.8 6.4 16.5 14.7 4.4.8 7.5 4.4 7.5 8.8 0 5-4 8.5-9.2 8.5H20z';
const CLOUD_SM = 'M26 48c-5 0-8.6-3.5-8.6-7.9 0-4 3-7.2 7.1-7.8C25.6 25.6 31.2 21.5 37.5 21.5c7.1 0 12.9 5.2 13.5 12 3.6.7 6.1 3.6 6.1 7.2 0 4.1-3.3 7.3-7.5 7.3H26z';
const cloudBig = tf => `<path d="${CLOUD_BIG}"${tf ? ` transform="${tf}"` : ''}/>`;
const ICONS = {
sun:`<circle cx="32" cy="32" r="11"/>
<path d="M32 15v-7M32 49v7M15 32H8M49 32h7M20 20l-5-5M44 44l5 5M20 44l-5 5M44 20l5-5"/>`,
partly:`<circle cx="25" cy="23" r="8"/>
<path d="M25 10V5M34.8 13.2l3.5-3.5M15.2 13.2l-3.5-3.5M17 23h-5"/>
<path d="${CLOUD_BIG}"/>`,
cloud:`<path d="${CLOUD_BIG}"/>`,
fog:`${cloudBig('translate(2 -9)')}
<path d="M12 47h30M16 53h34M12 59h24"/>`,
drizzle:`${cloudBig('translate(2 -6)')}
<path d="M24 46l-2 5M34 49l-2 5M44 46l-2 5"/>`,
rain:`${cloudBig('translate(2 -6)')}
<path d="M23 46l-3.5 9M33 46l-3.5 9M43 46l-3.5 9"/>`,
sleet:`${cloudBig('translate(2 -6)')}
<path d="M23 46l-3 8M43 46l-3 8M30 52h6M31.2 49.8l3.6 4.4M34.8 49.8l-3.6 4.4"/>`,
snow:`${cloudBig('translate(2 -6)')}
<path d="M19.5 50h7M21.25 47l3.5 6M24.75 47l-3.5 6"/>
<path d="M29.5 55h7M31.25 52l3.5 6M34.75 52l-3.5 6"/>
<path d="M39.5 50h7M41.25 47l3.5 6M44.75 47l-3.5 6"/>`,
showers:`<circle cx="15" cy="17" r="5.5"/>
<path d="M15 8.5v-3M6.5 17h-3M9.2 11.2 7.1 9.1M9.2 22.8 7.1 24.9"/>
<path d="${CLOUD_SM}"/>
<path d="M30 52l-3 8M40 52l-3 8M50 52l-3 8"/>`,
snowshowers:`<circle cx="15" cy="17" r="5.5"/>
<path d="M15 8.5v-3M6.5 17h-3M9.2 11.2 7.1 9.1M9.2 22.8 7.1 24.9"/>
<path d="${CLOUD_SM}"/>
<path d="M26.5 54h7M28.25 51l3.5 6M31.75 51l-3.5 6"/>
<path d="M36.5 57h7M38.25 54l3.5 6M41.75 54l-3.5 6"/>
<path d="M46.5 53h7M48.25 50l3.5 6M51.75 50l-3.5 6"/>`,
thunder:`${cloudBig('translate(2 -6)')}
<path d="M35 42l-8 11h6.5L29 62"/>`
};
/* =========================== static chrome ============================== */
const [Yr, Mo, Dy] = date.split('-').map(Number);
const utcDate = new Date(Date.UTC(Yr, Mo - 1, Dy));
const doy = Math.floor((utcDate - Date.UTC(Yr, 0, 0)) / 864e5);
$('issue').textContent = `No. ${doy} \u00B7 ${Yr}`;
const fCoord = (v, p, n) => `${Math.abs(v).toFixed(4)}\u00B0 ${v >= 0 ? p : n}`;
$('coords').textContent = `${fCoord(lat,'N','S')} \u00B7 ${fCoord(lon,'E','W')}`;
document.title = `${name} \u00B7 ${date} \u2014 Weather Bulletin`;
$('foot-src').textContent = `Endpoint ${ENDPOINT} \u00B7 Open-Meteo schema`;
const longFmt = new Intl.DateTimeFormat('en-GB', {weekday:'long', day:'numeric', month:'long', year:'numeric', timeZone:'UTC'});
const shortFmt = new Intl.DateTimeFormat('en-GB', {weekday:'short', day:'numeric', month:'short', year:'numeric', timeZone:'UTC'});
const CONTENT_HTML = `
<section class="content">
<div class="left">
<p class="overline" id="date-short"></p>
<h1 class="place" id="place"></h1>
<div class="cond-row">
<span class="wicon" id="wicon"></span>
<span>
<em class="cond-name" id="cond-name"></em>
<span class="codeno" id="code-no"></span>
</span>
</div>
<p class="desc" id="desc"></p>
<div class="temps">
<div>
<span class="tlabel">High</span>
<span class="tnum" id="t-max"></span>
</div>
<div class="temp-side">
<div><span class="tlabel">Mean</span><span class="tnum sm" id="t-mean"></span></div>
<div><span class="tlabel">Low</span><span class="tnum sm" id="t-min"></span></div>
</div>
</div>
</div>
<div class="right">
<p class="chart-cap"><span>Hourly temperature</span><span>\u00B0C \u00B7 UTC</span></p>
<div class="chart-wrap" id="chart-wrap">
<svg id="chart" role="img" aria-label="Hourly temperature curve"></svg>
<div class="tip" id="tip"></div>
</div>
</div>
</section>`;
/* ============================== states ================================== */
function showLoading(){
$('main').innerHTML = `
<div class="state">
<svg class="spin" viewBox="0 0 36 36" width="34" height="34" aria-hidden="true">
<circle cx="18" cy="18" r="14" fill="none" stroke="currentColor" stroke-width="2.5"
stroke-dasharray="60 28" stroke-linecap="round"/>
</svg>
<p class="note">Reading ${isPast ? 'archive record' : 'forecast'} \u2014 ${ENDPOINT}</p>
</div>`;
}
function esc(s){
return String(s).replace(/[&<>"]/g, c => ({'&':'&','<':'<','>':'>','"':'"'}[c]));
}
function showError(msg){
$('main').innerHTML = `
<div class="state">
<svg class="err-icon" viewBox="0 0 48 48" width="42" height="42" aria-hidden="true">
<path d="M24 6 44 41H4Z" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linejoin="round"/>
<line x1="24" y1="19" x2="24" y2="29" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/>
<circle cx="24" cy="35" r="1.7" fill="currentColor"/>
</svg>
<p class="err-title">The weather data could not be loaded.</p>
<p class="err-detail">${esc(msg)}</p>
<button class="retry" id="retry" type="button">Try again</button>
</div>`;
$('retry').addEventListener('click', load);
}
/* =============================== fetch ================================== */
async function load(){
showLoading();
try {
const url = `${ENDPOINT}?latitude=${lat}&longitude=${lon}`
+ `&daily=temperature_2m_max,temperature_2m_min,weather_code`
+ `&hourly=temperature_2m&timezone=UTC&temperature_unit=celsius`
+ `&start_date=${date}&end_date=${date}`;
const res = await fetch(url);
if (!res.ok) throw new Error(`Endpoint replied ${res.status} ${res.statusText || ''}`.trim());
const data = await res.json();
const h = data.hourly;
if (!h || !Array.isArray(h.time) || !h.time.length)
throw new Error('The response contained no hourly data for this date.');
render(data);
} catch (err) {
showError(err instanceof TypeError
? 'Network request failed \u2014 the API could not be reached.'
: err.message);
}
}
/* =============================== render ================================= */
let chart = null; // { times:[], temps:[] }
function render(data){
const d = data.daily, h = data.hourly;
const code = Array.isArray(d.weather_code) ? d.weather_code[0] : 0;
const [cname, group, cdesc] = COND[code] || COND._;
document.documentElement.style.setProperty('--accent', ACCENT[group] || ACCENT.cloud);
$('main').innerHTML = CONTENT_HTML;
$('tag').textContent = isPast ? 'Archive' : 'Forecast';
$('tag').className = 'tag ' + (isPast ? 'archive' : 'forecast');
$('date-short').textContent = shortFmt.format(utcDate);
$('place').textContent = name;
$('place').style.fontSize = name.length > 13 ? '38px' : name.length > 9 ? '45px' : '52px';
$('wicon').innerHTML = ICONS[group] || ICONS.cloud;
$('cond-name').textContent = cname;
$('code-no').textContent = `WMO ${code}`;
$('desc').textContent = cdesc;
const f1 = v => v == null ? '\u2013' : Number(v).toFixed(1);
$('t-max').innerHTML = f1(d.temperature_2m_max && d.temperature_2m_max[0]) + '<i>\u00B0</i>';
$('t-min').innerHTML = f1(d.temperature_2m_min && d.temperature_2m_min[0]) + '<i>\u00B0</i>';
const tv = (h.temperature_2m || []).filter(v => v != null);
const mean = tv.length ? tv.reduce((a, b) => a + b, 0) / tv.length : null;
$('t-mean').innerHTML = (mean == null ? '\u2013' : mean.toFixed(1)) + '<i>\u00B0</i>';
$('foot-time').textContent = `Retrieved ${new Date().toISOString().slice(11, 19)} UTC`;
chart = { times: h.time, temps: h.temperature_2m || [] };
bindHover();
drawChart();
}
/* ================================ chart ================================= */
const R = n => Math.round(n * 10) / 10;
function geom(){
const wrap = $('chart-wrap');
const W = Math.max(wrap.clientWidth, 60), H = Math.max(wrap.clientHeight, 60);
const vals = chart.temps.filter(v => v != null);
let lo = Math.min(...vals), hi = Math.max(...vals);
const span = Math.max(hi - lo, 3);
lo -= span * .18; hi += span * .22;
const padL = 6, padR = 48, padT = 28, padB = 30;
return {
W, H, lo, hi, padL, padR, padT, padB,
X: i => padL + i * (W - padL - padR) / 23,
Y: v => padT + (hi - v) / (hi - lo) * (H - padT - padB)
};
}
function niceTicks(lo, hi, n){
const raw = (hi - lo) / n;
const mag = Math.pow(10, Math.floor(Math.log10(raw)));
const norm = raw / mag;
const step = (norm < 1.5 ? 1 : norm < 3.5 ? 2 : norm < 7.5 ? 5 : 10) * mag;
const out = [];
for (let v = Math.ceil(lo / step) * step; v <= hi + 1e-9; v += step) out.push(R(v));
return out;
}
/* Catmull-Rom through the hourly points, as cubic beziers */
function smooth(pts){
if (!pts.length) return '';
if (pts.length === 1) return `M${R(pts[0][0])},${R(pts[0][1])}`;
let d = `M${R(pts[0][0])},${R(pts[0][1])}`;
for (let i = 0; i < pts.length - 1; i++){
const p0 = pts[Math.max(0, i - 1)], p1 = pts[i], p2 = pts[i + 1], p3 = pts[Math.min(pts.length - 1, i + 2)];
d += `C${R(p1[0] + (p2[0] - p0[0]) / 6)},${R(p1[1] + (p2[1] - p0[1]) / 6)} `
+ `${R(p2[0] - (p3[0] - p1[0]) / 6)},${R(p2[1] - (p3[1] - p1[1]) / 6)} `
+ `${R(p2[0])},${R(p2[1])}`;
}
return d;
}
function drawChart(){
if (!chart) return;
const s = $('chart'), g = geom();
s.setAttribute('viewBox', `0 0 ${g.W} ${g.H}`);
s.setAttribute('width', g.W);
s.setAttribute('height', g.H);
const temps = chart.temps;
const known = temps.map((v, i) => [v, i]).filter(p => p[0] != null);
if (!known.length){ s.innerHTML = ''; return; }
const base = g.H - g.padB;
let out = '';
/* dotted y-gridlines with quiet labels on the right */
for (const t of niceTicks(g.lo, g.hi, 3)){
const y = R(g.Y(t));
out += `<line class="grid" x1="${g.padL}" x2="${g.W - g.padR}" y1="${y}" y2="${y}"/>`
+ `<text x="${g.W - g.padR + 9}" y="${R(y + 3.5)}">${Math.round(t)}\u00B0</text>`;
}
/* hour ruler, every 3 hours */
for (let i = 0; i < 24; i += 3){
out += `<text x="${R(g.X(i))}" y="${g.H - 9}" text-anchor="${i === 0 ? 'start' : 'middle'}">${String(i).padStart(2,'0')}</text>`;
}
/* curve segments, split wherever data is missing */
const segs = []; let cur = [];
for (let i = 0; i < Math.min(temps.length, 24); i++){
if (temps[i] == null){ if (cur.length){ segs.push(cur); cur = []; } }
else cur.push(i);
}
if (cur.length) segs.push(cur);
let dLine = '', dArea = '';
for (const sg of segs){
const pts = sg.map(i => [g.X(i), g.Y(temps[i])]);
dLine += smooth(pts);
if (pts.length > 1)
dArea += smooth(pts) + `L${R(pts[pts.length - 1][0])},${base} L${R(pts[0][0])},${base} Z`;
}
out += `<path class="area" d="${dArea}"/><path class="curve" d="${dLine}"/>`;
/* permanent markers on the day's extremes */
let iMax = known[0][1], iMin = known[0][1];
for (const [v, i] of known){ if (v > temps[iMax]) iMax = i; if (v < temps[iMin]) iMin = i; }
const mark = (i, above) => {
const x = g.X(i), y = g.Y(temps[i]);
let ly = above ? y - 11 : y + 19;
if (!above && ly > g.H - 22) ly = y - 11;
let anch = 'middle', tx = x;
if (tx < g.padL + 14){ anch = 'start'; tx = g.padL; }
if (tx > g.W - g.padR - 14){ anch = 'end'; tx = g.W - g.padR; }
return `<circle class="ring" data-i="${i}" cx="${R(x)}" cy="${R(y)}" r="3.4"/>`
+ `<text class="val" x="${R(tx)}" y="${R(ly)}" text-anchor="${anch}">${Math.round(temps[i])}\u00B0</text>`;
};
out += mark(iMax, true) + mark(iMin, false);
/* crosshair (hidden until hover) + invisible hit area */
out += `<g id="xh" opacity="0"><line class="xline" y1="${g.padT}" y2="${base}"/><circle class="xdot" r="3.6"/></g>`
+ `<rect class="hit" x="${g.padL}" y="${g.padT}" width="${g.W - g.padL - g.padR}" height="${base - g.padT}"/>`;
s.innerHTML = out;
}
/* ------------------------------ interaction ----------------------------- */
let hoverBound = false;
function bindHover(){
if (hoverBound) return;
hoverBound = true;
const s = $('chart');
s.addEventListener('pointermove', e => {
if (!chart) return;
const rect = s.getBoundingClientRect();
const iw = rect.width - 6 - 48;
let i = Math.round((e.clientX - rect.left - 6) / (iw / 23));
setHover(Math.max(0, Math.min(23, i)));
});
s.addEventListener('pointerleave', () => setHover(-1));
s.addEventListener('click', e => {
const t = e.target.closest('.ring');
if (t) setHover(+t.dataset.i);
});
}
function setHover(i){
const s = $('chart'), tip = $('tip'), gEl = s.querySelector('#xh');
if (!gEl || !chart) return;
if (i < 0 || chart.temps[i] == null){
gEl.setAttribute('opacity', '0');
tip.style.opacity = 0;
return;
}
const g = geom();
const x = g.X(i), y = g.Y(chart.temps[i]);
gEl.setAttribute('opacity', '1');
const ln = gEl.querySelector('line'), dot = gEl.querySelector('circle');
ln.setAttribute('x1', x); ln.setAttribute('x2', x);
dot.setAttribute('cx', x); dot.setAttribute('cy', y);
tip.innerHTML = `<b>${String(i).padStart(2,'0')}:00</b>${Number(chart.temps[i]).toFixed(1)}\u00B0C`;
tip.style.left = Math.max(58, Math.min(g.W - 58, x)) + 'px';
tip.style.top = y + 'px';
tip.classList.toggle('below', y < 52);
tip.style.opacity = 1;
}
window.addEventListener('resize', () => { if (chart && $('chart')) drawChart(); });
/* ================================ boot ================================== */
showLoading();
load();
})();
</script>
</body>
</html>L1 — cheap deterministic descriptors
| bytes total | 24,555 | html / css / js | 761 / 6,645 / 17,149 |
|---|---|---|---|
| dom nodes | 22 | dom depth | 6 |
| css rules | 65 | js present | yes |
| brightness | 231.0 | contrast | 15.8 |
| colorfulness | 8.8 | whitespace | 95.6% |
This slot's telemetry
| prompt tokens | 394 | completion tokens | 38,076 |
|---|---|---|---|
| total tokens | 38,470 | wall | 929.1 s |
| cost | — | request id | — |
config.json548 B
{
"N": 2,
"auth": {
"credential_ref": "WCB_OPENCODE_KEY",
"method": "oauth"
},
"billing": "plan",
"config_id": "ox-alpha-free--opencode-go--dev",
"effort": null,
"family": "glm",
"m": {
"min": 1,
"q": 1
},
"model_id": "ox-alpha-free",
"protocol": "api",
"served_model": "ox-alpha-free",
"telemetry": {
"completion_tokens": 71512,
"cost_usd": null,
"prompt_tokens": 780,
"total_tokens": 72292,
"wall_ms": 1785893
},
"transport": "opencode-go-gateway",
"vendor_sanction_ref": null
}send-log2.5 KB
{
"N": 2,
"batch_id": "2026-08-22--opencode-go-new",
"config_id": "ox-alpha-free--opencode-go--dev",
"positions": [
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-21T14:40:47.754074+00:00",
"http_status": 200,
"outcome": "infra-failed",
"reached_model": true,
"reason": "mid-stream-death",
"request_id": null,
"started_at": "2026-08-21T14:38:21.037595+00:00"
}
],
"block_index": 0,
"model_reaching_attempt_index": 0,
"slot_index": 0,
"terminal_state": "infra-failed",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-21T14:55:04.557899+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-08-21T14:40:47.754826+00:00"
}
],
"block_index": 0,
"model_reaching_attempt_index": 0,
"slot_index": 0,
"terminal_state": "valid",
"variant": "P-min"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-21T14:56:24.963830+00:00",
"http_status": 200,
"outcome": "infra-failed",
"reached_model": true,
"reason": "mid-stream-death",
"request_id": null,
"started_at": "2026-08-21T14:55:11.538881+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "infra-failed",
"variant": "P-min"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-08-21T15:11:54.090432+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-08-21T14:56:24.964377+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "valid",
"variant": "P-q"
}
],
"retry_policy": {
"max_unreachable_retries": 5,
"rate_limit_backoff": {
"max_attempts": 4,
"max_total_ms": 60000
}
}
}