gpt-5.6-luna @ max · codex-oauth

codex-oauthmax
config
gpt-5.6-luna-eff-max--cli--codex-oauth--dev
batch
2026-07-19--unified
transport
codex-cli-oauth-chatgpt
protocol
cli · plan
served model
gpt-5.6-luna
captured
Jul 18, 2026, 11:54 AM · N=2
variant
live
slot 0 · P-q · sandboxed iframe
gpt-5.6-luna @max · codex-oauth P-q slot 0 screenshot

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

within session 2026-07-19--unified

similarity measures convergence within this session — not quality.

Fidelity — does the card show the right data?

  • namematch
  • conditionnot-foundicon-only
  • datematch
  • max tempnot-foundno-temperature-candidate
  • min tempnot-foundno-temperature-candidate
  • hourlynot-foundcoverage · 0 match · 0 mismatch · 24 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=device-width, initial-scale=1">
  <meta name="color-scheme" content="dark">
  <link rel="icon" href="data:,">
  <title>Weather card</title>
  <style>
    :root {
      --ink: #eff9fb;
      --muted: #91acb8;
      --dim: #63828e;
      --line: rgba(170, 225, 233, 0.14);
      --panel: rgba(12, 35, 47, 0.76);
      --panel-deep: rgba(6, 22, 33, 0.62);
      --accent: #68d6df;
      --accent-rgb: 104, 214, 223;
      --warm: #ffd078;
    }

    * {
      box-sizing: border-box;
    }

    [hidden] {
      display: none !important;
    }

    html,
    body {
      min-height: 100%;
    }

    body {
      margin: 0;
      min-width: 1050px;
      overflow: hidden;
      color: var(--ink);
      background:
        radial-gradient(circle at 17% 12%, rgba(47, 131, 150, 0.2), transparent 30rem),
        radial-gradient(circle at 86% 90%, rgba(74, 68, 133, 0.21), transparent 27rem),
        #08131f;
      font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      -webkit-font-smoothing: antialiased;
    }

    body[data-weather="clear"] {
      --accent: #ffd276;
      --accent-rgb: 255, 210, 118;
    }

    body[data-weather="partly"] {
      --accent: #ffc778;
      --accent-rgb: 255, 199, 120;
    }

    body[data-weather="cloud"] {
      --accent: #8dd9e2;
      --accent-rgb: 141, 217, 226;
    }

    body[data-weather="fog"] {
      --accent: #b7c9dd;
      --accent-rgb: 183, 201, 221;
    }

    body[data-weather="drizzle"],
    body[data-weather="rain"] {
      --accent: #68d6df;
      --accent-rgb: 104, 214, 223;
    }

    body[data-weather="snow"] {
      --accent: #c0ecff;
      --accent-rgb: 192, 236, 255;
    }

    body[data-weather="storm"] {
      --accent: #e9a5d7;
      --accent-rgb: 233, 165, 215;
    }

    .page-shell {
      position: relative;
      display: grid;
      place-items: center;
      min-height: 100vh;
      padding: 36px;
      overflow: hidden;
    }

    .ambient-grid {
      position: absolute;
      inset: -10%;
      opacity: 0.24;
      background-image:
        linear-gradient(rgba(144, 205, 215, 0.07) 1px, transparent 1px),
        linear-gradient(90deg, rgba(144, 205, 215, 0.07) 1px, transparent 1px);
      background-size: 58px 58px;
      transform: perspective(900px) rotateX(54deg) translateY(24%);
      transform-origin: center bottom;
      pointer-events: none;
    }

    .ambient-glow {
      position: absolute;
      width: 420px;
      height: 420px;
      border: 1px solid rgba(131, 212, 223, 0.12);
      border-radius: 50%;
      pointer-events: none;
    }

    .ambient-glow.one {
      top: -250px;
      right: -70px;
      box-shadow: 0 0 0 42px rgba(92, 183, 196, 0.025), 0 0 0 84px rgba(92, 183, 196, 0.02);
    }

    .ambient-glow.two {
      bottom: -330px;
      left: -110px;
      width: 500px;
      height: 500px;
      border-color: rgba(146, 112, 211, 0.12);
    }

    .weather-card {
      --card-radius: 30px;
      position: relative;
      isolation: isolate;
      display: flex;
      flex-direction: column;
      width: min(1140px, calc(100vw - 72px));
      height: min(728px, calc(100vh - 72px));
      min-height: 620px;
      overflow: hidden;
      border: 1px solid rgba(178, 229, 235, 0.17);
      border-radius: var(--card-radius);
      background:
        linear-gradient(140deg, rgba(24, 57, 68, 0.97), rgba(8, 26, 38, 0.985) 74%),
        #0b202d;
      box-shadow:
        0 36px 90px rgba(0, 0, 0, 0.42),
        0 8px 24px rgba(0, 0, 0, 0.2),
        inset 0 1px 0 rgba(255, 255, 255, 0.09);
    }

    .weather-card::before {
      content: "";
      position: absolute;
      z-index: -1;
      top: -34%;
      right: -11%;
      width: 76%;
      height: 118%;
      border: 1px solid rgba(var(--accent-rgb), 0.12);
      border-radius: 50%;
      transform: rotate(-23deg);
      pointer-events: none;
    }

    .weather-card::after {
      content: "";
      position: absolute;
      z-index: -1;
      inset: auto 0 0;
      height: 42%;
      opacity: 0.31;
      background:
        linear-gradient(rgba(129, 201, 210, 0.045) 1px, transparent 1px),
        linear-gradient(90deg, rgba(129, 201, 210, 0.045) 1px, transparent 1px);
      background-size: 42px 42px;
      mask-image: linear-gradient(to top, black, transparent);
      pointer-events: none;
    }

    .topbar {
      position: relative;
      z-index: 2;
      display: flex;
      flex: 0 0 80px;
      align-items: center;
      justify-content: space-between;
      padding: 20px 32px 18px;
      border-bottom: 1px solid rgba(173, 226, 233, 0.11);
    }

    .brand-lockup,
    .top-status,
    .date-line,
    .condition-line,
    .overview-note,
    .footer-meta,
    .hourly-foot,
    .chart-caption,
    .reading-count {
      display: flex;
      align-items: center;
    }

    .brand-lockup {
      gap: 12px;
    }

    .brand-symbol {
      display: grid;
      width: 36px;
      height: 36px;
      place-items: center;
      border: 1px solid rgba(var(--accent-rgb), 0.35);
      border-radius: 12px;
      background: rgba(var(--accent-rgb), 0.1);
      box-shadow: inset 0 0 18px rgba(var(--accent-rgb), 0.06);
    }

    .brand-symbol svg {
      width: 22px;
      height: 22px;
    }

    .brand-symbol path,
    .brand-symbol circle {
      fill: none;
      stroke: var(--accent);
      stroke-linecap: round;
      stroke-width: 2;
    }

    .brand-symbol circle {
      fill: var(--accent);
      stroke: none;
    }

    .brand-overline,
    .footer-label,
    .eyebrow,
    .reading-kicker,
    .range-head,
    .state-eyebrow,
    .panel-kicker {
      color: var(--dim);
      font-size: 9px;
      font-weight: 750;
      letter-spacing: 0.2em;
      line-height: 1.2;
      text-transform: uppercase;
    }

    .brand-overline {
      margin-bottom: 4px;
      color: var(--accent);
      font-size: 8px;
      letter-spacing: 0.18em;
    }

    .brand-title {
      color: var(--ink);
      font-size: 14px;
      font-weight: 700;
      letter-spacing: 0.15em;
      line-height: 1;
    }

    .top-status {
      gap: 9px;
      color: var(--muted);
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.17em;
      text-transform: uppercase;
    }

    .status-dot,
    .condition-dot,
    .mini-dot,
    .foot-dot {
      display: inline-block;
      flex: none;
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--accent);
      box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.09), 0 0 12px rgba(var(--accent-rgb), 0.75);
    }

    .status-dot.loading {
      animation: pulse 1.35s ease-in-out infinite;
    }

    .status-dot.ready {
      background: #7ae5b7;
      box-shadow: 0 0 0 4px rgba(122, 229, 183, 0.09), 0 0 12px rgba(122, 229, 183, 0.65);
    }

    .status-dot.error {
      background: #ff9b9b;
      box-shadow: 0 0 0 4px rgba(255, 155, 155, 0.09), 0 0 12px rgba(255, 155, 155, 0.6);
    }

    .weather-content {
      display: flex;
      flex: 1 1 auto;
      min-height: 0;
      flex-direction: column;
    }

    .main-grid {
      display: grid;
      grid-template-columns: minmax(360px, 0.82fr) minmax(0, 1.18fr);
      flex: 1 1 auto;
      min-height: 0;
      gap: 20px;
      padding: 20px 32px 16px;
    }

    .overview-panel,
    .hourly-panel {
      position: relative;
      overflow: hidden;
      min-width: 0;
      border: 1px solid rgba(175, 228, 234, 0.12);
      border-radius: 23px;
      background: var(--panel);
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
    }

    .overview-panel {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      padding: 28px;
    }

    .overview-panel::before {
      content: "";
      position: absolute;
      top: -120px;
      left: -120px;
      width: 310px;
      height: 310px;
      border-radius: 50%;
      background: radial-gradient(circle, rgba(var(--accent-rgb), 0.15), transparent 69%);
      pointer-events: none;
    }

    .overview-panel > *,
    .hourly-panel > * {
      position: relative;
      z-index: 1;
    }

    .eyebrow {
      display: flex;
      align-items: center;
      gap: 8px;
    }

    .eyebrow-line {
      width: 20px;
      height: 1px;
      background: var(--accent);
      box-shadow: 0 0 10px rgba(var(--accent-rgb), 0.6);
    }

    .location-name {
      max-width: 100%;
      margin: 13px 0 8px;
      overflow: hidden;
      color: var(--ink);
      font-size: clamp(38px, 4vw, 52px);
      font-weight: 680;
      letter-spacing: -0.055em;
      line-height: 0.98;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    .date-line {
      gap: 10px;
      color: var(--muted);
      font-size: 14px;
      font-weight: 500;
    }

    .utc-pill,
    .unit-badge {
      display: inline-flex;
      align-items: center;
      gap: 7px;
      border: 1px solid rgba(var(--accent-rgb), 0.25);
      border-radius: 999px;
      background: rgba(var(--accent-rgb), 0.08);
      color: var(--accent);
      font-size: 9px;
      font-weight: 800;
      letter-spacing: 0.13em;
      line-height: 1;
      text-transform: uppercase;
    }

    .utc-pill {
      padding: 6px 8px 5px;
    }

    .hero-readout {
      display: flex;
      align-items: center;
      gap: 22px;
      margin: 25px 0 22px;
    }

    .hero-icon {
      display: grid;
      flex: 0 0 128px;
      width: 128px;
      height: 128px;
      place-items: center;
      border: 1px solid rgba(var(--accent-rgb), 0.21);
      border-radius: 31px;
      background:
        radial-gradient(circle at 50% 36%, rgba(var(--accent-rgb), 0.2), transparent 58%),
        rgba(5, 20, 30, 0.55);
      box-shadow:
        0 15px 30px rgba(0, 0, 0, 0.18),
        inset 0 1px 0 rgba(255, 255, 255, 0.06);
    }

    .hero-icon svg {
      width: 100px;
      height: 100px;
      overflow: visible;
    }

    .hero-icon .sun-rays {
      fill: none;
      stroke: var(--accent);
      stroke-linecap: round;
      stroke-width: 3;
    }

    .hero-icon .sun-disc {
      fill: var(--accent);
    }

    .hero-icon .cloud-shape {
      fill: #b9e8ed;
      stroke: #effdff;
      stroke-linejoin: round;
      stroke-width: 2;
    }

    .hero-icon .cloud-shadow {
      fill: rgba(86, 145, 158, 0.46);
    }

    .hero-icon .rain-lines,
    .hero-icon .fog-lines {
      fill: none;
      stroke: #76d9e6;
      stroke-linecap: round;
      stroke-width: 3;
    }

    .hero-icon .snow-lines {
      fill: none;
      stroke: #c4efff;
      stroke-linecap: round;
      stroke-width: 2.6;
    }

    .hero-icon .lightning {
      fill: var(--accent);
      stroke: #fff4c9;
      stroke-linejoin: round;
      stroke-width: 1.3;
    }

    .reading-copy {
      min-width: 0;
    }

    .reading-kicker {
      margin-bottom: 7px;
      color: var(--accent);
      letter-spacing: 0.16em;
    }

    .reading-temp {
      display: flex;
      align-items: flex-start;
      color: var(--ink);
      font-size: 76px;
      font-variant-numeric: tabular-nums;
      font-weight: 630;
      letter-spacing: -0.085em;
      line-height: 0.82;
      white-space: nowrap;
    }

    .degree-mark {
      margin-top: 5px;
      margin-left: 3px;
      color: var(--accent);
      font-size: 29px;
      font-weight: 500;
      letter-spacing: -0.02em;
    }

    .unit-mark {
      margin-top: 13px;
      margin-left: 3px;
      color: var(--accent);
      font-size: 16px;
      font-weight: 800;
      letter-spacing: 0;
    }

    .condition-line {
      gap: 9px;
      margin-top: 17px;
      color: var(--ink);
      font-size: 16px;
      font-weight: 650;
    }

    .condition-dot {
      width: 6px;
      height: 6px;
      box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.08), 0 0 10px rgba(var(--accent-rgb), 0.7);
    }

    .condition-detail {
      max-width: 190px;
      margin: 8px 0 0;
      color: var(--muted);
      font-size: 11px;
      line-height: 1.45;
    }

    .range-card {
      padding: 15px 16px 14px;
      border: 1px solid rgba(177, 226, 231, 0.11);
      border-radius: 16px;
      background: rgba(5, 20, 30, 0.38);
    }

    .range-head,
    .range-endpoints {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .range-head strong {
      color: var(--accent);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.02em;
      text-transform: none;
    }

    .range-track {
      position: relative;
      height: 7px;
      margin: 14px 0 10px;
      overflow: hidden;
      border-radius: 999px;
      background: rgba(177, 226, 231, 0.1);
    }

    .range-track::before {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(90deg, rgba(137, 190, 220, 0.22), rgba(var(--accent-rgb), 0.27), rgba(255, 187, 111, 0.28));
    }

    .range-fill {
      position: absolute;
      top: 0;
      bottom: 0;
      left: 20%;
      width: 60%;
      min-width: 10px;
      border-radius: inherit;
      background: linear-gradient(90deg, #8ac9e4, var(--accent), #ffd17e);
      box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.52);
    }

    .range-endpoints {
      color: var(--dim);
      font-size: 9px;
      font-weight: 750;
      letter-spacing: 0.14em;
      text-transform: uppercase;
    }

    .range-endpoints b {
      margin-left: 4px;
      color: var(--muted);
      font-size: 12px;
      font-weight: 650;
      letter-spacing: 0;
    }

    .overview-note {
      gap: 8px;
      margin-top: 18px;
      color: var(--dim);
      font-size: 10px;
      font-weight: 650;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .overview-note .note-mark {
      width: 13px;
      height: 13px;
      border: 1px solid rgba(var(--accent-rgb), 0.42);
      border-radius: 4px;
      background:
        linear-gradient(90deg, transparent 42%, var(--accent) 42%, var(--accent) 58%, transparent 58%),
        linear-gradient(transparent 42%, var(--accent) 42%, var(--accent) 58%, transparent 58%);
      opacity: 0.8;
    }

    .hourly-panel {
      display: flex;
      flex-direction: column;
      padding: 24px;
      background:
        linear-gradient(145deg, rgba(15, 43, 54, 0.83), rgba(7, 25, 37, 0.74)),
        var(--panel-deep);
    }

    .hourly-header {
      display: flex;
      flex: 0 0 auto;
      align-items: flex-start;
      justify-content: space-between;
      gap: 18px;
    }

    .panel-kicker {
      display: flex;
      align-items: center;
      gap: 8px;
      margin-bottom: 8px;
      color: var(--accent);
    }

    .panel-kicker::before {
      content: "";
      width: 18px;
      height: 1px;
      background: var(--accent);
      box-shadow: 0 0 10px rgba(var(--accent-rgb), 0.6);
    }

    .hourly-title {
      margin: 0;
      color: var(--ink);
      font-size: 26px;
      font-weight: 650;
      letter-spacing: -0.045em;
      line-height: 1;
    }

    .unit-badge {
      flex: none;
      padding: 8px 10px 7px;
      color: var(--muted);
      border-color: rgba(174, 226, 232, 0.16);
      background: rgba(5, 20, 30, 0.33);
    }

    .unit-badge .mini-dot {
      width: 5px;
      height: 5px;
      background: var(--accent);
      box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.72);
    }

    .chart-caption {
      justify-content: space-between;
      margin: 17px 2px 9px;
      color: var(--dim);
      font-size: 10px;
      font-weight: 650;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .reading-count {
      gap: 7px;
      color: var(--muted);
      font-variant-numeric: tabular-nums;
      letter-spacing: 0.04em;
      text-transform: none;
    }

    .reading-count .mini-dot {
      width: 4px;
      height: 4px;
      box-shadow: 0 0 7px rgba(var(--accent-rgb), 0.6);
    }

    .chart-shell {
      position: relative;
      flex: 0 0 222px;
      overflow: hidden;
      border: 1px solid rgba(172, 225, 232, 0.11);
      border-radius: 17px;
      background:
        radial-gradient(circle at 68% 38%, rgba(var(--accent-rgb), 0.08), transparent 35%),
        rgba(4, 18, 28, 0.47);
    }

    .chart-shell::before {
      content: "";
      position: absolute;
      inset: 0;
      opacity: 0.38;
      background: linear-gradient(120deg, transparent 0 34%, rgba(255, 255, 255, 0.025) 48%, transparent 65%);
      pointer-events: none;
    }

    #temperatureGraph {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
    }

    #temperatureGraph text {
      fill: #6e909b;
      font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
      font-size: 11px;
      font-weight: 650;
      letter-spacing: 0.02em;
    }

    #temperatureGraph .chart-gridline {
      stroke: rgba(161, 216, 224, 0.1);
      stroke-dasharray: 3 7;
      stroke-width: 1;
    }

    #temperatureGraph .chart-axis {
      stroke: rgba(161, 216, 224, 0.18);
      stroke-width: 1;
    }

    #temperatureGraph .chart-area {
      fill: url("#areaFill");
    }

    #temperatureGraph .chart-line {
      fill: none;
      stroke: var(--accent);
      stroke-linecap: round;
      stroke-linejoin: round;
      stroke-width: 3;
      filter: drop-shadow(0 0 6px rgba(var(--accent-rgb), 0.36));
    }

    #temperatureGraph .chart-point {
      fill: var(--accent);
      stroke: #dffbfc;
      stroke-width: 1.5;
    }

    #temperatureGraph .chart-point.extreme {
      fill: #f9ffff;
      stroke: var(--accent);
      stroke-width: 2.5;
    }

    #temperatureGraph .accent-stop {
      stop-color: var(--accent);
    }

    .hourly-grid {
      display: grid;
      grid-template-columns: repeat(12, minmax(0, 1fr));
      flex: 0 0 auto;
      gap: 6px;
      margin-top: 12px;
    }

    .hour-cell {
      display: flex;
      min-width: 0;
      height: 47px;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 5px;
      border: 1px solid rgba(171, 224, 231, 0.09);
      border-radius: 10px;
      background: rgba(4, 19, 29, 0.44);
      text-align: center;
      transition: border-color 160ms ease, background 160ms ease, transform 160ms ease;
    }

    .hour-cell:nth-child(6n + 1) {
      border-color: rgba(var(--accent-rgb), 0.28);
      background: rgba(var(--accent-rgb), 0.06);
    }

    .hour-cell:hover {
      border-color: rgba(var(--accent-rgb), 0.5);
      background: rgba(var(--accent-rgb), 0.11);
      transform: translateY(-2px);
    }

    .hour-cell .hour-label {
      color: var(--dim);
      font-size: 9px;
      font-variant-numeric: tabular-nums;
      font-weight: 700;
      line-height: 1;
    }

    .hour-cell .hour-temperature {
      color: var(--ink);
      font-size: 13px;
      font-variant-numeric: tabular-nums;
      font-weight: 700;
      letter-spacing: -0.02em;
      line-height: 1;
    }

    .hourly-foot {
      justify-content: space-between;
      gap: 12px;
      margin-top: 13px;
      color: var(--dim);
      font-size: 10px;
      font-weight: 600;
    }

    .hourly-foot .foot-dot {
      width: 5px;
      height: 5px;
      margin-right: 2px;
      box-shadow: 0 0 8px rgba(var(--accent-rgb), 0.65);
    }

    .hourly-foot .foot-range {
      margin-left: auto;
      color: var(--muted);
      font-variant-numeric: tabular-nums;
    }

    .card-footer {
      display: flex;
      flex: 0 0 52px;
      align-items: center;
      justify-content: space-between;
      gap: 24px;
      margin: 0 32px;
      border-top: 1px solid rgba(173, 226, 233, 0.11);
    }

    .footer-meta {
      gap: 12px;
      min-width: 0;
      color: var(--muted);
      font-size: 10px;
      font-variant-numeric: tabular-nums;
      font-weight: 600;
    }

    .footer-label {
      color: var(--dim);
      font-size: 8px;
    }

    .footer-center {
      color: var(--dim);
      font-size: 8px;
      font-weight: 750;
      letter-spacing: 0.16em;
      text-transform: uppercase;
    }

    .state-panel {
      display: grid;
      flex: 1 1 auto;
      min-height: 0;
      place-items: center;
      padding: 40px;
    }

    .state-card {
      width: min(480px, 100%);
      padding: 35px 38px 32px;
      border: 1px solid rgba(173, 226, 233, 0.12);
      border-radius: 23px;
      background: rgba(7, 25, 37, 0.47);
      text-align: center;
      box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
    }

    .loader-orbit {
      position: relative;
      width: 66px;
      height: 66px;
      margin: 0 auto 22px;
      border: 1px solid rgba(var(--accent-rgb), 0.22);
      border-radius: 50%;
      box-shadow: 0 0 30px rgba(var(--accent-rgb), 0.08);
    }

    .loader-orbit::before,
    .loader-orbit::after {
      content: "";
      position: absolute;
      border-radius: 50%;
    }

    .loader-orbit::before {
      inset: 9px;
      border: 1px dashed rgba(var(--accent-rgb), 0.42);
      animation: spin 4s linear infinite;
    }

    .loader-orbit::after {
      top: 3px;
      left: 50%;
      width: 7px;
      height: 7px;
      background: var(--accent);
      box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.9);
      transform: translateX(-50%);
      animation: orbit 2.2s ease-in-out infinite;
    }

    .state-eyebrow {
      margin-bottom: 10px;
      color: var(--accent);
    }

    .state-title {
      margin: 0;
      color: var(--ink);
      font-size: 25px;
      font-weight: 650;
      letter-spacing: -0.04em;
    }

    .state-message {
      margin: 12px auto 0;
      max-width: 340px;
      color: var(--muted);
      font-size: 13px;
      line-height: 1.55;
    }

    .state-context {
      margin: 18px 0 0;
      color: var(--dim);
      font-size: 10px;
      font-weight: 700;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .retry-button {
      margin-top: 22px;
      padding: 11px 17px;
      border: 1px solid rgba(var(--accent-rgb), 0.36);
      border-radius: 999px;
      outline: none;
      background: rgba(var(--accent-rgb), 0.1);
      color: var(--accent);
      cursor: pointer;
      font: inherit;
      font-size: 10px;
      font-weight: 800;
      letter-spacing: 0.14em;
      text-transform: uppercase;
      transition: background 160ms ease, border-color 160ms ease, transform 160ms ease;
    }

    .retry-button:hover,
    .retry-button:focus-visible {
      border-color: rgba(var(--accent-rgb), 0.66);
      background: rgba(var(--accent-rgb), 0.18);
      transform: translateY(-1px);
    }

    .retry-button:focus-visible {
      box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.15);
    }

    @keyframes spin {
      to {
        transform: rotate(360deg);
      }
    }

    @keyframes orbit {
      0%, 100% {
        transform: translateX(-50%) scale(0.85);
        opacity: 0.72;
      }
      50% {
        transform: translateX(-50%) scale(1.18);
        opacity: 1;
      }
    }

    @keyframes pulse {
      0%, 100% {
        opacity: 0.45;
        transform: scale(0.8);
      }
      50% {
        opacity: 1;
        transform: scale(1.1);
      }
    }

    @media (max-width: 900px) {
      body {
        min-width: 0;
        overflow: auto;
      }

      .page-shell {
        padding: 18px;
      }

      .weather-card {
        width: 100%;
        height: auto;
        min-height: 700px;
      }

      .main-grid {
        grid-template-columns: 1fr;
      }

      .hourly-panel {
        min-height: 510px;
      }
    }
  </style>
