Cannabis Freedom Index

Changelog 6894f5a

history from 1995

18 history entries added4 files of code, design or docs +237 −7 lines

History changes.yaml

Added 18

Code, design and documents 4 files

src/components/AverageChart.astro +5 −2
@@ -12,5 +12,5 @@ const time = (iso) => Date.parse(iso.length === 7 ? `${iso}-15` : iso);
 const first = averageHistory[0];
 const now = averageHistory.at(-1).after;
-const startYear = +first.date.slice(0, 4);
+const startYear = Math.floor(+first.date.slice(0, 4) / 5) * 5; // start the axis on a round year
 const endYear = +lastUpdated.slice(0, 4);
 const t0 = Date.UTC(startYear, 0, 1);
@@ -24,5 +24,8 @@ const yMax = Math.ceil(Math.max(...values) * 2) / 2;
 const y = (v) => (1 - (v - yMin) / (yMax - yMin)) * 100;
 const ticks = Array.from({ length: Math.round((yMax - yMin) * 2) + 1 }, (_, i) => yMin + i / 2);
-const years = Array.from({ length: endYear - startYear + 1 }, (_, i) => startYear + i);
+// at most about a dozen year labels, on round steps
+const span = endYear - startYear;
+const step = span > 50 ? 10 : span > 20 ? 5 : span > 14 ? 2 : 1;
+const years = Array.from({ length: span + 1 }, (_, i) => startYear + i).filter((yr) => yr % step === 0);
 
 const points = averageHistory.map((p) => ({ ...p, x: x(time(p.date)), y: y(p.after) }));

src/lib/facts.js +1 −1
@@ -31,5 +31,5 @@ function computed() {
     { text: `${SEGMENTS[lowest].name} is the rarest freedom. The world average is ${segAvg[lowest].toFixed(1)} out of 10, lower than for any other segment.` },
     { text: `${medOnly.length} countries allow some medical use of cannabis while keeping recreational use fully illegal.` },
-    { text: `${regionAvg[0].r} is the freest region, averaging ${Math.round(regionAvg[0].avg)}. ${regionAvg.at(-1).r} is the strictest at ${Math.round(regionAvg.at(-1).avg)}. The world average is ${Math.round(worldAvg)}.` },
+    { text: `${regionAvg[0].r} is the freest region, averaging ${Math.round(regionAvg[0].avg)}. ${regionAvg.at(-1).r} is the strictest at ${Math.round(regionAvg.at(-1).avg)}. The world average is ${worldAvg.toFixed(1)}.` },
   ];
 }

src/pages/index.astro +1 −1
@@ -11,5 +11,5 @@ const count = (fn) => countries.filter(fn).length;
 const stats = [
   [countries.length, "countries scored"],
-  [Math.round(worldAvg), "world average, out of 100"],
+  [worldAvg.toFixed(1), "world average, out of 100"],
   [count((c) => c.raw >= 60), "reach the “Free” tier (60+)"],
   [count((c) => c.raw >= 40), "score 40+: legal to possess and grow, with limits"],

src/styles/global.css +3 −3
@@ -511,8 +511,8 @@ td.num, th.num { width: 52px; color: var(--muted); }
 .avg-plot .grid { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
 .avg-plot .line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
-/* a 24px hit target around a 9px dot with a surface ring */
+/* a 24px hit target around a 6px dot with a surface ring */
 .avg-dot { position: absolute; width: 24px; height: 24px; margin: -12px 0 0 -12px; border-radius: 50%; }
-.avg-dot::after { content: ""; position: absolute; inset: 7.5px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 2px var(--surface); transition: transform .12s; }
-.avg-dot.on::after, .avg-dot:focus-visible::after { transform: scale(1.5); }
+.avg-dot::after { content: ""; position: absolute; inset: 9px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 1.5px var(--surface); transition: transform .12s; }
+.avg-dot.on::after, .avg-dot:focus-visible::after { transform: scale(1.8); }
 .avg-dot.on { z-index: 1; }
 .avg-tip { position: absolute; z-index: 2; transform: translateX(-50%); width: max-content; max-width: min(260px, 100%); padding: 8px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2); box-shadow: var(--shadow); pointer-events: none; font-size: 13px; line-height: 1.35; }

    ↑↓ to move, ↵ to open.