claude-sonnet-5 @ max · CC
CCmax
- config
- claude-sonnet-5-eff-max--cli--claude-code--dev
- batch
- 2026-07-19--unified
- transport
- claude-code-cli-headless
- protocol
- cli · plan
- served model
- claude-haiku-4-5-20251001
- 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 @xhigh · cursor0.66claude-sonnet-5 @xhigh · cursor-xl0.66claude-opus-4-7-thinking @xhigh · cursor0.64claude-sonnet-5-thinking @high · cursor-xl0.64claude-sonnet-5 @high · cursor0.64farthest
grok-4.3 · api0.49grok-4.3 @medium · api0.50grok-4.3 @low · api0.50gpt-5.2-codex @low · api0.50deepseek-v4-pro · opencode0.50within 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 · 4 mismatch · 20 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">
<meta name="viewport" content="width=1280, initial-scale=1">
<link rel="icon" href="data:,">
<title>Weather Card</title>
<style>
:root { color-scheme: dark; }
* { box-sizing: border-box; }
html, body {
margin: 0; padding: 0;
width: 1280px; height: 800px;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
body {
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(160deg, #4a5b7a 0%, #6f85a8 55%, #a9bdd4 100%);
}
body.theme-default { background: linear-gradient(160deg, #4a5b7a 0%, #6f85a8 55%, #a9bdd4 100%); }
body.theme-clear { background: linear-gradient(160deg, #2d6fb0 0%, #5aa8e0 55%, #ffe2a8 100%); }
body.theme-partly-cloudy { background: linear-gradient(160deg, #4c6c8f 0%, #86a9c9 55%, #dbe8f2 100%); }
body.theme-cloudy { background: linear-gradient(160deg, #5b6675 0%, #8b96a3 55%, #c4ccd4 100%); }
body.theme-fog { background: linear-gradient(160deg, #6d7a86 0%, #a2aeb8 55%, #d6dee3 100%); }
body.theme-drizzle { background: linear-gradient(160deg, #435669 0%, #6c8497 55%, #a2b7c4 100%); }
body.theme-rain { background: linear-gradient(160deg, #24344a 0%, #3f5872 55%, #6c869a 100%); }
body.theme-snow { background: linear-gradient(160deg, #5f7ea0 0%, #a7cbe3 55%, #eef7fc 100%); }
body.theme-thunderstorm { background: linear-gradient(160deg, #181d2b 0%, #323a52 55%, #4c5468 100%); }
#app { width: 1280px; height: 800px; display: flex; align-items: center; justify-content: center; }
.card {
position: relative;
width: 1120px;
border-radius: 32px;
padding: 48px 60px 40px;
background: linear-gradient(165deg, rgba(6,14,26,0.46), rgba(6,14,26,0.22));
backdrop-filter: blur(30px) saturate(160%);
-webkit-backdrop-filter: blur(30px) saturate(160%);
border: 1px solid rgba(255,255,255,0.22);
box-shadow: 0 30px 80px -20px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.22);
color: #fff;
text-shadow: 0 1px 3px rgba(0,0,0,0.2);
overflow: hidden;
display: flex;
flex-direction: column;
animation: cardIn 0.5s ease;
}
@keyframes cardIn { from { opacity: 0; transform: translateY(14px) scale(0.99); } to { opacity: 1; transform: translateY(0) scale(1); } }
.card::before, .card::after { content: ''; position: absolute; border-radius: 50%; filter: blur(70px); pointer-events: none; z-index: 0; }
.card::before { width: 380px; height: 380px; background: var(--accent, #ffb648); opacity: 0.30; top: -140px; right: -100px; }
.card::after { width: 300px; height: 300px; background: var(--accent2, #4a90e2); opacity: 0.22; bottom: -120px; left: -80px; }
.card > * { position: relative; z-index: 1; }
.card__header { display: flex; align-items: flex-start; justify-content: space-between; }
.card__header > div:first-child { min-width: 0; flex: 1 1 auto; }
.location-name { margin: 0; font-size: 38px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.15; overflow-wrap: anywhere; }
.date-label { margin: 8px 0 0; font-size: 16.5px; font-weight: 500; opacity: 0.8; }
.badge { flex: 0 0 auto; font-size: 12px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; padding: 8px 16px; border-radius: 999px; background: rgba(255,255,255,0.14); border: 1px solid rgba(255,255,255,0.28); white-space: nowrap; }
.hero-row { display: flex; align-items: center; gap: 36px; margin-top: 30px; }
.hero-icon { width: 132px; height: 132px; flex: 0 0 auto; filter: drop-shadow(0 10px 18px rgba(0,0,0,0.28)); }
.hero-icon svg, .error-icon svg { width: 100%; height: 100%; display: block; }
.hero-condition { flex: 1 1 auto; min-width: 0; }
.condition-label { margin: 0; font-size: 29px; font-weight: 700; letter-spacing: -0.01em; }
.coords-label { margin: 8px 0 0; font-size: 14px; opacity: 0.68; font-variant-numeric: tabular-nums; }
.hero-stats { display: flex; align-items: center; gap: 26px; flex: 0 0 auto; }
.stat { display: flex; flex-direction: column; align-items: flex-end; }
.stat-label { font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.09em; opacity: 0.68; margin-bottom: 6px; }
.stat-value { font-size: 52px; font-weight: 800; line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.stat--low .stat-value { opacity: 0.85; }
.stat-divider { width: 1px; height: 56px; background: rgba(255,255,255,0.25); }
.hourly-section { margin-top: 32px; padding-top: 24px; border-top: 1px solid rgba(255,255,255,0.16); }
.section-heading { margin: 0 0 6px; font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; opacity: 0.65; }
.chart-wrap { position: relative; margin-top: 6px; }
.chart-svg { display: block; overflow: visible; }
.chart-axis-label { fill: rgba(255,255,255,0.62); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chart-callout { fill: #fff; font-size: 13.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
#chartOverlay { cursor: crosshair; }
.chart-tooltip { position: absolute; transform: translate(-50%, -100%); pointer-events: none; opacity: 0; transition: opacity 0.12s ease; background: rgba(6,12,22,0.92); color: #fff; font-size: 12.5px; font-weight: 600; padding: 6px 11px; border-radius: 8px; white-space: nowrap; box-shadow: 0 8px 20px rgba(0,0,0,0.35); }
.card__footer { margin-top: 20px; font-size: 12.5px; opacity: 0.55; }
.skeleton { background: rgba(255,255,255,0.16); border-radius: 10px; animation: pulse 1.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }
.card--loading { min-height: 620px; }
.sk-badge { width: 90px; height: 26px; border-radius: 999px; position: absolute; top: 48px; right: 60px; }
.sk-title { width: 320px; height: 38px; }
.sk-subtitle { width: 220px; height: 18px; margin-top: 12px; }
.hero-row .sk-icon { width: 132px; height: 132px; border-radius: 26px; }
.hero-row .sk-condition { flex: 1; height: 29px; margin: 0 24px; align-self: center; }
.hero-row .sk-stats { width: 220px; height: 56px; align-self: center; }
.sk-chart { height: 220px; margin-top: 48px; border-radius: 16px; }
.loading-caption { text-align: center; margin-top: 24px; font-size: 14px; opacity: 0.7; }
.card--error { min-height: 620px; justify-content: center; align-items: center; text-align: center; padding: 60px 100px; }
.error-icon { width: 72px; height: 72px; margin-bottom: 20px; opacity: 0.92; }
.error-title { margin: 0 0 10px; font-size: 28px; font-weight: 800; }
.error-message { margin: 0; font-size: 16px; opacity: 0.85; max-width: 560px; line-height: 1.5; }
.error-meta { margin: 14px 0 0; font-size: 13px; opacity: 0.55; text-transform: uppercase; letter-spacing: 0.08em; }
.retry-btn { margin-top: 28px; padding: 12px 28px; border-radius: 999px; border: 1px solid rgba(255,255,255,0.35); background: rgba(255,255,255,0.14); color: #fff; font-size: 14px; font-weight: 700; cursor: pointer; transition: background 0.15s ease, transform 0.15s ease; font-family: inherit; }
.retry-btn:hover { background: rgba(255,255,255,0.24); transform: translateY(-1px); }
.retry-btn:active { transform: translateY(0); }
.retry-btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
</style>
</head>
<body class="theme-default">
<div id="app"></div>
<script>
(function () {
'use strict';
const DEFAULTS = { lat: 52.52, lon: 13.405, name: 'Berlin' };
const WMO = {
0: ['Clear sky', 'clear'], 1: ['Mainly clear', 'clear'],
2: ['Partly cloudy', 'partlyCloudy'], 3: ['Overcast', 'cloudy'],
45: ['Fog', 'fog'], 48: ['Depositing rime fog', 'fog'],
51: ['Light drizzle', 'drizzle'], 53: ['Moderate drizzle', 'drizzle'], 55: ['Dense drizzle', 'drizzle'],
56: ['Light freezing drizzle', 'drizzle'], 57: ['Dense freezing drizzle', 'drizzle'],
61: ['Slight rain', 'rain'], 63: ['Moderate rain', 'rain'], 65: ['Heavy rain', 'rain'],
66: ['Light freezing rain', 'rain'], 67: ['Heavy freezing rain', 'rain'],
71: ['Slight snow fall', 'snow'], 73: ['Moderate snow fall', 'snow'], 75: ['Heavy snow fall', 'snow'],
77: ['Snow grains', 'snow'],
80: ['Slight rain showers', 'rain'], 81: ['Moderate rain showers', 'rain'], 82: ['Violent rain showers', 'rain'],
85: ['Slight snow showers', 'snow'], 86: ['Heavy snow showers', 'snow'],
95: ['Thunderstorm', 'thunderstorm'], 96: ['Thunderstorm, slight hail', 'thunderstorm'], 99: ['Thunderstorm, heavy hail', 'thunderstorm']
};
const CATEGORY_META = {
clear: { theme: 'clear', accent: '#ffb648', accent2: '#3d7dc0' },
partlyCloudy: { theme: 'partly-cloudy', accent: '#ffcf7a', accent2: '#5f8fc4' },
cloudy: { theme: 'cloudy', accent: '#dbe2ea', accent2: '#8b98a8' },
fog: { theme: 'fog', accent: '#dbe6ee', accent2: '#93a4b2' },
drizzle: { theme: 'drizzle', accent: '#a9d6ff', accent2: '#5b7ea6' },
rain: { theme: 'rain', accent: '#7ab8ff', accent2: '#2c4a66' },
snow: { theme: 'snow', accent: '#eaf6ff', accent2: '#8fb6d6' },
thunderstorm: { theme: 'thunderstorm', accent: '#ffe066', accent2: '#4a5470' }
};
const WARNING_SVG = '<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">' +
'<path d="M50 10 L94 86 L6 86 Z" fill="rgba(255,255,255,0.12)" stroke="#fff" stroke-width="5" stroke-linejoin="round" stroke-linecap="round"/>' +
'<line x1="50" y1="40" x2="50" y2="62" stroke="#fff" stroke-width="6" stroke-linecap="round"/>' +
'<circle cx="50" cy="74" r="4.5" fill="#fff"/>' +
'</svg>';
function iconDefs() {
return '<defs>' +
'<linearGradient id="gSun" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#ffe6a7"/><stop offset="100%" stop-color="#ff9f43"/></linearGradient>' +
'<linearGradient id="gCloud" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#ffffff"/><stop offset="100%" stop-color="#c7d3e0"/></linearGradient>' +
'<linearGradient id="gCloudDark" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#bdc9d6"/><stop offset="100%" stop-color="#8898ab"/></linearGradient>' +
'<linearGradient id="gRain" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#a9d6ff"/><stop offset="100%" stop-color="#4a90e2"/></linearGradient>' +
'<linearGradient id="gSnow" x1="0" y1="0" x2="0" y2="1"><stop offset="0%" stop-color="#ffffff"/><stop offset="100%" stop-color="#cfe7fb"/></linearGradient>' +
'<linearGradient id="gBolt" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#ffe066"/><stop offset="100%" stop-color="#ffb703"/></linearGradient>' +
'</defs>';
}
const ICON_BODIES = {
clear:
'<circle cx="50" cy="50" r="24" fill="url(#gSun)"/>' +
'<g stroke="url(#gSun)" stroke-width="6" stroke-linecap="round">' +
'<line x1="50" y1="6" x2="50" y2="18"/><line x1="50" y1="82" x2="50" y2="94"/>' +
'<line x1="6" y1="50" x2="18" y2="50"/><line x1="82" y1="50" x2="94" y2="50"/>' +
'<line x1="19.3" y1="19.3" x2="27.6" y2="27.6"/><line x1="72.4" y1="72.4" x2="80.7" y2="80.7"/>' +
'<line x1="19.3" y1="80.7" x2="27.6" y2="72.4"/><line x1="72.4" y1="27.6" x2="80.7" y2="19.3"/>' +
'</g>',
partlyCloudy:
'<circle cx="35" cy="35" r="17" fill="url(#gSun)"/>' +
'<g stroke="url(#gSun)" stroke-width="5" stroke-linecap="round">' +
'<line x1="35" y1="7" x2="35" y2="16"/><line x1="8" y1="35" x2="17" y2="35"/>' +
'<line x1="14" y1="14" x2="20.4" y2="20.4"/><line x1="56" y1="14" x2="49.6" y2="20.4"/>' +
'</g>' +
'<g fill="url(#gCloud)">' +
'<ellipse cx="42" cy="66" rx="20" ry="15.5"/><ellipse cx="62" cy="56" rx="25" ry="20.5"/>' +
'<ellipse cx="80" cy="64" rx="15" ry="12.5"/><rect x="33" y="62" width="56" height="19" rx="9.5"/>' +
'</g>',
cloudy:
'<g fill="url(#gCloudDark)" opacity="0.6">' +
'<ellipse cx="28" cy="38" rx="15" ry="11"/><ellipse cx="44" cy="32" rx="19" ry="15"/>' +
'<rect x="22" y="36" width="42" height="14" rx="7"/>' +
'</g>' +
'<g fill="url(#gCloud)">' +
'<ellipse cx="40" cy="63" rx="21" ry="16"/><ellipse cx="62" cy="53" rx="26" ry="21"/>' +
'<ellipse cx="81" cy="62" rx="16" ry="13"/><rect x="31" y="59" width="58" height="20" rx="10"/>' +
'</g>',
fog:
'<g fill="url(#gCloud)" opacity="0.85"><ellipse cx="46" cy="32" rx="22" ry="14"/></g>' +
'<g stroke="#dbe6ee" stroke-width="6" stroke-linecap="round" opacity="0.92">' +
'<line x1="10" y1="54" x2="90" y2="54"/><line x1="18" y1="68" x2="82" y2="68"/><line x1="14" y1="82" x2="86" y2="82"/>' +
'</g>',
drizzle:
'<g fill="url(#gCloud)">' +
'<ellipse cx="38" cy="44" rx="19" ry="14.5"/><ellipse cx="58" cy="35" rx="23" ry="18.5"/>' +
'<ellipse cx="76" cy="43" rx="14" ry="11.5"/><rect x="29" y="40" width="54" height="18" rx="9"/>' +
'</g>' +
'<g stroke="url(#gRain)" stroke-width="4.5" stroke-linecap="round">' +
'<line x1="38" y1="70" x2="35" y2="78"/><line x1="52" y1="72" x2="49" y2="80"/><line x1="66" y1="70" x2="63" y2="78"/>' +
'</g>',
rain:
'<g fill="url(#gCloud)">' +
'<ellipse cx="38" cy="40" rx="20" ry="15"/><ellipse cx="58" cy="31" rx="24" ry="19"/>' +
'<ellipse cx="77" cy="39" rx="15" ry="12"/><rect x="29" y="36" width="55" height="18" rx="9"/>' +
'</g>' +
'<g stroke="url(#gRain)" stroke-width="5.5" stroke-linecap="round">' +
'<line x1="34" y1="66" x2="28" y2="86"/><line x1="52" y1="68" x2="46" y2="90"/><line x1="70" y1="66" x2="64" y2="86"/>' +
'</g>',
snow:
'<g fill="url(#gCloud)">' +
'<ellipse cx="38" cy="40" rx="20" ry="15"/><ellipse cx="58" cy="31" rx="24" ry="19"/>' +
'<ellipse cx="77" cy="39" rx="15" ry="12"/><rect x="29" y="36" width="55" height="18" rx="9"/>' +
'</g>' +
'<g fill="url(#gSnow)">' +
'<circle cx="34" cy="72" r="4"/><circle cx="52" cy="79" r="4"/><circle cx="70" cy="72" r="4"/>' +
'<circle cx="43" cy="87" r="3.2"/><circle cx="61" cy="87" r="3.2"/>' +
'</g>',
thunderstorm:
'<g fill="url(#gCloudDark)">' +
'<ellipse cx="38" cy="38" rx="20" ry="15"/><ellipse cx="58" cy="29" rx="24" ry="19"/>' +
'<ellipse cx="77" cy="37" rx="15" ry="12"/><rect x="29" y="34" width="55" height="18" rx="9"/>' +
'</g>' +
'<polygon points="56,56 42,80 52,80 46,97 73,66 60,66 66,56" fill="url(#gBolt)"/>'
};
function getWeatherIconSVG(category) {
const body = ICON_BODIES[category] || ICON_BODIES.cloudy;
return '<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">' + iconDefs() + body + '</svg>';
}
function describeWeatherCode(code) {
const entry = WMO[code];
if (!entry) return { label: 'Unknown conditions', category: 'cloudy' };
return { label: entry[0], category: entry[1] };
}
function pad2(n) { return n < 10 ? '0' + n : '' + n; }
function todayUTCString() {
const now = new Date();
return now.getUTCFullYear() + '-' + pad2(now.getUTCMonth() + 1) + '-' + pad2(now.getUTCDate());
}
function isValidDateStr(s) {
if (!/^\d{4}-\d{2}-\d{2}$/.test(s)) return false;
const parts = s.split('-').map(Number);
const y = parts[0], m = parts[1], d = parts[2];
const dt = new Date(Date.UTC(y, m - 1, d));
return dt.getUTCFullYear() === y && dt.getUTCMonth() === m - 1 && dt.getUTCDate() === d;
}
function formatFullDate(dateStr) {
const parts = dateStr.split('-').map(Number);
const dt = new Date(Date.UTC(parts[0], parts[1] - 1, parts[2]));
return dt.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: 'UTC' });
}
function hourFromIso(iso) { return parseInt(iso.slice(11, 13), 10); }
function formatHourLabel(h) {
const hour12 = (h % 12 === 0) ? 12 : (h % 12);
return hour12 + ' ' + (h < 12 ? 'AM' : 'PM');
}
function formatCoords(lat, lon) {
const latDir = lat >= 0 ? 'N' : 'S';
const lonDir = lon >= 0 ? 'E' : 'W';
return Math.abs(lat).toFixed(2) + '°' + latDir + ', ' + Math.abs(lon).toFixed(2) + '°' + lonDir;
}
// ---- Query param parsing ----
const qs = new URLSearchParams(window.location.search);
let lat = parseFloat(qs.get('lat'));
if (!isFinite(lat) || lat < -90 || lat > 90) lat = DEFAULTS.lat;
let lon = parseFloat(qs.get('lon'));
if (!isFinite(lon) || lon < -180 || lon > 180) lon = DEFAULTS.lon;
let name = qs.get('name');
if (!name || !name.trim()) name = DEFAULTS.name;
const today = todayUTCString();
let dateParam = qs.get('date');
if (!dateParam || !isValidDateStr(dateParam)) dateParam = today;
const endpoint = (dateParam < today) ? '/api/om/archive' : '/api/om/forecast';
const apiUrl = endpoint + '?' + new URLSearchParams({
latitude: String(lat),
longitude: String(lon),
daily: 'temperature_2m_max,temperature_2m_min,weather_code',
hourly: 'temperature_2m',
timezone: 'UTC',
temperature_unit: 'celsius',
start_date: dateParam,
end_date: dateParam
}).toString();
// ---- Chart ----
function buildChart(times, temps, accent, accent2) {
const n = temps.length;
const W = 992, H = 190, TOP = 34, BOTTOM = 30;
const svgH = TOP + H + BOTTOM;
let tMin = Math.min.apply(null, temps);
let tMax = Math.max.apply(null, temps);
if (tMin === tMax) { tMin -= 1; tMax += 1; }
const range = tMax - tMin;
const padAmt = Math.max(range * 0.25, 2);
const domainMin = tMin - padAmt;
const domainMax = tMax + padAmt;
function xAt(i) { return n > 1 ? (i / (n - 1)) * W : W / 2; }
function yAt(t) { return TOP + H - ((t - domainMin) / (domainMax - domainMin)) * H; }
const pts = [];
for (let i = 0; i < n; i++) pts.push({ x: xAt(i), y: yAt(temps[i]), t: temps[i] });
let linePath = 'M ' + pts[0].x.toFixed(1) + ' ' + pts[0].y.toFixed(1);
for (let i = 0; i < pts.length - 1; i++) {
const p0 = pts[i], p1 = pts[i + 1];
const mx = ((p0.x + p1.x) / 2).toFixed(1);
const my = ((p0.y + p1.y) / 2).toFixed(1);
linePath += ' Q ' + p0.x.toFixed(1) + ' ' + p0.y.toFixed(1) + ' ' + mx + ' ' + my;
}
const lastPt = pts[pts.length - 1];
linePath += ' L ' + lastPt.x.toFixed(1) + ' ' + lastPt.y.toFixed(1);
const baseline = (TOP + H).toFixed(1);
const areaPath = linePath + ' L ' + lastPt.x.toFixed(1) + ' ' + baseline + ' L ' + pts[0].x.toFixed(1) + ' ' + baseline + ' Z';
let maxIdx = 0, minIdx = 0;
for (let i = 0; i < temps.length; i++) {
if (temps[i] > temps[maxIdx]) maxIdx = i;
if (temps[i] < temps[minIdx]) minIdx = i;
}
const gridLines = [0.25, 0.5, 0.75].map(function (f) {
const gy = (TOP + H * f).toFixed(1);
return '<line x1="0" y1="' + gy + '" x2="' + W + '" y2="' + gy + '" stroke="rgba(255,255,255,0.14)" stroke-width="1" stroke-dasharray="4 6"/>';
}).join('');
const hourTicks = [0, 3, 6, 9, 12, 15, 18, 21].filter(function (h) { return h < n; }).map(function (h) {
const px = xAt(h).toFixed(1);
return '<text x="' + px + '" y="' + (svgH - 8) + '" text-anchor="middle" class="chart-axis-label">' + formatHourLabel(hourFromIso(times[h])) + '</text>';
}).join('');
const dots = pts.map(function (p) {
return '<circle cx="' + p.x.toFixed(1) + '" cy="' + p.y.toFixed(1) + '" r="2.4" fill="#ffffff" opacity="0.5"/>';
}).join('');
const maxCallout = '<circle cx="' + pts[maxIdx].x.toFixed(1) + '" cy="' + pts[maxIdx].y.toFixed(1) + '" r="5" fill="#fff" stroke="' + accent + '" stroke-width="3"/>' +
'<text x="' + pts[maxIdx].x.toFixed(1) + '" y="' + (pts[maxIdx].y - 14).toFixed(1) + '" text-anchor="middle" class="chart-callout">' + Math.round(temps[maxIdx]) + '°</text>';
const minCallout = '<circle cx="' + pts[minIdx].x.toFixed(1) + '" cy="' + pts[minIdx].y.toFixed(1) + '" r="5" fill="#fff" stroke="' + accent2 + '" stroke-width="3"/>' +
'<text x="' + pts[minIdx].x.toFixed(1) + '" y="' + (pts[minIdx].y + 22).toFixed(1) + '" text-anchor="middle" class="chart-callout">' + Math.round(temps[minIdx]) + '°</text>';
const svg = '<svg width="' + W + '" height="' + svgH + '" viewBox="0 0 ' + W + ' ' + svgH + '" class="chart-svg">' +
'<defs><linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">' +
'<stop offset="0%" stop-color="' + accent + '" stop-opacity="0.5"/>' +
'<stop offset="100%" stop-color="' + accent + '" stop-opacity="0"/>' +
'</linearGradient></defs>' +
gridLines +
'<path d="' + areaPath + '" fill="url(#areaGrad)"/>' +
'<path d="' + linePath + '" fill="none" stroke="#ffffff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>' +
dots + maxCallout + minCallout + hourTicks +
'<line id="hoverLine" x1="0" y1="' + TOP + '" x2="0" y2="' + (TOP + H) + '" stroke="#ffffff" stroke-width="1.5" opacity="0"/>' +
'<circle id="hoverDot" cx="0" cy="0" r="5.5" fill="#ffffff" stroke="' + accent + '" stroke-width="3" opacity="0"/>' +
'<rect id="chartOverlay" x="0" y="0" width="' + W + '" height="' + svgH + '" fill="transparent"/>' +
'</svg>';
return { svg: svg, W: W, svgH: svgH, pts: pts, times: times, temps: temps };
}
function attachChartInteractivity(chart) {
const overlay = document.getElementById('chartOverlay');
const hoverLine = document.getElementById('hoverLine');
const hoverDot = document.getElementById('hoverDot');
const tooltip = document.getElementById('chartTooltip');
if (!overlay) return;
const svgEl = overlay.closest('svg');
overlay.addEventListener('mousemove', function (e) {
const rect = svgEl.getBoundingClientRect();
const relX = (e.clientX - rect.left) / rect.width * chart.W;
let idx = Math.round((relX / chart.W) * (chart.pts.length - 1));
idx = Math.max(0, Math.min(chart.pts.length - 1, idx));
const p = chart.pts[idx];
hoverLine.setAttribute('x1', p.x); hoverLine.setAttribute('x2', p.x); hoverLine.setAttribute('opacity', '1');
hoverDot.setAttribute('cx', p.x); hoverDot.setAttribute('cy', p.y); hoverDot.setAttribute('opacity', '1');
tooltip.style.opacity = '1';
tooltip.style.left = ((p.x / chart.W) * 100) + '%';
tooltip.style.top = Math.max(p.y - 46, 0) + 'px';
tooltip.textContent = formatHourLabel(hourFromIso(chart.times[idx])) + ' · ' + Math.round(chart.temps[idx]) + '°C';
});
overlay.addEventListener('mouseleave', function () {
hoverLine.setAttribute('opacity', '0');
hoverDot.setAttribute('opacity', '0');
tooltip.style.opacity = '0';
});
}
// ---- Rendering ----
const app = document.getElementById('app');
function renderLoading() {
document.body.className = 'theme-default';
app.innerHTML =
'<div class="card card--loading" role="status" aria-live="polite">' +
'<div class="skeleton sk-badge"></div>' +
'<div class="skeleton sk-title"></div>' +
'<div class="skeleton sk-subtitle"></div>' +
'<div class="hero-row">' +
'<div class="skeleton sk-icon"></div>' +
'<div class="skeleton sk-condition"></div>' +
'<div class="skeleton sk-stats"></div>' +
'</div>' +
'<div class="skeleton sk-chart"></div>' +
'<p class="loading-caption">Loading weather…</p>' +
'</div>';
}
function renderError(message) {
document.body.className = 'theme-default';
app.innerHTML =
'<div class="card card--error" role="alert">' +
'<div class="error-icon">' + WARNING_SVG + '</div>' +
'<h1 class="error-title">Weather unavailable</h1>' +
'<p class="error-message" id="errorMessage"></p>' +
'<p class="error-meta" id="errorMeta"></p>' +
'<button class="retry-btn" id="retryBtn" type="button">Try again</button>' +
'</div>';
document.getElementById('errorMessage').textContent = message;
document.getElementById('errorMeta').textContent = name + ' · ' + dateParam;
document.getElementById('retryBtn').addEventListener('click', loadWeather);
}
function renderCard(info) {
const desc = describeWeatherCode(info.code);
const meta = CATEGORY_META[desc.category] || CATEGORY_META.cloudy;
document.body.className = 'theme-' + meta.theme;
const relLabel = (dateParam === today) ? 'Today' : (dateParam > today ? 'Forecast' : 'Historical');
const dateLabel = formatFullDate(dateParam);
const maxT = Math.round(info.max);
const minT = Math.round(info.min);
const chart = buildChart(info.hourlyTimes, info.hourlyTemps, meta.accent, meta.accent2);
const rangeLabel = 'Hourly temperature chart ranging from ' + Math.round(Math.min.apply(null, info.hourlyTemps)) + ' to ' + Math.round(Math.max.apply(null, info.hourlyTemps)) + ' degrees Celsius';
app.innerHTML =
'<div class="card" style="--accent:' + meta.accent + ';--accent2:' + meta.accent2 + ';">' +
'<div class="card__header">' +
'<div><h1 class="location-name" id="locationName"></h1><p class="date-label" id="dateLabel"></p></div>' +
'<div class="badge" id="badgeLabel"></div>' +
'</div>' +
'<div class="hero-row">' +
'<div class="hero-icon" aria-hidden="true">' + getWeatherIconSVG(desc.category) + '</div>' +
'<div class="hero-condition">' +
'<p class="condition-label" id="conditionLabel"></p>' +
'<p class="coords-label" id="coordsLabel"></p>' +
'</div>' +
'<div class="hero-stats">' +
'<div class="stat stat--high"><span class="stat-label">↑ High</span><span class="stat-value" id="statHigh"></span></div>' +
'<div class="stat-divider"></div>' +
'<div class="stat stat--low"><span class="stat-label">↓ Low</span><span class="stat-value" id="statLow"></span></div>' +
'</div>' +
'</div>' +
'<div class="hourly-section">' +
'<h2 class="section-heading">Hourly Temperature · °C</h2>' +
'<div class="chart-wrap" id="chartWrap" style="width:' + chart.W + 'px;height:' + chart.svgH + 'px;" role="img" aria-label="' + rangeLabel + '">' +
chart.svg +
'<div class="chart-tooltip" id="chartTooltip"></div>' +
'</div>' +
'</div>' +
'<p class="card__footer" id="footerText"></p>' +
'</div>';
document.getElementById('locationName').textContent = name;
document.getElementById('dateLabel').textContent = dateLabel;
document.getElementById('badgeLabel').textContent = relLabel;
document.getElementById('conditionLabel').textContent = desc.label;
document.getElementById('coordsLabel').textContent = formatCoords(lat, lon);
document.getElementById('statHigh').textContent = maxT + '°C';
document.getElementById('statLow').textContent = minT + '°C';
document.getElementById('footerText').textContent = 'Source: Open-Meteo · ' + (endpoint === '/api/om/archive' ? 'Historical Archive API' : 'Forecast API');
document.title = name + ' · Weather';
attachChartInteractivity(chart);
}
function validateAndRender(data) {
const daily = data && data.daily;
const hourly = data && data.hourly;
const ok = daily && Array.isArray(daily.temperature_2m_max) && daily.temperature_2m_max.length &&
Array.isArray(daily.temperature_2m_min) && daily.temperature_2m_min.length &&
Array.isArray(daily.weather_code) && daily.weather_code.length &&
hourly && Array.isArray(hourly.time) && Array.isArray(hourly.temperature_2m) &&
hourly.time.length && hourly.time.length === hourly.temperature_2m.length;
if (!ok) {
renderError('Weather data for this location and date is unavailable.');
return;
}
renderCard({
max: daily.temperature_2m_max[0],
min: daily.temperature_2m_min[0],
code: daily.weather_code[0],
hourlyTimes: hourly.time,
hourlyTemps: hourly.temperature_2m
});
}
async function loadWeather() {
renderLoading();
try {
const res = await fetch(apiUrl);
let data;
try {
data = await res.json();
} catch (parseErr) {
throw new Error('The server returned an unreadable response.');
}
if (!res.ok) {
const reason = (data && data.reason) ? data.reason : ('Request failed with status ' + res.status + '.');
throw new Error(reason);
}
if (data && data.error) {
throw new Error(data.reason || 'The weather service returned an error.');
}
validateAndRender(data);
} catch (err) {
renderError((err && err.message) ? err.message : 'Something went wrong while loading weather data.');
}
}
loadWeather();
})();
</script>
</body>
</html>L1 — cheap deterministic descriptors
| bytes total | 29,003 | html / css / js | 291 / 7,375 / 21,337 |
|---|---|---|---|
| dom nodes | 10 | dom depth | 3 |
| css rules | 70 | js present | yes |
| brightness | 101.1 | contrast | 26.3 |
| colorfulness | 20.8 | whitespace | 31.5% |
This slot's telemetry
| prompt tokens | 48 | completion tokens | 120,348 |
|---|---|---|---|
| total tokens | 120,396 | wall | 1,380.5 s |
| cost | — | request id | — |
config.json585 B
{
"N": 2,
"auth": {
"credential_ref": "WCB_NONE",
"method": "oauth-login"
},
"billing": "plan",
"config_id": "claude-sonnet-5-eff-max--cli--claude-code--dev",
"effort": "max",
"family": "claude",
"m": {
"min": 2,
"q": 2
},
"model_id": "claude-sonnet-5",
"protocol": "cli",
"served_model": "claude-haiku-4-5-20251001",
"telemetry": {
"completion_tokens": 338250,
"cost_usd": null,
"prompt_tokens": 92,
"total_tokens": 338342,
"wall_ms": 3794199
},
"transport": "claude-code-cli-headless",
"vendor_sanction_ref": null
}send-log2.5 KB
{
"N": 2,
"batch_id": "2026-07-20--refill4-cc-sonnet5-max",
"config_id": "claude-sonnet-5-eff-max--cli--claude-code--dev",
"positions": [
{
"attempts": [
{
"attempt_index": 0,
"backoff_ms": null,
"charged": true,
"ended_at": "2026-07-20T11:35:38.122160+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-20T11:25:05.181904+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-20T11:58:43.086041+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-20T11:35:42.572651+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-20T12:23:34.901949+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-20T11:58:47.059152+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-20T12:28:32.176241+00:00",
"http_status": null,
"outcome": "valid",
"reached_model": true,
"reason": "ok",
"request_id": null,
"started_at": "2026-07-20T12:23:39.224864+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
}
}
}