</head>
<body>
  <div class="page-shell">
    <div class="ambient-grid" aria-hidden="true"></div>
    <div class="ambient-glow one" aria-hidden="true"></div>
    <div class="ambient-glow two" aria-hidden="true"></div>

    <main class="weather-card" id="weatherCard" aria-busy="true">
      <header class="topbar">
        <div class="brand-lockup">
          <span class="brand-symbol" aria-hidden="true">
            <svg viewBox="0 0 24 24">
              <circle cx="12" cy="12" r="3.4"></circle>
              <path d="M12 2.5v3M12 18.5v3M2.5 12h3M18.5 12h3M5.3 5.3l2.1 2.1M16.6 16.6l2.1 2.1M18.7 5.3l-2.1 2.1M7.4 16.6l-2.1 2.1"></path>
            </svg>
          </span>
          <span>
            <span class="brand-overline">Atmosphere / Daily brief</span>
            <span class="brand-title">WEATHER CARD</span>
          </span>
        </div>

        <div class="top-status">
          <span class="status-dot loading" id="statusDot"></span>
          <span id="sourceLabel">WAITING FOR DATA</span>
        </div>
      </header>

      <section class="state-panel" id="loadingState" aria-live="polite">
        <div class="state-card">
          <div class="loader-orbit" aria-hidden="true"></div>
          <div class="state-eyebrow">Connecting to weather data</div>
          <h1 class="state-title">Reading the atmosphere</h1>
          <p class="state-message" id="loadingMessage">Retrieving the forecast and hourly temperatures.</p>
          <p class="state-context" id="loadingContext">Berlin · UTC</p>
        </div>
      </section>

      <section class="state-panel" id="errorState" aria-live="assertive" hidden>
        <div class="state-card">
          <div class="state-eyebrow">Local weather service</div>
          <h1 class="state-title">Weather data could not be loaded</h1>
          <p class="state-message" id="errorDetail">No usable readings were returned for this date.</p>
          <p class="state-context" id="errorContext">Berlin · UTC</p>
          <button class="retry-button" id="retryButton" type="button">Try again</button>
        </div>
      </section>

      <section class="weather-content" id="weatherContent" hidden>
        <div class="main-grid">
          <section class="overview-panel" aria-labelledby="locationName">
            <div class="location-block">
              <div class="eyebrow">
                <span class="eyebrow-line" aria-hidden="true"></span>
                <span id="reportType">Forecast / UTC</span>
              </div>
              <h1 class="location-name" id="locationName">Berlin</h1>
              <div class="date-line">
                <span id="dateLabel">Today</span>
                <span class="utc-pill">UTC</span>
              </div>
            </div>

            <div class="hero-readout">
              <div class="hero-icon" id="heroIcon" aria-hidden="true"></div>
              <div class="reading-copy">
                <div class="reading-kicker">Daytime high</div>
                <div class="reading-temp">
                  <span id="maxTemp">--</span>
                  <span class="degree-mark">°</span>
                  <span class="unit-mark">C</span>
                </div>
                <div class="condition-line">
                  <span class="condition-dot" aria-hidden="true"></span>
                  <span id="conditionName">Loading</span>
                </div>
                <p class="condition-detail" id="conditionDetail">Preparing the daily weather summary.</p>
              </div>
            </div>

            <div>
              <div class="range-card">
                <div class="range-head">
                  <span>Thermal range</span>
                  <strong id="rangeValue">--</strong>
                </div>
                <div class="range-track" aria-hidden="true">
                  <div class="range-fill" id="rangeFill"></div>
                </div>
                <div class="range-endpoints">
                  <span>Low <b id="lowEndpoint">--</b></span>
                  <span>High <b id="highEndpoint">--</b></span>
                </div>
              </div>

              <div class="overview-note">
                <span class="note-mark" aria-hidden="true"></span>
                <span>One complete UTC day</span>
              </div>
            </div>
          </section>

          <section class="hourly-panel" aria-labelledby="hourlyHeading">
            <div class="hourly-header">
              <div>
                <div class="panel-kicker">24-hour trace</div>
                <h2 class="hourly-title" id="hourlyHeading">A day in motion</h2>
              </div>
              <div class="unit-badge">
                <span class="mini-dot" aria-hidden="true"></span>
                °C / UTC
              </div>
            </div>

            <div class="chart-caption">
              <span id="chartDescriptor">Hourly temperature trace</span>
              <span class="reading-count">
                <span class="mini-dot" aria-hidden="true"></span>
                <span id="readingCount">0 readings</span>
              </span>
            </div>

            <div class="chart-shell">
              <svg id="temperatureGraph" viewBox="0 0 1000 230" preserveAspectRatio="none" role="img" aria-label="Hourly temperature chart"></svg>
            </div>

            <div class="hourly-grid" id="hourlyGrid" role="list" aria-label="Hourly temperatures"></div>

            <div class="hourly-foot">
              <span><span class="foot-dot" aria-hidden="true"></span>Every reading shown</span>
              <span class="foot-range" id="hourlySpan">--</span>
            </div>
          </section>
        </div>

        <footer class="card-footer">
          <div class="footer-meta">
            <span class="footer-label">Coordinates</span>
            <span id="coordinateLabel">52.52° N / 13.41° E</span>
          </div>
          <div class="footer-center">Open-Meteo compatible · Celsius</div>
          <div class="footer-meta">
            <span class="footer-label">Data window</span>
            <span id="footerMode">Forecast window</span>
          </div>
        </footer>
      </section>
    </main>
  </div>

  <script>
    (() => {
      "use strict";

      const $ = (selector) => document.querySelector(selector);

      const elements = {
        card: $("#weatherCard"),
        statusDot: $("#statusDot"),
        sourceLabel: $("#sourceLabel"),
        loadingState: $("#loadingState"),
        loadingMessage: $("#loadingMessage"),
        loadingContext: $("#loadingContext"),
        errorState: $("#errorState"),
        errorDetail: $("#errorDetail"),
        errorContext: $("#errorContext"),
        retryButton: $("#retryButton"),
        weatherContent: $("#weatherContent"),
        reportType: $("#reportType"),
        locationName: $("#locationName"),
        dateLabel: $("#dateLabel"),
        heroIcon: $("#heroIcon"),
        maxTemp: $("#maxTemp"),
        minTemp: $("#minTemp"),
        conditionName: $("#conditionName"),
        conditionDetail: $("#conditionDetail"),
        rangeValue: $("#rangeValue"),
        rangeFill: $("#rangeFill"),
        lowEndpoint: $("#lowEndpoint"),
        highEndpoint: $("#highEndpoint"),
        chartDescriptor: $("#chartDescriptor"),
        readingCount: $("#readingCount"),
        temperatureGraph: $("#temperatureGraph"),
        hourlyGrid: $("#hourlyGrid"),
        hourlySpan: $("#hourlySpan"),
        coordinateLabel: $("#coordinateLabel"),
        footerMode: $("#footerMode")
      };

      const query = new URLSearchParams(window.location.search);
      const todayUtc = new Date().toISOString().slice(0, 10);

      function isValidIsoDate(value) {
        if (!/^\d{4}-\d{2}-\d{2}$/.test(value || "")) {
          return false;
        }

        const [year, month, day] = value.split("-").map(Number);
        if (year < 1 || month < 1 || month > 12 || day < 1 || day > 31) {
          return false;
        }

        const date = new Date(Date.UTC(year, month - 1, day));
        return date.getUTCFullYear() === year &&
          date.getUTCMonth() === month - 1 &&
          date.getUTCDate() === day;
      }

      function parseCoordinate(value, fallback, minimum, maximum) {
        if (value === null || value.trim() === "") {
          return fallback;
        }

        const number = Number(value);
        return Number.isFinite(number) && number >= minimum && number <= maximum
          ? number
          : fallback;
      }

      const selectedDate = isValidIsoDate(query.get("date")) ? query.get("date") : todayUtc;
      const latitude = parseCoordinate(query.get("lat"), 52.52, -90, 90);
      const longitude = parseCoordinate(query.get("lon"), 13.405, -180, 180);
      const placeName = (query.get("name") || "").trim() || "Berlin";
      const isArchive = selectedDate < todayUtc;
      const endpoint = isArchive ? "/api/om/archive" : "/api/om/forecast";
      const modeLabel = isArchive ? "Archive" : "Forecast";

      const requestParams = new URLSearchParams({
        latitude: String(latitude),
        longitude: String(longitude),
        daily: "temperature_2m_max,temperature_2m_min,weather_code",
        hourly: "temperature_2m",
        timezone: "UTC",
        temperature_unit: "celsius",
        start_date: selectedDate,
        end_date: selectedDate
      });

      function formatLongDate(value) {
        return new Intl.DateTimeFormat("en-GB", {
          weekday: "long",
          day: "numeric",
          month: "long",
          year: "numeric",
          timeZone: "UTC"
        }).format(new Date(value + "T00:00:00Z"));
      }

      function formatTemperature(value) {
        const rounded = Math.round(Number(value) * 10) / 10;
        if (Object.is(rounded, -0)) {
          return "0";
        }
        return Number.isInteger(rounded) ? String(rounded) : rounded.toFixed(1);
      }

      function readNumber(array, index) {
        if (!Array.isArray(array)) {
          return null;
        }

        const raw = array[index];
        if (raw === null || raw === undefined || raw === "") {
          return null;
        }

        const value = Number(raw);
        return Number.isFinite(value) ? value : null;
      }

      function formatCoordinate(value, positive, negative) {
        return `${Math.abs(value).toFixed(2)}° ${value < 0 ? negative : positive}`;
      }

      function formatHour(time, index) {
        const match = String(time).match(/T(\d{2}):(\d{2})/);
        return match ? `${match[1]}:${match[2]}` : `${String(index).padStart(2, "0")}:00`;
      }

      function conditionFor(code) {
        const value = Math.round(Number(code));

        if (value === 0) {
          return {
            label: "Clear sky",
            detail: "Bright and open skies",
            theme: "clear",
            icon: "clear"
          };
        }

        if (value === 1) {
          return {
            label: "Mainly clear",
            detail: "Mostly calm with passing cloud",
            theme: "partly",
            icon: "partly"
          };
        }

        if (value === 2) {
          return {
            label: "Partly cloudy",
            detail: "A mix of sun and cloud",
            theme: "partly",
            icon: "partly"
          };
        }

        if (value === 3) {
          return {
            label: "Overcast",
            detail: "Cloud cover through the day",
            theme: "cloud",
            icon: "cloud"
          };
        }

        if (value === 45 || value === 48) {
          return {
            label: "Fog",
            detail: "Hazy with reduced visibility",
            theme: "fog",
            icon: "fog"
          };
        }

        if ([51, 53, 55, 56, 57].includes(value)) {
          return {
            label: value >= 56 ? "Freezing drizzle" : "Drizzle",
            detail: "Light precipitation nearby",
            theme: "drizzle",
            icon: "drizzle"
          };
        }

        if ([61, 63, 65, 66, 67, 80, 81, 82].includes(value)) {
          return {
            label: [80, 81, 82].includes(value) ? "Rain showers" : "Rain",
            detail: "Rainfall expected during the day",
            theme: "rain",
            icon: "rain"
          };
        }

        if ([71, 73, 75, 77, 85, 86].includes(value)) {
          return {
            label: [85, 86].includes(value) ? "Snow showers" : "Snow",
            detail: "Wintry conditions possible",
            theme: "snow",
            icon: "snow"
          };
        }

        if ([95, 96, 99].includes(value)) {
          return {
            label: "Thunderstorms",
            detail: "Thunderstorms in the forecast",
            theme: "storm",
            icon: "storm"
          };
        }

        return {
          label: "Unsettled conditions",
          detail: "Mixed atmospheric conditions",
          theme: "cloud",
          icon: "cloud"
        };
      }

      function iconMarkup(type) {
        const open = '<svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">';
        const close = "</svg>";
        const rays = `
          <g class="sun-rays">
            <path d="M72 5v11M72 52v11M43 34H32M101 34H90M51 13l8 8M93 55l8 8M93 13l-8 8M51 55l-8 8"></path>
          </g>
        `;
        const sun = '<circle class="sun-disc" cx="72" cy="34" r="17"></circle>';
        const cloud = '<path class="cloud-shape" d="M24 80h68c13 0 23-9 23-21s-10-21-23-21h-4C84 24 72 16 58 16c-17 0-31 11-35 27h-2C10 43 2 51 2 62s8 18 22 18Z"></path>';

        if (type === "clear") {
          return `${open}${rays}${sun}${close}`;
        }

        if (type === "partly") {
          return `${open}<g transform="translate(-4 -3) scale(.78)">${rays}${sun}</g><g transform="translate(7 26) scale(.9)">${cloud}</g>${close}`;
        }

        if (type === "cloud") {
          return `${open}<g transform="translate(0 10)">${cloud}</g>${close}`;
        }

        if (type === "fog") {
          return `${open}<g transform="translate(0 4)">${cloud}</g><g class="fog-lines"><path d="M19 94h72M30 104h61"></path></g>${close}`;
        }

        if (type === "drizzle") {
          return `${open}<g transform="translate(0 3)">${cloud}</g><g class="rain-lines"><path d="M36 91l-3 8M59 91l-3 8M82 91l-3 8"></path></g>${close}`;
        }

        if (type === "rain") {
          return `${open}<g transform="translate(0 1)">${cloud}</g><g class="rain-lines"><path d="M31 89l-5 16M58 89l-5 16M85 89l-5 16"></path></g>${close}`;
        }

        if (type === "snow") {
          return `${open}<g transform="translate(0 2)">${cloud}</g><g class="snow-lines"><path d="M35 92v15M28 99h14M30 94l10 10M40 94l-10 10M61 92v15M54 99h14M56 94l10 10M66 94l-10 10M87 92v15M80 99h14M82 94l10 10M92 94l-10 10"></path></g>${close}`;
        }

        return `${open}<g transform="translate(0 1)">${cloud}</g><path class="lightning" d="M61 78h14l-9 16h10l-22 24 6-18H49Z"></path>${close}`;
      }

      function setStatus(state, label) {
        elements.statusDot.className = `status-dot ${state}`;
        elements.sourceLabel.textContent = label;
      }

      function showLoading() {
        elements.loadingState.hidden = false;
        elements.errorState.hidden = true;
        elements.weatherContent.hidden = true;
        elements.card.setAttribute("aria-busy", "true");
        elements.loadingMessage.textContent = isArchive
          ? "Retrieving the historical record and hourly temperatures."
          : "Retrieving the forecast and hourly temperatures.";
        setStatus("loading", "LOADING / UTC");
      }

      function showError() {
        elements.loadingState.hidden = true;
        elements.errorState.hidden = false;
        elements.weatherContent.hidden = true;
        elements.card.setAttribute("aria-busy", "false");
        elements.errorDetail.textContent = `No usable readings were returned for ${formatLongDate(selectedDate)}.`;
        setStatus("error", "UNAVAILABLE / UTC");
      }

      function renderChart(points) {
        const width = 1000;
        const height = 230;
        const plotLeft = 57;
        const plotRight = 972;
        const plotTop = 25;
        const plotBottom = 193;
        const values = points.map((point) => point.value);
        const minimum = Math.min(...values);
        const maximum = Math.max(...values);

        let axisMin = Math.floor(minimum - 2);
        let axisMax = Math.ceil(maximum + 2);

        if (axisMax - axisMin < 6) {
          axisMin -= 3;
          axisMax += 3;
        }

        const yFor = (value) => plotBottom - ((value - axisMin) / (axisMax - axisMin)) * (plotBottom - plotTop);
        const xFor = (index) => points.length === 1
          ? (plotLeft + plotRight) / 2
          : plotLeft + (index / (points.length - 1)) * (plotRight - plotLeft);

        const coordinates = points.map((point, index) => ({
          x: xFor(index),
          y: yFor(point.value),
          value: point.value
        }));

        const linePath = coordinates
          .map((point, index) => `${index === 0 ? "M" : "L"}${point.x.toFixed(2)} ${point.y.toFixed(2)}`)
          .join(" ");

        const areaPath = `${linePath} L${coordinates[coordinates.length - 1].x.toFixed(2)} ${plotBottom} L${coordinates[0].x.toFixed(2)} ${plotBottom} Z`;

        const gridLines = Array.from({ length: 5 }, (_, index) => {
          const value = axisMax - ((axisMax - axisMin) * index / 4);
          const y = yFor(value);
          return `
            <line class="chart-gridline" x1="${plotLeft}" y1="${y.toFixed(2)}" x2="${plotRight}" y2="${y.toFixed(2)}"></line>
            <text x="13" y="${(y + 4).toFixed(2)}">${formatTemperature(value)}°</text>
          `;
        }).join("");

        const labelIndexes = [...new Set([
          0,
          Math.floor((points.length - 1) / 4),
          Math.floor((points.length - 1) / 2),
          Math.floor((points.length - 1) * 0.75),
          points.length - 1
        ])];

        const xLabels = labelIndexes.map((index) => {
          const x = xFor(index);
          return `<text x="${x.toFixed(2)}" y="218" text-anchor="middle">${points[index].hour.slice(0, 2)}</text>`;
        }).join("");

        const maxIndex = values.indexOf(maximum);
        const minIndex = values.indexOf(minimum);

        const circles = coordinates.map((point, index) => {
          const extreme = index === maxIndex || index === minIndex;
          return `<circle class="chart-point${extreme ? " extreme" : ""}" cx="${point.x.toFixed(2)}" cy="${point.y.toFixed(2)}" r="${extreme ? 5 : 3.5}"></circle>`;
        }).join("");

        elements.temperatureGraph.innerHTML = `
          <defs>
            <linearGradient id="areaFill" x1="0" y1="0" x2="0" y2="1">
              <stop class="accent-stop" offset="0%" stop-opacity=".32"></stop>
              <stop class="accent-stop" offset="100%" stop-opacity="0"></stop>
            </linearGradient>
          </defs>
          ${gridLines}
          <line class="chart-axis" x1="${plotLeft}" y1="${plotBottom}" x2="${plotRight}" y2="${plotBottom}"></line>
          <path class="chart-area" d="${areaPath}"></path>
          <path class="chart-line" d="${linePath}"></path>
          ${circles}
          ${xLabels}
        `;

        elements.temperatureGraph.setAttribute(
          "aria-label",
          `Hourly temperatures from ${formatTemperature(Math.min(...values))} to ${formatTemperature(Math.max(...values))} degrees Celsius`
        );
      }

      function renderHourlyGrid(points) {
        const fragment = document.createDocumentFragment();

        points.forEach((point) => {
          const cell = document.createElement("div");
          cell.className = "hour-cell";
          cell.setAttribute("role", "listitem");
          cell.setAttribute(
            "aria-label",
            `${point.hour}, ${formatTemperature(point.value)} degrees Celsius`
          );

          const hour = document.createElement("span");
          hour.className = "hour-label";
          hour.textContent = point.hour;

          const temperature = document.createElement("strong");
          temperature.className = "hour-temperature";
          temperature.textContent = `${formatTemperature(point.value)}°`;

          cell.append(hour, temperature);
          fragment.appendChild(cell);
        });

        elements.hourlyGrid.replaceChildren(fragment);
      }

      function renderWeather(data) {
        const daily = data && data.daily;
        const dailyTimes = Array.isArray(daily && daily.time) ? daily.time : [];
        const dailyIndex = Math.max(0, dailyTimes.indexOf(selectedDate));

        const maximum = readNumber(daily && daily.temperature_2m_max, dailyIndex);
        const minimum = readNumber(daily && daily.temperature_2m_min, dailyIndex);
        const code = readNumber(daily && daily.weather_code, dailyIndex);

        if (maximum === null || minimum === null || code === null) {
          throw new Error("Missing daily weather values");
        }

        const hourly = data && data.hourly;
        const hourlyTimes = Array.isArray(hourly && hourly.time) ? hourly.time : [];
        const allPoints = hourlyTimes
          .map((time, index) => {
            const value = readNumber(hourly.temperature_2m, index);
            return value === null
              ? null
              : { time, value, hour: formatHour(time, index) };
          })
          .filter(Boolean);

        const sameDayPoints = allPoints.filter((point) => String(point.time).startsWith(selectedDate));
        const points = sameDayPoints.length ? sameDayPoints : allPoints;

        if (!points.length) {
          throw new Error("Missing hourly weather values");
        }

        const condition = conditionFor(code);
        const lower = Math.min(minimum, maximum);
        const upper = Math.max(minimum, maximum);
        const scaleMin = Math.floor(lower / 5) * 5 - 5;
        const scaleMax = Math.ceil(upper / 5) * 5 + 5;
        const scaleSpan = Math.max(1, scaleMax - scaleMin);
        const rangeStart = ((lower - scaleMin) / scaleSpan) * 100;
        const rangeEnd = ((upper - scaleMin) / scaleSpan) * 100;

        document.body.dataset.weather = condition.theme;
        document.title = `${placeName} · Weather`;

        elements.locationName.textContent = placeName;
        elements.locationName.title = placeName;
        elements.dateLabel.textContent = formatLongDate(selectedDate);
        elements.reportType.textContent = `${modeLabel} / UTC`;
        elements.maxTemp.textContent = formatTemperature(maximum);
        elements.minTemp.textContent = formatTemperature(minimum);
        elements.lowEndpoint.textContent = `${formatTemperature(minimum)}°C`;
        elements.highEndpoint.textContent = `${formatTemperature(maximum)}°C`;
        elements.conditionName.textContent = condition.label;
        elements.conditionDetail.textContent = condition.detail;
        elements.heroIcon.innerHTML = iconMarkup(condition.icon);
        elements.rangeValue.textContent = `${formatTemperature(upper - lower)}° spread`;
        elements.rangeFill.style.left = `${Math.max(0, Math.min(100, rangeStart))}%`;
        elements.rangeFill.style.width = `${Math.max(5, Math.min(100 - rangeStart, rangeEnd - rangeStart))}%`;
        elements.chartDescriptor.textContent = `${points.length}-hour temperature trace`;
        elements.readingCount.textContent = `${points.length} readings`;
        elements.hourlySpan.textContent = `${formatTemperature(Math.min(...points.map((point) => point.value)))}°C — ${formatTemperature(Math.max(...points.map((point) => point.value)))}°C`;
        elements.coordinateLabel.textContent = `${formatCoordinate(latitude, "N", "S")} / ${formatCoordinate(longitude, "E", "W")}`;
        elements.footerMode.textContent = isArchive ? "Historical archive" : "Forecast window";

        renderChart(points);
        renderHourlyGrid(points);

        elements.loadingState.hidden = true;
        elements.errorState.hidden = true;
        elements.weatherContent.hidden = false;
        elements.card.setAttribute("aria-busy", "false");
        setStatus("ready", `${modeLabel.toUpperCase()} / UTC`);
      }

      let requestSequence = 0;

      async function loadWeather() {
        const sequence = ++requestSequence;
        showLoading();

        try {
          const response = await fetch(`${endpoint}?${requestParams.toString()}`, {
            method: "GET",
            headers: {
              "Accept": "application/json"
            }
          });

          if (!response || (typeof response.ok === "boolean" && !response.ok)) {
            throw new Error("Weather service request failed");
          }

          const data = await response.json();

          if (sequence !== requestSequence) {
            return;
          }

          renderWeather(data);
        } catch (error) {
          if (sequence !== requestSequence) {
            return;
          }

          showError();
        }
      }

      const contextText = `${placeName} · ${formatLongDate(selectedDate)} · UTC`;
      elements.loadingContext.textContent = contextText;
      elements.errorContext.textContent = contextText;
      elements.retryButton.addEventListener("click", loadWeather);

      loadWeather();
    })();
  </script>
