thermograph/templates/records.html.j2
Emi Griffith 4e8d1e9e59 SEO: monthly & seasonal records + colour-coded climate pages (#107)
* SEO: monthly & seasonal records on the city records page

The /climate/<city>/records page showed only all-time records per metric.
Expand it into a full records page: record high/low for each of the 12
months (each linking its month page) and for each meteorological season,
alongside the existing all-time table.

Seasons are hemisphere-aware — Dec–Feb reads as winter for northern cities
and summer for southern ones (picked from the city's latitude). Records
reuse grading.all_time_records over a month-filtered archive, so no new
data fetching or warming is needed. Adds a Dataset + breadcrumb JSON-LD
block and richer title/description for the expanded coverage.

* SEO: colour-code climate & records pages (heat-map + range strip)

The city, records and month pages were plain muted tables — generic climate-site
styling. Bring the interactive grader's diverging cold→hot palette onto them so
they read as heat maps in the site's own visual language:

- Map absolute °F to the 9-tier palette (temp_class, a Jinja global) and tint the
  temperature cells across the monthly-normals, monthly/seasonal/all-time records
  tables. The value stays in the ink token; the tint is a wash behind it. Non-temp
  rows (humidity/wind/precip) and date columns stay untinted.
- Add a monthly temperature-range strip on the city page: one gradient bar per
  month spanning the average low→high on a shared −10..115°F axis, so a city's
  whole-year rhythm (and hot-vs-cold character) reads at a glance.
- Tint the month page's hero high/low and its record values inline.

Palette, light/dark, and 390–1920px layouts verified by rendering hot (Phoenix)
and cold (Anchorage) cities.
2026-07-16 03:50:59 +00:00

88 lines
4.3 KiB
Django/Jinja
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html.j2" %}
{% block title %}{{ page_title }}{% endblock %}
{% block description %}{{ page_description }}{% endblock %}
{% block canonical_path %}{{ canonical_path }}{% endblock %}
{% block jsonld %}<script type="application/ld+json">{{ jsonld_str | safe }}</script>{% endblock %}
{% block content %}
<nav class="breadcrumb" aria-label="Breadcrumb">
{% for label, href in breadcrumb %}{% if href %}<a href="{{ href }}">{{ label }}</a>{% else %}<span>{{ label }}</span>{% endif %}{% if not loop.last %} <span class="sep"></span> {% endif %}{% endfor %}
</nav>
<article class="climate-page">
<h1>{{ display }} weather records</h1>
<p class="lede">Record high and low temperatures for <b>{{ display }}</b> — by month, by season, and
all-time — with the dates they occurred, across {{ year_range[0] }}{{ year_range[1] }} of daily
climate history.{% if all_time.tmax and all_time.tmin %} Its hottest day on record reached
{{ all_time.tmax.max | round | int }}°F ({{ ((all_time.tmax.max - 32) * 5 / 9) | round | int }}°C)
on {{ all_time.tmax.max_date }}; its coldest fell to
{{ all_time.tmin.min | round | int }}°F ({{ ((all_time.tmin.min - 32) * 5 / 9) | round | int }}°C)
on {{ all_time.tmin.min_date }}.{% endif %}</p>
<section class="climate-records-section">
<h2>Records by month</h2>
<p>The warmest and coldest {{ name }} has ever been in each calendar month. Tap a month for its full
averages and typical range.</p>
<div class="table-wrap">
<table class="normals-table records-table">
<thead><tr><th>Month</th><th>Record high</th><th>On</th><th>Record low</th><th>On</th></tr></thead>
<tbody>
{% for m in monthly %}
<tr>
<td><a href="{{ base }}/climate/{{ city.slug }}/{{ m.slug }}">{{ m.name }}</a></td>
<td class="t-cell t-{{ temp_class(m.high_f) }}">{{ m.high }}</td><td class="rec-date">{{ m.high_date }}</td>
<td class="t-cell t-{{ temp_class(m.low_f) }}">{{ m.low }}</td><td class="rec-date">{{ m.low_date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
<section class="climate-records-section">
<h2>Records by season</h2>
<p>Meteorological seasons for the {{ hemisphere }} Hemisphere — each a three-month span — and the
most extreme {{ name }} has recorded within each.</p>
<div class="table-wrap">
<table class="normals-table records-table">
<thead><tr><th>Season</th><th>Record high</th><th>On</th><th>Record low</th><th>On</th></tr></thead>
<tbody>
{% for s in seasonal %}
<tr>
<td>{{ s.name }} <span class="season-span">({{ s.span }})</span></td>
<td class="t-cell t-{{ temp_class(s.high_f) }}">{{ s.high }}</td><td class="rec-date">{{ s.high_date }}</td>
<td class="t-cell t-{{ temp_class(s.low_f) }}">{{ s.low }}</td><td class="rec-date">{{ s.low_date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
<section class="climate-records-section">
<h2>All-time records</h2>
<p>The most extreme value {{ name }} has recorded for each metric across its entire history.</p>
<div class="records-grid">
{% for r in rows %}
<div class="record-card">
<h3 class="rc-metric">{{ r.label }}</h3>
<div class="rc-row rc-high">
<span class="rc-tag">{% if r.label == 'Precip' %}Wettest{% else %}Highest{% endif %}</span>
<span class="rc-val">{{ r.high }}</span>
<span class="rc-date">{{ r.high_date }}</span>
</div>
<div class="rc-row rc-low">
<span class="rc-tag">{% if r.label == 'Precip' %}Driest{% else %}Lowest{% endif %}</span>
<span class="rc-val">{{ r.low }}</span>
<span class="rc-date">{{ r.low_date }}</span>
</div>
</div>
{% endfor %}
</div>
<p class="records-note muted">For rainfall, the “driest” figure is the <b>longest run of consecutive
days without measurable rain</b>, dated to when that dry spell began.</p>
</section>
<p><a class="cta" href="{{ base }}/#{{ '%.5f,%.5f' | format(city.lat, city.lon) }}">Grade {{ name }}'s weather now →</a></p>
<p class="climate-foot muted"><a href="{{ base }}/climate/{{ city.slug }}"> Back to {{ name }} climate</a></p>
</article>
{% endblock %}