glm-5.1 · go
go
- config
- glm-5.1--opencode-go--dev
- batch
- 2026-07-19--unified
- transport
- opencode-go-gateway
- protocol
- api · plan
- served model
- glm-5.1
- captured
- Jul 18, 2026, 11:54 AM · N=2
variant
live
slot 0 · 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 neighbors
nearest
claude-sonnet-5 @medium · kiro0.66glm-5.2-eff-enabled--api--official--dev0.66gpt-5.6-sol @xhigh · codex-oauth0.66claude-fable-5 @xhigh · CC0.64claude-opus-4-7 @medium · kiro0.64farthest
qwen3.7-max · qoder0.45gpt-5.5 @xhigh · codex-oauth0.45minimax-m2.5 · kiro0.47mimo-v2.5-free · api0.47gpt-5.6-terra @medium · kiro0.47within session 2026-07-19--unified
similarity measures convergence within this session — not quality.
Fidelity — does the card show the right data?
- namematch
- conditionmatch
- datematch
- max tempmatchshown: 25
- min tempmatchshown: 16
- hourlymismatchcoverage 0/24 · 0 match · 5 mismatch · 19 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 lang="en">
<head>
<meta charset="UTF-8">
<title>Weather</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
width: 1280px;
height: 800px;
overflow: hidden;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: #fff;
}
body {
background: #0b1020;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
#bg {
position: absolute; inset: 0;
background: linear-gradient(135deg, #1a2a4f 0%, #2d1b4e 50%, #4a1942 100%);
transition: background 1.2s ease;
}
#bg::before {
content: '';
position: absolute; inset: 0;
background:
radial-gradient(circle at 20% 20%, rgba(255,200,120,0.15), transparent 40%),
radial-gradient(circle at 80% 70%, rgba(120,180,255,0.15), transparent 45%);
animation: drift 20s ease-in-out infinite alternate;
}
@keyframes drift {
0% { transform: translate(0,0); }
100% { transform: translate(-30px, 20px); }
}
.stars {
position: absolute; inset: 0;
background-image:
radial-gradient(1px 1px at 12% 18%, rgba(255,255,255,0.7), transparent),
radial-gradient(1px 1px at 28% 65%, rgba(255,255,255,0.5), transparent),
radial-gradient(1px 1px at 47% 32%, rgba(255,255,255,0.6), transparent),
radial-gradient(1px 1px at 68% 78%, rgba(255,255,255,0.5), transparent),
radial-gradient(1.5px 1.5px at 82% 22%, rgba(255,255,255,0.8), transparent),
radial-gradient(1px 1px at 92% 55%, rgba(255,255,255,0.4), transparent),
radial-gradient(1px 1px at 38% 88%, rgba(255,255,255,0.5), transparent),
radial-gradient(1.5px 1.5px at 58% 12%, rgba(255,255,255,0.6), transparent);
animation: twinkle 6s ease-in-out infinite alternate;
}
@keyframes twinkle {
0% { opacity: 0.6; }
100% { opacity: 1; }
}
.card {
position: relative;
width: 1100px;
height: 640px;
border-radius: 28px;
background: rgba(255,255,255,0.06);
backdrop-filter: blur(30px) saturate(140%);
-webkit-backdrop-filter: blur(30px) saturate(140%);
border: 1px solid rgba(255,255,255,0.12);
box-shadow: 0 30px 80px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.15);
padding: 48px 56px;
display: grid;
grid-template-rows: auto 1fr;
gap: 28px;
overflow: hidden;
}
.card::after {
content: '';
position: absolute; top: 0; left: 0; right: 0; height: 1px;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
}
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.location {
font-size: 13px;
letter-spacing: 4px;
text-transform: uppercase;
color: rgba(255,255,255,0.6);
margin-bottom: 8px;
}
.place {
font-size: 44px;
font-weight: 200;
letter-spacing: -0.5px;
color: #fff;
}
.date-block {
text-align: right;
}
.date {
font-size: 28px;
font-weight: 300;
letter-spacing: 0.5px;
}
.weekday {
font-size: 13px;
letter-spacing: 3px;
text-transform: uppercase;
color: rgba(255,255,255,0.6);
margin-top: 6px;
}
.main {
display: grid;
grid-template-columns: 1.1fr 1fr;
gap: 40px;
align-items: center;
}
.left {
display: flex;
flex-direction: column;
gap: 24px;
}
.condition-row {
display: flex;
align-items: center;
gap: 18px;
}
.icon-wrap {
width: 84px; height: 84px;
display: flex; align-items: center; justify-content: center;
border-radius: 50%;
background: rgba(255,255,255,0.08);
border: 1px solid rgba(255,255,255,0.15);
}
.icon-wrap svg { width: 52px; height: 52px; }
.condition {
font-size: 26px;
font-weight: 300;
letter-spacing: 0.3px;
}
.condition-sub {
font-size: 13px;
color: rgba(255,255,255,0.55);
margin-top: 4px;
letter-spacing: 0.5px;
}
.temps {
display: flex;
align-items: baseline;
gap: 30px;
}
.big-temp {
font-size: 120px;
font-weight: 100;
line-height: 1;
letter-spacing: -4px;
background: linear-gradient(180deg, #fff 0%, rgba(255,255,255,0.7) 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.big-temp .deg {
font-size: 60px;
font-weight: 200;
vertical-align: top;
margin-left: 4px;
}
.hi-lo {
display: flex;
flex-direction: column;
gap: 6px;
}
.hi-lo .row {
display: flex; align-items: center; gap: 10px;
font-size: 18px; font-weight: 300;
}
.hi-lo .label {
font-size: 11px; letter-spacing: 2px; text-transform: uppercase;
color: rgba(255,255,255,0.5);
width: 28px;
}
.arrow { font-size: 14px; opacity: 0.7; }
.right {
height: 100%;
display: flex;
flex-direction: column;
gap: 14px;
}
.right-title {
font-size: 12px;
letter-spacing: 3px;
text-transform: uppercase;
color: rgba(255,255,255,0.55);
display: flex;
justify-content: space-between;
align-items: center;
}
.chart {
flex: 1;
position: relative;
min-height: 0;
}
.chart svg { width: 100%; height: 100%; display: block; }
.x-axis {
display: flex;
justify-content: space-between;
padding: 0 4px;
font-size: 11px;
color: rgba(255,255,255,0.45);
letter-spacing: 1px;
}
.error {
text-align: center;
padding: 80px 20px;
}
.error h2 {
font-size: 32px;
font-weight: 300;
margin-bottom: 12px;
}
.error p {
color: rgba(255,255,255,0.6);
font-size: 15px;
letter-spacing: 0.5px;
}
.loading {
position: absolute; inset: 0;
display: flex; align-items: center; justify-content: center;
flex-direction: column; gap: 20px;
}
.spinner {
width: 44px; height: 44px;
border: 2px solid rgba(255,255,255,0.15);
border-top-color: rgba(255,255,255,0.9);
border-radius: 50%;
animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.loading-text {
font-size: 13px; letter-spacing: 4px; text-transform: uppercase;
color: rgba(255,255,255,0.6);
}
.fade-in { animation: fadeIn 0.7s ease both; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px);} to { opacity: 1; transform: none; } }
.meta {
position: absolute;
bottom: 18px; left: 0; right: 0;
text-align: center;
font-size: 10px; letter-spacing: 3px;
text-transform: uppercase;
color: rgba(255,255,255,0.3);
}
</style>
</head>
<body>
<div id="bg"></div>
<div class="stars"></div>
<div class="card" id="card">
<div class="loading" id="loading">
<div class="spinner"></div>
<div class="loading-text">Reading the sky…</div>
</div>
</div>
<div class="meta">Open-Meteo · UTC · Celsius</div>
<script>
// --- Parse parameters ---
const params = new URLSearchParams(location.search);
const lat = parseFloat(params.get('lat')) || 52.52;
const lon = parseFloat(params.get('lon')) || 13.405;
const name = params.get('name') || 'Berlin';
function todayUTC() {
const d = new Date();
return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
}
function parseDate(s) {
if (!s) return todayUTC();
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
if (!m) return todayUTC();
return new Date(Date.UTC(+m[1], +m[2]-1, +m[3]));
}
const dateObj = parseDate(params.get('date'));
const yyyy = dateObj.getUTCFullYear();
const mm = String(dateObj.getUTCMonth()+1).padStart(2,'0');
const dd = String(dateObj.getUTCDate()).padStart(2,'0');
const dateStr = `${yyyy}-${mm}-${dd}`;
const todayStr = (() => {
const t = todayUTC();
return `${t.getUTCFullYear()}-${String(t.getUTCMonth()+1).padStart(2,'0')}-${String(t.getUTCDate()).padStart(2,'0')}`;
})();
const isPast = dateStr < todayStr;
const endpoint = isPast ? '/api/om/archive' : '/api/om/forecast';
// --- Weather code mapping ---
const WMO = {
0: { label: 'Clear sky', bg: 'linear-gradient(135deg, #1a3a5f 0%, #2d5a8f 50%, #4a7fb5 100%)', icon: 'sun' },
1: { label: 'Mainly clear', bg: 'linear-gradient(135deg, #243a5f 0%, #436a9f 50%, #6a8fb5 100%)', icon: 'sun-cloud' },
2: { label: 'Partly cloudy', bg: 'linear-gradient(135deg, #2a3550 0%, #475575 50%, #6a7590 100%)', icon: 'sun-cloud' },
3: { label: 'Overcast', bg: 'linear-gradient(135deg, #2a2d3a 0%, #454858 50%, #606578 100%)', icon: 'cloud' },
45: { label: 'Fog', bg: 'linear-gradient(135deg, #3a3f4a 0%, #5a606f 50%, #7a8090 100%)', icon: 'fog' },
48: { label: 'Depositing rime fog',bg: 'linear-gradient(135deg, #3a3f4a 0%, #5a606f 50%, #7a8090 100%)', icon: 'fog' },
51: { label: 'Light drizzle', bg: 'linear-gradient(135deg, #2a3550 0%, #3a5575 50%, #5a7595 100%)', icon: 'rain' },
53: { label: 'Moderate drizzle', bg: 'linear-gradient(135deg, #2a3550 0%, #3a5575 50%, #5a7595 100%)', icon: 'rain' },
55: { label: 'Dense drizzle', bg: 'linear-gradient(135deg, #2a3550 0%, #3a5575 50%, #5a7595 100%)', icon: 'rain' },
61: { label: 'Slight rain', bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
63: { label: 'Moderate rain', bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
65: { label: 'Heavy rain', bg: 'linear-gradient(135deg, #1a2438 0%, #283a58 50%, #3a5575 100%)', icon: 'rain' },
66: { label: 'Freezing rain', bg: 'linear-gradient(135deg, #2a4055 0%, #456075 50%, #6080a0 100%)', icon: 'rain' },
67: { label: 'Freezing rain', bg: 'linear-gradient(135deg, #2a4055 0%, #456075 50%, #6080a0 100%)', icon: 'rain' },
71: { label: 'Slight snow', bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
73: { label: 'Moderate snow', bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
75: { label: 'Heavy snow', bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
77: { label: 'Snow grains', bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
80: { label: 'Slight showers', bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
81: { label: 'Moderate showers', bg: 'linear-gradient(135deg, #1f2a45 0%, #2f4570 50%, #4a6595 100%)', icon: 'rain' },
82: { label: 'Violent showers', bg: 'linear-gradient(135deg, #1a2438 0%, #283a58 50%, #3a5575 100%)', icon: 'rain' },
85: { label: 'Snow showers', bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
86: { label: 'Snow showers', bg: 'linear-gradient(135deg, #3a4a6a 0%, #5a6f8f 50%, #8090b0 100%)', icon: 'snow' },
95: { label: 'Thunderstorm', bg: 'linear-gradient(135deg, #1a1830 0%, #2f2848 50%, #4a3f6a 100%)', icon: 'storm' },
96: { label: 'Storm with hail', bg: 'linear-gradient(135deg, #1a1830 0%, #2f2848 50%, #4a3f6a 100%)', icon: 'storm' },
99: { label: 'Storm with hail', bg: 'linear-gradient(135deg, #1a1830 0%, #2f2848 50%, #4a3f6a 100%)', icon: 'storm' },
};
function codeInfo(c) { return WMO[c] || { label: '—', bg: 'linear-gradient(135deg, #2a3550 0%, #455575 100%)', icon: 'cloud' }; }
// --- Icons ---
function iconSVG(kind) {
const stroke = '#fff';
const sun = `<circle cx="32" cy="32" r="12" fill="url(#sun)"/><g stroke="${stroke}" stroke-width="2" stroke-linecap="round">
<line x1="32" y1="6" x2="32" y2="12"/><line x1="32" y1="52" x2="32" y2="58"/>
<line x1="6" y1="32" x2="12" y2="32"/><line x1="52" y1="32" x2="58" y2="32"/>
<line x1="13" y1="13" x2="17" y2="17"/><line x1="47" y1="47" x2="51" y2="51"/>
<line x1="13" y1="51" x2="17" y2="47"/><line x1="47" y1="17" x2="51" y2="13"/></g>`;
const cloud = `<path d="M20 44 Q10 44 10 34 Q10 26 18 26 Q20 16 30 16 Q40 16 42 26 Q50 26 50 34 Q50 44 42 44 Z" fill="rgba(255,255,255,0.85)"/>`;
const rain = `<path d="M18 36 Q10 36 10 28 Q10 20 18 20 Q20 12 28 12 Q38 12 40 20 Q48 20 48 28 Q48 36 42 36 Z" fill="rgba(255,255,255,0.85)"/>
<g stroke="#9fd0ff" stroke-width="2.5" stroke-linecap="round">
<line x1="20" y1="42" x2="17" y2="52"/>
<line x1="30" y1="42" x2="27" y2="54"/>
<line x1="40" y1="42" x2="37" y2="52"/></g>`;
const snow = `<path d="M18 36 Q10 36 10 28 Q10 20 18 20 Q20 12 28 12 Q38 12 40 20 Q48 20 48 28 Q48 36 42 36 Z" fill="rgba(255,255,255,0.9)"/>
<g fill="#fff">
<circle cx="20" cy="48" r="2.5"/><circle cx="30" cy="52" r="2.5"/><circle cx="40" cy="48" r="2.5"/></g>`;
const fog = `<g stroke="rgba(255,255,255,0.7)" stroke-width="3" stroke-linecap="round">
<line x1="10" y1="20" x2="54" y2="20"/>
<line x1="14" y1="30" x2="50" y2="30"/>
<line x1="8" y1="40" x2="56" y2="40"/>
<line x1="16" y1="50" x2="48" y2="50"/></g>`;
const storm = `<path d="M18 32 Q10 32 10 24 Q10 16 18 16 Q20 8 28 8 Q38 8 40 16 Q48 16 48 24 Q48 32 42 32 Z" fill="rgba(255,255,255,0.8)"/>
<path d="M30 32 L24 46 L32 46 L26 58 L36 42 L30 42 Z" fill="#ffd24a"/>`;
const suncloud = `<circle cx="22" cy="22" r="8" fill="url(#sun)"/>
<g stroke="#fff" stroke-width="1.6" stroke-linecap="round">
<line x1="22" y1="8" x2="22" y2="11"/><line x1="8" y1="22" x2="11" y2="22"/>
<line x1="11.5" y1="11.5" x2="13.5" y2="13.5"/><line x1="32.5" y1="11.5" x2="30.5" y2="13.5"/></g>
<path d="M24 46 Q16 46 16 38 Q16 30 24 30 Q26 24 34 24 Q44 24 46 32 Q54 32 54 40 Q54 46 48 46 Z" fill="rgba(255,255,255,0.9)"/>`;
let body = '';
if (kind === 'sun') body = sun;
else if (kind === 'cloud') body = cloud;
else if (kind === 'rain') body = rain;
else if (kind === 'snow') body = snow;
else if (kind === 'fog') body = fog;
else if (kind === 'storm') body = storm;
else if (kind === 'sun-cloud') body = suncloud;
else body = cloud;
return `<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="sun" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="#ffe27a"/><stop offset="100%" stop-color="#ff9d4a"/>
</radialGradient>
</defs>
${body}
</svg>`;
}
// --- Date formatting ---
const MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];
const DAYS = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
// --- Build hourly chart ---
function buildChart(hourlyTemps) {
// hourlyTemps: array of 24 numbers (00:00 .. 23:00)
const W = 500, H = 260, P = 20;
const min = Math.min(...hourlyTemps);
const max = Math.max(...hourlyTemps);
const range = max - min || 1;
const pad = range * 0.15;
const lo = min - pad, hi = max + pad;
const xStep = (W - P*2) / (hourlyTemps.length - 1);
const y = t => P + (1 - (t - lo)/(hi - lo)) * (H - P*2);
const x = i => P + i * xStep;
const pts = hourlyTemps.map((t,i) => `${x(i).toFixed(1)},${y(t).toFixed(1)}`).join(' ');
const areaPts = `${x(0).toFixed(1)},${(H-P).toFixed(1)} ${pts} ${x(hourlyTemps.length-1).toFixed(1)},${(H-P).toFixed(1)}`;
// Find max & min points
const maxIdx = hourlyTemps.indexOf(max);
const minIdx = hourlyTemps.indexOf(min);
let labels = '';
hourlyTemps.forEach((t, i) => {
if (i % 3 === 0) {
labels += `<text x="${x(i)}" y="${y(t) - 12}" fill="rgba(255,255,255,0.55)" font-size="11" text-anchor="middle" font-family="Inter, sans-serif">${Math.round(t)}°</text>`;
}
});
return `<svg viewBox="0 0 ${W} ${H}" preserveAspectRatio="none">
<defs>
<linearGradient id="area" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="rgba(255,210,140,0.5)"/>
<stop offset="100%" stop-color="rgba(255,210,140,0)"/>
</linearGradient>
<linearGradient id="line" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#7fd0ff"/>
<stop offset="100%" stop-color="#ffd28a"/>
</linearGradient>
</defs>
<polygon points="${areaPts}" fill="url(#area)"/>
<polyline points="${pts}" fill="none" stroke="url(#line)" stroke-width="2.5" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="${x(maxIdx)}" cy="${y(max)}" r="5" fill="#ffd28a" stroke="rgba(0,0,0,0.2)" stroke-width="1"/>
<circle cx="${x(minIdx)}" cy="${y(min)}" r="5" fill="#7fd0ff" stroke="rgba(0,0,0,0.2)" stroke-width="1"/>
${labels}
</svg>`;
}
function xAxisLabels() {
const hours = ['00','06','12','18','23'];
return hours.map(h => `<span>${h}:00</span>`).join('');
}
// --- Render ---
function render(data) {
const daily = data.daily;
const hourly = data.hourly;
if (!daily || !daily.time || daily.time.length === 0 || !hourly || !hourly.time) {
renderError('No data available for this date.');
return;
}
// daily might return multiple or single — find matching date index
let dIdx = daily.time.indexOf(dateStr);
if (dIdx < 0) dIdx = 0;
const tMax = daily.temperature_2m_max[dIdx];
const tMin = daily.temperature_2m_min[dIdx];
const code = daily.weather_code[dIdx];
const info = codeInfo(code);
// Build hourly array for our date (24 entries)
let temps24 = [];
for (let h = 0; h < 24; h++) {
const hh = String(h).padStart(2,'0');
const ts = `${dateStr}T${hh}:00`;
const idx = hourly.time.indexOf(ts);
if (idx >= 0) {
temps24.push(hourly.temperature_2m[idx]);
} else {
// Try ISO with Z
const ts2 = `${dateStr}T${hh}:00Z`;
const idx2 = hourly.time.indexOf(ts2);
if (idx2 >= 0) temps24.push(hourly.temperature_2m[idx2]);
else temps24.push(null);
}
}
if (temps24.every(v => v === null)) {
renderError('Hourly data unavailable for this date.');
return;
}
// Interpolate nulls
for (let i = 0; i < 24; i++) {
if (temps24[i] === null) {
let prev = null, next = null;
for (let j = i-1; j >= 0 && prev === null; j--) if (temps24[j] !== null) prev = temps24[j];
for (let j = i+1; j < 24 && next === null; j++) if (temps24[j] !== null) next = temps24[j];
if (prev !== null && next !== null) temps24[i] = (prev+next)/2;
else if (prev !== null) temps24[i] = prev;
else if (next !== null) temps24[i] = next;
else temps24[i] = tMax;
}
}
// Set background
document.getElementById('bg').style.background = info.bg;
// Average for big display
const avg = temps24.reduce((a,b)=>a+b,0)/24;
const displayTemp = Math.round(avg);
const placeDate = new Date(dateObj);
const wd = DAYS[placeDate.getUTCDay()];
const dateLabel = `${placeDate.getUTCDate()} ${MONTHS[placeDate.getUTCMonth()]} ${placeDate.getUTCFullYear()}`;
let scenario = '';
if (tMax - tMin > 10) scenario = 'Large swing day';
else if (tMax < 0) scenario = 'Below freezing';
else if (tMax < 10) scenario = 'Cold';
else if (tMax < 20) scenario = 'Mild';
else if (tMax < 28) scenario = 'Warm';
else scenario = 'Hot';
const html = `
<div class="header fade-in">
<div>
<div class="location">Location</div>
<div class="place">${escapeHtml(name)}</div>
<div style="font-size:13px; color:rgba(255,255,255,0.45); margin-top:6px; letter-spacing:0.5px;">${Math.abs(lat).toFixed(2)}°${lat>=0?'N':'S'}, ${Math.abs(lon).toFixed(2)}°${lon>=0?'E':'W'}</div>
</div>
<div class="date-block">
<div class="date">${dateLabel}</div>
<div class="weekday">${wd}</div>
</div>
</div>
<div class="main fade-in">
<div class="left">
<div class="condition-row">
<div class="icon-wrap">${iconSVG(info.icon)}</div>
<div>
<div class="condition">${info.label}</div>
<div class="condition-sub">${scenario} · ${isPast ? 'Archived' : 'Forecast'} data</div>
</div>
</div>
<div class="temps">
<div class="big-temp">${displayTemp}<span class="deg">°</span></div>
<div class="hi-lo">
<div class="row"><span class="label">High</span><span>${Math.round(tMax)}°</span><span class="arrow">▲</span></div>
<div class="row"><span class="label">Low</span><span>${Math.round(tMin)}°</span><span class="arrow">▼</span></div>
<div style="height:1px; background:rgba(255,255,255,0.12); margin:6px 0;"></div>
<div class="row"><span class="label">Avg</span><span>${Math.round(avg)}°</span></div>
</div>
</div>
</div>
<div class="right">
<div class="right-title">
<span>Hourly Temperature</span>
<span>${dateStr}</span>
</div>
<div class="chart">${buildChart(temps24)}</div>
<div class="x-axis">${xAxisLabels()}</div>
</div>
</div>
`;
document.getElementById('card').innerHTML = html;
}
function renderError(msg) {
document.getElementById('card').innerHTML = `
<div class="error fade-in">
<div style="font-size:60px; margin-bottom:10px; opacity:0.4;">⛨</div>
<h2>Weather unavailable</h2>
<p>${escapeHtml(msg)}</p>
<p style="margin-top:14px; font-size:12px; letter-spacing:2px; text-transform:uppercase; color:rgba(255,255,255,0.4);">${escapeHtml(name)} · ${dateStr}</p>
</div>
`;
}
function escapeHtml(s) {
return String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
}
// --- Fetch ---
async function load() {
const qs = new URLSearchParams({
latitude: lat,
longitude: lon,
daily: 'temperature_2m_max,temperature_2m_min,weather_code',
hourly: 'temperature_2m',
timezone: 'UTC',
temperature_unit: 'celsius',
start_date: dateStr,
end_date: dateStr
});
const url = `${endpoint}?${qs.toString()}`;
try {
const res = await fetch(url);
if (!res.ok) throw new Error('HTTP ' + res.status);
const data = await res.json();
render(data);
} catch (e) {
renderError('Could not load weather data. ' + (e.message || ''));
}
}
load();
</script>
</body>
</html>L1 — cheap deterministic descriptors
| bytes total | 22,637 | html / css / js | 439 / 6,481 / 15,717 |
|---|---|---|---|
| dom nodes | 14 | dom depth | 5 |
| css rules | 52 | js present | yes |
| brightness | 93.9 | contrast | 18.5 |
| colorfulness | 34.0 | whitespace | 41.1% |
This slot's telemetry
| prompt tokens | 319 | completion tokens | 8,215 |
|---|---|---|---|
| total tokens | 8,534 | wall | 43.2 s |
| cost | — | request id | — |
config.json530 B
{
"N": 2,
"auth": {
"credential_ref": "WCB_OPENCODE_KEY",
"method": "oauth"
},
"billing": "plan",
"config_id": "glm-5.1--opencode-go--dev",
"effort": null,
"family": "glm",
"m": {
"min": 2,
"q": 2
},
"model_id": "glm-5.1",
"protocol": "api",
"served_model": "glm-5.1",
"telemetry": {
"completion_tokens": 26768,
"cost_usd": null,
"prompt_tokens": 1260,
"total_tokens": 28028,
"wall_ms": 158017
},
"transport": "opencode-go-gateway",
"vendor_sanction_ref": null
}send-log2.4 KB
{
"N": 2,
"batch_id": "2026-07-19--go-requeue2",
"config_id": "glm-5.1--opencode-go--dev",
"positions": [
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-18T19:50:25.586916+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-18T19:49:53.412958+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-07-18T19:51:12.341008+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-18T19:50:29.098934+00:00"
}
],
"block_index": 0,
"model_reaching_attempt_index": 0,
"slot_index": 0,
"terminal_state": "valid",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-18T19:52:25.633215+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-18T19:51:15.984052+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "valid",
"variant": "P-q"
},
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-18T19:53:25.346035+00:00",
"http_status": 200,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-18T19:53:12.390936+00:00"
}
],
"block_index": 1,
"model_reaching_attempt_index": 0,
"slot_index": 1,
"terminal_state": "valid",
"variant": "P-min"
}
],
"retry_policy": {
"max_unreachable_retries": 5,
"rate_limit_backoff": {
"max_attempts": 4,
"max_total_ms": 60000
}
}
}