← Back to the site changelog
Site Changelog
Original commit record
LIVE ticker: each flash links to its story (no underline)
Ticker items stay structured through to base.html: every marquee entry
is an <a> to its article (external agg items open in a new tab), with
the clickable affordance carried by an accent ↗ mark and hover color -
never an underline (owner request). The track pauses on hover so the
moving items can actually be clicked; placeholder items without a URL
render as plain text.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SHA
8fb37161b09fbe42fa5b76e725593b68173cb344
Commit date
2026-07-26T23:47:40Z
Author
avwire
Committer
avwire
Changed files (3)
pipeline/build.py
modified · +7 / −3
static/site.css
modified · +15 / −0
templates/base.html
modified · +13 / −3
Full diff
@@ -575,7 +575,7 @@ def _pre(x):\n },\n }\n \n-TICKER_SEP = " ▪ " # 「 ▪ 」 per the design\n+# (the design's 「 ▪ 」 ticker separator now lives in base.html/.ticker-sep)\n \n # Footer source-tag order, exactly as in the design footer.\n FOOTER_ORDER = ["faa", "icao", "iata", "ntsb", "easa", "eurocontrol",\n@@ -1341,7 +1341,7 @@ def base_ctx(lang, page, sub, *, title, description, ticker, build, hreflang=Tru\n "home_url": page_url(lang, ""),\n "nav": [{"label": t["nav"][i], "url": page_url(lang, s), "active": page == p}\n for i, (p, s) in enumerate(nav_defs)],\n- "ticker_line": ticker, "build": build,\n+ "ticker_items": ticker or [], "build": build,\n "footer_sources": FOOTER_SOURCES,\n }\n \n@@ -1422,7 +1422,11 @@ def main() -> int:\n fl = flash_view(flashes, lang)\n hero = None\n feed = []\n- ticker = TICKER_SEP.join(f"{f['time']} {f['text']}" for f in fl)\n+ # ticker items stay structured so the marquee can link each flash\n+ # to its story (owner request: clickable, no underline)\n+ ticker = [{"time": f.get("time"), "text": f.get("text"),\n+ "url": f.get("url"), "hot": bool(f.get("hot")),\n+ "external": bool(f.get("external"))} for f in fl]\n sv = stats_views(stats_raw, lang)\n \n bviews = [brief_view(b, lang, t, published_ids) for b in briefings]\n@@ -30,6 +30,21 @@ a:hover { color: var(--color-accent-600); }\n }\n \n @keyframes avwire-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }\n+\n+/* — LIVE ticker: each flash links to its story. Affordance is the accent\n+ ↗ mark + hover color (owner: clickable-looking but NO underline);\n+ the track pauses on hover so items can actually be clicked. — */\n+.marquee-track:hover { animation-play-state: paused; }\n+.ticker-item { color: inherit; text-decoration: none; }\n+a.ticker-item:hover { color: var(--color-accent); }\n+a.ticker-item:hover .ticker-time { color: var(--color-accent); }\n+.ticker-time { font-weight: 800; }\n+.ticker-time.hot { color: var(--color-accent); }\n+.ticker-go {\n+ font-size: 10px; font-weight: 800; color: var(--color-accent);\n+ margin-left: 4px; vertical-align: 2px;\n+}\n+.ticker-sep { padding: 0 18px; color: color-mix(in srgb, var(--color-text) 35%, transparent); }\n @keyframes avwire-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }\n \n /* — chrome — */\n@@ -57,13 +57,23 @@\n </nav>\n </div>\n </div>\n- {% if ticker_line %}\n+ {% if ticker_items %}\n <div style="border-bottom:2px solid var(--color-divider);display:flex;align-items:stretch;">\n <div style="background:var(--color-accent);color:var(--color-bg);font-weight:800;font-size:12px;letter-spacing:.14em;display:flex;align-items:center;padding:7px 16px;flex-shrink:0;text-transform:uppercase;">{{ t.live }}</div>\n <div style="overflow:hidden;flex:1;display:flex;align-items:center;">\n <div class="marquee-track">\n- <span style="padding-right:70px;font-size:13px;">{{ ticker_line }}</span>\n- <span style="padding-right:70px;font-size:13px;">{{ ticker_line }}</span>\n+ {% for pass in range(2) %}\n+ <span style="padding-right:70px;font-size:13px;white-space:nowrap;">\n+ {%- for it in ticker_items -%}\n+ {%- if it.url -%}\n+ <a class="ticker-item" href="{{ it.url }}"{% if it.external %} target="_blank" rel="noopener"{% endif %}><b class="ticker-time{% if it.hot %} hot{% endif %}">{{ it.time }}</b> {{ it.text }}<span class="ticker-go">↗</span></a>\n+ {%- else -%}\n+ <span class="ticker-item"><b class="ticker-time{% if it.hot %} hot{% endif %}">{{ it.time }}</b> {{ it.text }}</span>\n+ {%- endif -%}\n+ {%- if not loop.last %}<span class="ticker-sep">▪</span>{% endif -%}\n+ {%- endfor -%}\n+ </span>\n+ {% endfor %}\n </div>\n </div>\n </div>