</body>
</html>

L1 — cheap deterministic descriptors

bytes total49,114html / css / js6,522 / 23,367 / 19,225
dom nodes106dom depth12
css rules136js presentyes
brightness29.5contrast11.6
colorfulness16.1whitespace96.6%

This slot's telemetry

prompt tokens0completion tokens41,701
total tokens0wall644.5 s
costrequest id
config.json562 B
{
  "N": 2,
  "auth": {
    "credential_ref": "WCB_NONE",
    "method": "oauth-login"
  },
  "billing": "plan",
  "config_id": "gpt-5.6-luna-eff-max--cli--codex-oauth--dev",
  "effort": "max",
  "family": "gpt",
  "m": {
    "min": 2,
    "q": 2
  },
  "model_id": "gpt-5.6-luna",
  "protocol": "cli",
  "served_model": "gpt-5.6-luna",
  "telemetry": {
    "completion_tokens": 103620,
    "cost_usd": null,
    "prompt_tokens": null,
    "total_tokens": null,
    "wall_ms": 1437956
  },
  "transport": "codex-cli-oauth-chatgpt",
  "vendor_sanction_ref": null
}
send-log2.5 KB
{
  "N": 2,
  "batch_id": "2026-07-19--codex-oauth-extra",
  "config_id": "gpt-5.6-luna-eff-max--cli--codex-oauth--dev",
  "positions": [
    {
      "attempts": [
        {
          "attempt_index": 0,
          "backoff_ms": null,
          "charged": true,
          "ended_at": "2026-07-18T21:17:19.911260+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T21:13:33.947513+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-18T21:28:09.315831+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T21:17:24.855793+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-18T21:34:39.968915+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T21:28:13.521212+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-18T21:37:44.784979+00:00",
          "http_status": null,
          "outcome": "valid",
          "reached_model": true,
          "reason": "ok",
          "request_id": null,
          "started_at": "2026-07-18T21:34:43.621187+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
    }
  }
}