Changelog 974ea0e
better look
4 files of code, design or docs +231 −136 lines
Code, design and documents 4 files
src/components/Changes.astro +20 −26
@@ -1,8 +1,7 @@ --- -// Home page: the four most recent changes as a small vertical timeline (date on the left, -// details on the right), next to the world average chart. See /changes.yaml. +// Home page: the four most recent changes as a ledger, one row each: date, country, what +// happened, and the score before and after. See /changes.yaml. import { changes } from "../lib/countries.js"; import { tierColor } from "../lib/tiers.js"; -import AverageChart from "./AverageChart.astro"; import ScoreChange from "./ScoreChange.astro"; @@ -12,25 +11,20 @@ const shortDate = (iso) => iso.length === 4 ? iso : new Date(`${iso.length === 7 ? iso + "-01" : iso}T00:00:00Z`).toLocaleDateString("en-GB", { day: iso.length === 7 ? undefined : "numeric", month: "short", year: "numeric", timeZone: "UTC" }); --- -<div class="home-split"> - <section class="card changes" aria-labelledby="changesTitle"> - <div class="changes-head"> - <h2 class="changes-title" id="changesTitle">Latest changes</h2> - <a href={`${base}history/`}>Full history →</a> - </div> - <ol class="mini-tl"> - {changes.filter((ch) => ch.score).slice(0, 4).map((ch) => ( - <li style={`--c:${tierColor(ch.score.after)}`}> - <a href={`${base}history/${ch.id}/`}> - <time datetime={ch.date}>{shortDate(ch.date)}</time> - <span class="mini-tl-body"> - <span class="mini-tl-country">{ch.country.flag} {ch.country.name}</span> - <b><span class="kind" title={ch.kind.label} aria-hidden="true">{ch.kind.emoji}</span><span class="visually-hidden">{ch.kind.label}: </span>{ch.title}</b> - <ScoreChange score={ch.score} /> - </span> - </a> - </li> - ))} - </ol> - </section> - <AverageChart /> -</div> +<section class="ledger" aria-labelledby="changesTitle"> + <div class="ledger-head"> + <h2 id="changesTitle">Latest changes</h2> + <a href={`${base}history/`}>Full history →</a> + </div> + <ol> + {changes.filter((ch) => ch.score).slice(0, 4).map((ch) => ( + <li style={`--c:${tierColor(ch.score.after)}`}> + <a href={`${base}history/${ch.id}/`}> + <time datetime={ch.date}>{shortDate(ch.date)}</time> + <span class="ledger-place">{ch.country.flag} {ch.country.name}</span> + <b><span class="visually-hidden">{ch.kind.label}: </span>{ch.title}</b> + <ScoreChange score={ch.score} /> + </a> + </li> + ))} + </ol> +</section>
src/layouts/Base.astro +1 −1
@@ -38,5 +38,5 @@ const schemas = jsonld ? [jsonld].flat() : []; <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@500;600;700&display=swap" rel="stylesheet"> + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> <script is:inline> // Set the theme before first paint to avoid a flash.
src/pages/index.astro +13 −6
@@ -3,4 +3,5 @@ import Base from "../layouts/Base.astro"; import DidYouKnow from "../components/DidYouKnow.astro"; import Changes from "../components/Changes.astro"; +import AverageChart from "../components/AverageChart.astro"; import { SEGMENTS, DATA_SNAPSHOT, REC_LABEL, REC_ORDER, REC_HELP, MED_LABEL, MED_HELP, countries, regions, worldAvg, lastUpdated, formatDate, subunitsOf, places, trendOf, changeDate, TREND_YEARS } from "../lib/countries.js"; import { TIERS, tierColor } from "../lib/tiers.js"; @@ -105,10 +106,16 @@ const columnGroups = [["Shown by default", BASE_COLUMNS], ...["Score segments", <Base description={`Where is cannabis legal? Cannabis laws in ${countries.length} countries, each scored from 0 to 100 for possession, home growing, penalties and legal access, with a world map, rankings${SHOW_PRICES ? ", retail prices" : ""} and legal history.`} jsonld={homeSeo(Astro.site, countries.length)}> <main id="top"> - <section class="hero"> - <p class="eyebrow">Global index · {DATA_SNAPSHOT} edition</p> - <h1>How free is cannabis<br>in every country?</h1> - <p class="lede">Every country gets a score from 0 to 100. It shows how free you are to carry, grow, share and use cannabis. See the map, rankings{SHOW_PRICES && ", sourced retail prices"} and how each country's laws changed over time.</p> - <div class="stats"> - {stats.map(([n, label, tone]) => <div class={`stat ${tone ?? ""}`}><div class="big">{n}</div><div class="label">{label}</div></div>)} + {/* The opening: the question, the answer in one number with its history, then what just changed. */} + <section class="front"> + <p class="eyebrow">Cannabis Freedom Index <span>{DATA_SNAPSHOT} edition</span></p> + <h1>How free is cannabis <em>in every country?</em></h1> + <div class="front-grid"> + <div class="front-intro"> + <p class="lede">Every country gets a score from 0 to 100 for how free you are to carry, grow, share and use cannabis. Below: the map, the rankings{SHOW_PRICES && ", sourced retail prices"} and how each country's law got where it is.</p> + <dl class="front-stats"> + {stats.map(([n, label, tone]) => <div class={tone ?? ""}><dt>{n}</dt><dd>{label}</dd></div>)} + </dl> + </div> + <AverageChart /> </div> <Changes />
src/styles/global.css +197 −103
@@ -1,13 +1,17 @@ /* ── Tokens ─────────────────────────────────────────── */ :root { - --bg: #0a0f0c; - --surface: #111814; - --surface-2: #18211c; - --border: #233029; - --text: #ecf3ee; - --text-2: #a9b8ae; - --muted: #74857a; - --accent: #5fd97f; - --accent-ink: #06210f; + /* Monochrome: ink on near-black. The red-to-green freedom scale is the only colour on the site. */ + --bg: #0c0c0b; + --surface: #121211; + --surface-2: #1a1a18; + --border: #2a2a27; + --text: #f2f0e9; + --text-2: #a9a79d; + --muted: #77756c; + --accent: #f2f0e9; + --accent-ink: #0c0c0b; + --display: "Instrument Serif", "Iowan Old Style", Georgia, serif; /* headlines */ + --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace; /* labels and figures */ + --r: 2px; /* the one corner radius */ /* red → green freedom scale, shared by both themes */ --t0: #a3121f; @@ -17,7 +21,7 @@ --t4: #9ccc55; --t5: #2e9e4f; - --nodata: #1a1f1c; - --hatch: #2c3530; - --land: #2a322d; /* land that is not a country: Antarctica */ + --nodata: #181817; + --hatch: #2e2e2b; + --land: #2a2a27; /* land that is not a country: Antarctica */ /* cannabis use on the map: one hue, more is lighter on the dark theme */ --u0: #1b2c45; --u1: #24456f; --u2: #2f65a3; --u3: #5591d3; --u4: #a3c8f2; @@ -28,16 +32,16 @@ } :root[data-theme="light"] { - --bg: #f5f7f4; - --surface: #ffffff; - --surface-2: #eef2ee; - --border: #dde4de; - --text: #0f1a13; - --text-2: #46554b; - --muted: #6d7c72; - --accent: #14803f; - --accent-ink: #ffffff; - --nodata: #f0f1f0; - --hatch: #d5dad6; - --land: #dfe3df; + --bg: #f4f2eb; + --surface: #fbfaf5; + --surface-2: #eae7dd; + --border: #d9d5c8; + --text: #11110f; + --text-2: #4b4a43; + --muted: #7a786d; + --accent: #11110f; + --accent-ink: #f4f2eb; + --nodata: #efede5; + --hatch: #d6d2c5; + --land: #e2dfd4; /* …and darker on the light theme */ --u0: #dfe9f5; --u1: #b0cbea; --u2: #74a2d8; --u3: #3f77bd; --u4: #1c4a8f; @@ -56,10 +60,10 @@ body { -webkit-font-smoothing: antialiased; } -h1, h2, h3, .brand, .big { font-family: "Space Grotesk", Inter, system-ui, sans-serif; letter-spacing: -.02em; } +h1, h2, h3, .brand, .big { font-family: var(--display); letter-spacing: -.02em; } h2 { font-size: 28px; margin: 0 0 4px; } h3 { font-size: 17px; margin: 0 0 8px; } p { margin: 0 0 12px; } a { color: inherit; text-decoration: none; } -code { background: var(--surface-2); padding: 1px 6px; border-radius: 5px; font-size: 13px; } +code { background: var(--surface-2); padding: 1px 6px; border-radius: var(--r); font-size: 13px; } .num, .big, td.num, .score-val { font-variant-numeric: tabular-nums; } @@ -76,5 +80,5 @@ code { background: var(--surface-2); padding: 1px 6px; border-radius: 5px; font- .brand-mark { display: grid; place-items: center; width: 34px; height: 34px; - border-radius: 10px; background: var(--accent); color: var(--accent-ink); + border-radius: var(--r); background: var(--accent); color: var(--accent-ink); } .nav { display: flex; gap: clamp(12px, 2vw, 22px); margin-left: auto; } @@ -85,5 +89,5 @@ code { background: var(--surface-2); padding: 1px 6px; border-radius: 5px; font- .icon-btn { display: grid; place-items: center; width: 34px; height: 34px; - border: 1px solid var(--border); border-radius: 10px; + border: 1px solid var(--border); border-radius: var(--r); background: var(--surface); color: var(--text-2); font-size: 17px; line-height: 1; cursor: pointer; @@ -101,5 +105,5 @@ main { max-width: 1240px; margin: 0 auto; padding: 0 clamp(16px, 4vw, 40px); } .card { background: var(--surface); border: 1px solid var(--border); - border-radius: 18px; + border-radius: var(--r); } @@ -112,11 +116,4 @@ main { max-width: 1240px; margin: 0 auto; padding: 0 clamp(16px, 4vw, 40px); } h1 { font-size: clamp(36px, 6.2vw, 68px); line-height: 1.02; margin: 0 0 18px; } .lede { font-size: clamp(16px, 1.6vw, 19px); color: var(--text-2); max-width: 62ch; } -.stats { - display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); - gap: 12px; margin-top: 34px; -} -.stat { padding: 18px 20px; border-radius: 16px; background: var(--surface); border: 1px solid var(--border); } -.stat .big { font-size: 34px; font-weight: 700; line-height: 1.1; } -.stat .label { color: var(--text-2); font-size: 13.5px; } /* ── Form controls ──────────────────────────────────── */ @@ -126,5 +123,5 @@ select, input[type="search"] { font: inherit; color: var(--text); background: var(--surface); border: 1px solid var(--border); - border-radius: 10px; padding: 8px 12px; min-width: 0; + border-radius: var(--r); padding: 8px 12px; min-width: 0; } input[type="search"] { width: 200px; } @@ -151,5 +148,5 @@ select:focus-visible, input:focus-visible, button:focus-visible, tr:focus-visibl .tooltip { position: absolute; pointer-events: none; z-index: 5; - min-width: 170px; padding: 10px 12px; border-radius: 12px; + min-width: 170px; padding: 10px 12px; border-radius: var(--r); background: var(--surface-2); border: 1px solid var(--border); box-shadow: var(--shadow); font-size: 13px; @@ -166,5 +163,5 @@ select:focus-visible, input:focus-visible, button:focus-visible, tr:focus-visibl .legend[hidden] { display: none; } .legend .legend-note { flex-basis: 100%; color: var(--muted); } -.sw { width: 14px; height: 14px; border-radius: 4px; border: 1px solid var(--border); flex: none; } +.sw { width: 14px; height: 14px; border-radius: var(--r); border: 1px solid var(--border); flex: none; } .sw-nodata { background: repeating-linear-gradient(45deg, var(--nodata) 0 3px, var(--hatch) 3px 5px); } @@ -202,11 +199,11 @@ th.num-col { text-align: right; } .approx { color: var(--muted); margin-right: 1px; } .score-val { width: 28px; text-align: right; font-weight: 600; } -.bar { flex: 1; height: 8px; border-radius: 4px; background: var(--surface-2); position: relative; } -.bar > i { position: absolute; inset: 0 auto 0 0; border-radius: 4px; min-width: 3px; } +.bar { flex: 1; height: 8px; border-radius: var(--r); background: var(--surface-2); position: relative; } +.bar > i { position: absolute; inset: 0 auto 0 0; border-radius: var(--r); min-width: 3px; } .empty { padding: 36px; text-align: center; color: var(--muted); } .chip { display: inline-flex; align-items: center; gap: 6px; - padding: 2px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 500; + padding: 2px 10px; border-radius: var(--r); font-size: 12.5px; font-weight: 500; background: var(--surface-2); color: var(--text-2); border: 1px solid var(--border); white-space: nowrap; @@ -228,10 +225,10 @@ th.num-col { text-align: right; } display: grid; place-items: center; overflow: hidden; } -.weights div:first-child { border-radius: 8px 0 0 8px; } +.weights div:first-child { border-radius: var(--r); } .weights div:last-child { border-radius: 0 8px 8px 0; } .seg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; } .seg { padding: 18px 20px; } .seg-top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; } -.seg-w { font-family: "Space Grotesk", sans-serif; font-weight: 700; font-size: 22px; color: var(--accent); } +.seg-w { font-family: var(--display); font-weight: 700; font-size: 22px; color: var(--accent); } … 362 more lines