inkplot 0.1.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +33 -9
  4. data/bench/inkplot.rb +12 -0
  5. data/docs/index.html +31 -0
  6. data/examples/gallery/01-line.svg +1 -1
  7. data/examples/gallery/02-line-gaps.svg +1 -1
  8. data/examples/gallery/03-series.svg +1 -1
  9. data/examples/gallery/09-histogram.svg +1 -0
  10. data/examples/gallery/12-time.svg +1 -0
  11. data/examples/gallery/13-annotations.svg +1 -0
  12. data/examples/gallery/14-dark-theme.svg +1 -0
  13. data/examples/gallery/15-category-labels.svg +1 -0
  14. data/examples/gallery/16-custom-bins.svg +1 -0
  15. data/examples/gallery/17-connected-gaps.svg +1 -0
  16. data/examples/gallery/18-step-series.svg +1 -0
  17. data/examples/gallery/19-combined-marks.svg +1 -0
  18. data/examples/gallery/20-scatter-sizes.svg +1 -0
  19. data/examples/gallery/README.md +6 -1
  20. data/examples/gallery.rb +33 -1
  21. data/lib/inkplot/core.rb +354 -15
  22. data/lib/inkplot/renderers/png.rb +390 -0
  23. data/lib/inkplot/renderers/svg.rb +3 -1
  24. data/lib/inkplot/version.rb +1 -1
  25. data/lib/inkplot.rb +8 -0
  26. data/sig/inkplot.rbs +9 -2
  27. data/test/snapshots/inkplot/01-line.png +0 -0
  28. data/test/snapshots/inkplot/02-line-gaps.png +0 -0
  29. data/test/snapshots/inkplot/03-series.png +0 -0
  30. data/test/snapshots/inkplot/04-scatter.png +0 -0
  31. data/test/snapshots/inkplot/05-bars.png +0 -0
  32. data/test/snapshots/inkplot/06-horizontal-bars.png +0 -0
  33. data/test/snapshots/inkplot/07-grouped-bars.png +0 -0
  34. data/test/snapshots/inkplot/08-stacked-bars.png +0 -0
  35. data/test/snapshots/inkplot/09-histogram.png +0 -0
  36. data/test/snapshots/inkplot/10-area.png +0 -0
  37. data/test/snapshots/inkplot/11-step.png +0 -0
  38. data/test/snapshots/inkplot/12-time.png +0 -0
  39. data/test/snapshots/inkplot/13-annotations.png +0 -0
  40. data/test/snapshots/inkplot/14-dark-theme.png +0 -0
  41. data/test/snapshots/inkplot/15-category-labels.png +0 -0
  42. data/test/snapshots/inkplot/16-custom-bins.png +0 -0
  43. data/test/snapshots/inkplot/17-connected-gaps.png +0 -0
  44. data/test/snapshots/inkplot/18-step-series.png +0 -0
  45. data/test/snapshots/inkplot/19-combined-marks.png +0 -0
  46. data/test/snapshots/inkplot/20-scatter-sizes.png +0 -0
  47. metadata +41 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b849fabe00ddcb70337337fe69039b30a4d5c6897ba99c1ab23503c856c9355
4
- data.tar.gz: 1303d52c866fbab95d6a933200162b890f2e1deee22c2dc1bc3eb95e7bf3942b
3
+ metadata.gz: 6adf2de18dafb5d84431bcf3d6a9505dfcf17d9a20587045b5a900e554d1c79e
4
+ data.tar.gz: e175007fcd7109ef9f5a35c8c3741b94d733cf436543152fc597cc028d7dfb34
5
5
  SHA512:
6
- metadata.gz: f5c7e69766bb2bd50ed69f680693e90463390b7183366802273c3d940ac343a5a3ec120a94b2afe362438fbca4c6d8b7ecf7afc9af2624583852971240a0122d
7
- data.tar.gz: e4a74f925d2c6d2eec4af35f034f4278531e09e0f3517ce8c82dde71611b0771da34bdf4ea6a3cc548c68cf5690f19137c189985e1a28a1012bf0dbf859c312e
6
+ metadata.gz: b5786c86bf094c6a71e3867b66d1781b0f1c58edd743c36ce843278d4792530a3112c92d996777afc2db548cdf520baf0462dfad27cdae04c6632aa11dd53563
7
+ data.tar.gz: 8923af448e4d10ea8700831876a1c8f8aa0d67379f618e487b72e0ad8aeba50b13ec0b9a391d5eabe19613a21ca0b2da7c010c2db201d8dc13acac3785ef997c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ No 0.2.0 release was published. The 0.3.1 gem contains the PNG and chart features described below.
4
+
5
+ ## [0.3.1] - 2026-09-25
6
+
7
+ - Include the PNG renderer and expanded chart features in the published gem.
8
+ - Resolve optional renderer dependencies from RubyGems.
9
+
10
+ ## [0.3.0] - 2026-09-25
11
+
12
+ - Add PNG rendering, time scales, histograms, category labels, and text annotations.
13
+ - Expand the gallery to 20 charts and add chart-to-Inlay integration.
14
+
3
15
  ## [0.1.0] - 2026-09-25
4
16
 
5
17
  Initial release
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <h1 align="center">Inkplot</h1>
2
2
 
3
- <p align="center">Build clear charts as standalone SVG with plain Ruby data.</p>
3
+ <p align="center">Build clear SVG and PNG charts from plain Ruby data.</p>
4
4
 
5
5
  <p align="center">
6
6
  <a href="https://github.com/rbgfx/inkplot/actions/workflows/main.yml"><img src="https://github.com/rbgfx/inkplot/actions/workflows/main.yml/badge.svg" alt="CI"></a>
@@ -8,14 +8,14 @@
8
8
  <a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-750014.svg" alt="MIT license"></a>
9
9
  </p>
10
10
 
11
- Inkplot draws line, scatter, bar, area, and step charts without native libraries or runtime dependencies.
11
+ Inkplot draws line, scatter, bar, area, histogram, and step charts without runtime dependencies. SVG output uses only Ruby's standard library; optional PNG output needs `tessel` and `glyphic`.
12
12
 
13
13
  ## Install
14
14
 
15
- Until the first RubyGems release, add the GitHub repository to your Gemfile:
15
+ Install the gem:
16
16
 
17
- ```ruby
18
- gem "inkplot", github: "rbgfx/inkplot"
17
+ ```sh
18
+ gem install inkplot
19
19
  ```
20
20
 
21
21
  ## Quick start
@@ -43,11 +43,34 @@ end
43
43
  svg = chart.to_svg
44
44
  ```
45
45
 
46
+ ## PNG output
47
+
48
+ PNG rendering is optional and uses the pure Ruby [Tessel](https://github.com/rbgfx/tessel) and [Glyphic](https://github.com/rbgfx/glyphic) gems:
49
+
50
+ ```sh
51
+ gem install tessel glyphic
52
+ ```
53
+
54
+ ```ruby
55
+ chart = Inkplot.line([3, 1, 4, 1, 5, 9], title: "A small series")
56
+ chart.save("series.png", scale: 2)
57
+ png_bytes = chart.to_png
58
+ ```
59
+
60
+ Set `Inkplot.config.font` to a TrueType font path for Unicode text. Without a font path, PNG output uses Glyphic's small ASCII bitmap font; SVG uses the viewer's system fonts.
61
+
46
62
  ## Data and output
47
63
 
48
- Charts accept arrays, hashes, CSV tables, and records with string or symbol keys. Scales include linear, logarithmic, and ordered categories. Light and dark themes, grouped and stacked bars, and terminal sparklines are included.
64
+ Charts accept arrays, hashes, CSV tables, and records with string or symbol keys. Scales include linear, logarithmic, time (`Time` and `Date`), and ordered categories. Light and dark themes, grouped and stacked bars, annotations, and terminal sparklines are included.
65
+
66
+ ```ruby
67
+ latencies = [12, 13, 15, 15, 18, 21, 26, 42]
68
+ Inkplot.histogram(latencies, bins: :auto, x_label: "ms").save("latencies.svg")
69
+ ```
70
+
71
+ For dated data, configure the x axis with `type: :time`. `plot.annotate(x, y, "text")` places text at a data point; `hline` and `vline` can also carry labels.
49
72
 
50
- The [gallery](examples/gallery/README.md) contains ten runnable examples. Regenerate its SVG previews with:
73
+ The [gallery](examples/gallery/README.md) contains 20 runnable examples. Regenerate its SVG previews with:
51
74
 
52
75
  ```sh
53
76
  ruby examples/gallery.rb
@@ -55,10 +78,11 @@ ruby examples/gallery.rb
55
78
 
56
79
  ## API contracts
57
80
 
58
- - `to_svg` returns a standalone SVG string; `save` writes an `.svg` file.
81
+ - `to_svg` returns a standalone SVG string; `save` writes `.svg` or `.png` files. `to_png` returns PNG bytes and `to_image` returns a `Tessel::Image`.
59
82
  - Paired x/y arrays must have the same length. Non-finite y values break line segments by default; use `gaps: :connect` to bridge them.
60
- - Explicit axis limits must be ordered. Log scales omit non-positive values.
83
+ - Explicit axis limits must be ordered. Log scales omit non-positive values. Time axes reject mixed time zones while preserving local daylight-saving transitions.
61
84
  - Invalid scales, colors, dimensions, and file extensions raise `ArgumentError`.
85
+ - Charts provide `_repr_svg_` for notebook frontends and `to_inlay` for [Inlay](https://github.com/rbgfx/inlay); neither is a runtime dependency.
62
86
 
63
87
  ## Development
64
88
 
data/bench/inkplot.rb CHANGED
@@ -5,8 +5,20 @@ require "inkplot"
5
5
 
6
6
  points = 1_000.times.map { |index| Math.sin(index / 20.0) }
7
7
  line = Inkplot.line(points)
8
+ scatter = Inkplot.scatter(Array.new(10_000) { |index| index }, Array.new(10_000) { |index| (index * 7_919) % 10_000 })
8
9
 
9
10
  puts "YJIT=#{RubyVM::YJIT.enabled?} Ruby=#{RUBY_VERSION}"
10
11
  Benchmark.bm(22) do |bench|
11
12
  bench.report("1k line SVG") { line.to_svg }
12
13
  end
14
+
15
+ begin
16
+ require "tessel"
17
+ require "glyphic"
18
+ Benchmark.bm(22) do |bench|
19
+ bench.report("1k line PNG") { line.to_png }
20
+ bench.report("10k scatter PNG") { scatter.to_png }
21
+ end
22
+ rescue LoadError => e
23
+ warn "PNG benchmarks skipped: #{e.message}"
24
+ end
data/docs/index.html ADDED
@@ -0,0 +1,31 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="theme-color" content="#101113">
7
+ <meta name="description" content="Build clear SVG and PNG charts from plain Ruby data with Inkplot.">
8
+ <title>Inkplot — charts from Ruby</title>
9
+ <style>
10
+ :root{color-scheme:dark;--bg:#101113;--panel:#191b1f;--line:#2c2f34;--text:#f2f0e9;--muted:#a3a5aa;--accent:#c6f277;--mono:ui-monospace,SFMono-Regular,Menlo,monospace;--sans:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif}
11
+ *{box-sizing:border-box}body{margin:0;background:radial-gradient(ellipse at 72% -20%,#293523,transparent 42%),var(--bg);color:var(--text);font:16px/1.6 var(--sans)}a{color:inherit;text-decoration:none}a:hover{color:var(--accent)}.wrap{width:min(1080px,calc(100% - 40px));margin:auto}.nav{height:76px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--line)}.brand{font-size:20px;font-weight:750;letter-spacing:-.04em}.brand span,.tag{color:var(--accent)}.navlinks{display:flex;gap:26px;color:var(--muted);font-size:14px}.hero{padding:94px 0 70px;max-width:800px}.tag{font:12px var(--mono);text-transform:uppercase;letter-spacing:.14em}h1{font-size:clamp(48px,8vw,88px);line-height:.98;letter-spacing:-.075em;margin:22px 0}.hero p{max-width:590px;color:var(--muted);font-size:19px}.actions{display:flex;gap:12px;margin-top:30px;flex-wrap:wrap}.button{padding:11px 17px;border:1px solid var(--line);border-radius:5px;font-weight:650}.primary{background:var(--accent);color:#14170e;border-color:var(--accent)}.install{margin-top:26px;display:inline-flex;gap:18px;background:#090a0b;border:1px solid var(--line);border-radius:6px;padding:12px 15px;font:14px var(--mono)}.install span{color:#72757b}.section{padding:46px 0 70px;border-top:1px solid var(--line)}.sectionhead{display:flex;justify-content:space-between;align-items:end;gap:24px;margin-bottom:24px}.section h2{font-size:28px;letter-spacing:-.045em;margin:8px 0}.sectionhead p{color:var(--muted);margin:0;max-width:420px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.card{background:var(--panel);border:1px solid var(--line);border-radius:8px;overflow:hidden}.card img{display:block;width:100%;aspect-ratio:1.7;object-fit:cover;background:#11151b}.cardbody{padding:14px 16px}.card h3{font-size:15px;margin:0}.card p{font-size:13px;color:var(--muted);margin:4px 0 0}.features{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}.feature{border-left:1px solid var(--line);padding:3px 0 3px 16px}.feature p{margin:4px 0 0;color:var(--muted);font-size:14px}.code{padding:20px;background:#090a0b;border:1px solid var(--line);border-radius:8px;overflow:auto;font:14px/1.8 var(--mono);color:#d8e7c2}.foot{border-top:1px solid var(--line);padding:24px 0 38px;color:var(--muted);font-size:13px;display:flex;justify-content:space-between;gap:16px}
12
+ @media(max-width:700px){.hero{padding:68px 0 54px}.navlinks{gap:14px}.grid,.features{grid-template-columns:1fr}.sectionhead{align-items:start;flex-direction:column}.foot{flex-direction:column}}
13
+ </style>
14
+ </head>
15
+ <body><div class="wrap">
16
+ <nav class="nav" aria-label="Main navigation"><a class="brand" href="#top">ink<span>plot</span></a><div class="navlinks"><a href="#gallery">Gallery</a><a href="https://github.com/rbgfx/inkplot">GitHub</a><a href="https://rubygems.org/gems/inkplot">RubyGems</a></div></nav>
17
+ <main id="top">
18
+ <section class="hero"><div class="tag">A plotting toolkit for Ruby</div><h1>Make data<br>easy to see.</h1><p>Build clear SVG and PNG charts from plain Ruby data. A small, dependency-free core with thoughtful defaults and room to tune the details.</p><div class="actions"><a class="button primary" href="https://github.com/rbgfx/inkplot#quick-start">Read the quick start ↗</a><a class="button" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/README.md">Browse all examples</a></div><div class="install"><span>$</span> gem install inkplot</div></section>
19
+ <section class="section" id="gallery"><div class="sectionhead"><div><div class="tag">Selected work</div><h2>Charts from a few lines of Ruby</h2></div><p>Line, bar, scatter, histogram, and area charts share one consistent API.</p></div><div class="grid">
20
+ <a class="card" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/01-line.svg"><img src="https://raw.githubusercontent.com/rbgfx/inkplot/main/examples/gallery/01-line.svg" alt="Line chart example"><div class="cardbody"><h3>Readable trends</h3><p>Line charts with labeled axes and a restrained grid.</p></div></a>
21
+ <a class="card" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/14-dark-theme.svg"><img src="https://raw.githubusercontent.com/rbgfx/inkplot/main/examples/gallery/14-dark-theme.svg" alt="Dark themed chart example"><div class="cardbody"><h3>Dark theme</h3><p>Charts that sit naturally in dark interfaces.</p></div></a>
22
+ <a class="card" href="https://github.com/rbgfx/inkplot/blob/main/examples/gallery/09-histogram.svg"><img src="https://raw.githubusercontent.com/rbgfx/inkplot/main/examples/gallery/09-histogram.svg" alt="Histogram example"><div class="cardbody"><h3>Distribution at a glance</h3><p>Explore a dataset with an automatic histogram.</p></div></a>
23
+ </div></section>
24
+ <section class="section"><div class="sectionhead"><div><div class="tag">Quick start</div><h2>From values to SVG</h2></div></div><pre class="code"><code>require "inkplot"
25
+
26
+ chart = Inkplot.line([3, 1, 4, 1, 5, 9], title: "A small series")
27
+ chart.save("series.svg")</code></pre></section>
28
+ <section class="section"><div class="features"><div class="feature"><strong>Plain Ruby data</strong><p>Arrays, hashes, CSV tables, and records with string or symbol keys.</p></div><div class="feature"><strong>SVG by default</strong><p>Standalone SVG from Ruby's standard library. Optional PNG rendering is pure Ruby.</p></div><div class="feature"><strong>Useful scales</strong><p>Linear, logarithmic, time, and ordered category axes, plus dark and light themes.</p></div></div></section>
29
+ </main><footer class="foot"><span>Inkplot · Charts from Ruby</span><span><a href="https://github.com/rbgfx/inkplot">Source</a> · MIT License</span></footer>
30
+ </div></body>
31
+ </html>
@@ -1 +1 @@
1
- <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="60" y="40" width="562" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 60 306 L 622 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="310" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 60 217.33 L 622 217.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="221.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 60 128.67 L 622 128.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="132.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 106.83 40 L 106.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="106.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W1</text><path class="grid-line" d="M 200.5 40 L 200.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="200.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W2</text><path class="grid-line" d="M 294.17 40 L 294.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="294.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W3</text><path class="grid-line" d="M 387.83 40 L 387.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="387.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W4</text><path class="grid-line" d="M 481.5 40 L 481.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="481.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W5</text><path class="grid-line" d="M 575.17 40 L 575.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="575.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W6</text><path class="axis-line" d="M 60 40 L 60 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Weekly signups</text><text x="341" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Week</text><text x="14" y="180" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-90 14 180)">People</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 106.83 226.2 L 200.5 195.17 L 294.17 212.9 L 387.83 146.4 L 481.5 115.37 L 575.17 48.87" fill="none" stroke="#0072B2" stroke-width="2"/></g></g></svg>
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="60" y="40" width="562" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 60 306 L 622 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="310" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 60 217.33 L 622 217.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="221.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 60 128.67 L 622 128.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="52" y="132.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 106.83 40 L 106.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="106.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W1</text><path class="grid-line" d="M 200.5 40 L 200.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="200.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W2</text><path class="grid-line" d="M 294.17 40 L 294.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="294.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W3</text><path class="grid-line" d="M 387.83 40 L 387.83 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="387.83" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W4</text><path class="grid-line" d="M 481.5 40 L 481.5 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="481.5" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W5</text><path class="grid-line" d="M 575.17 40 L 575.17 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="575.17" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">W6</text><path class="axis-line" d="M 60 40 L 60 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Weekly signups</text><text x="341" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Week</text><text x="14" y="180" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-90 14 180)">People</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 106.83 226.2 L 200.5 195.17 L 294.17 212.9 L 387.83 146.4 L 481.5 115.37 L 575.17 48.87" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -1 +1 @@
1
- <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 297.4 L 622 297.4" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="301.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2.0</text><path class="grid-line" d="M 42 240.2 L 622 240.2" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="244.2" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4.0</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">3.0</text><path class="grid-line" d="M 42 125.8 L 622 125.8" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="129.8" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6.0</text><path class="grid-line" d="M 42 68.6 L 622 68.6" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="72.6" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">7.0</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Missing values break a line</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 297.4 L 114.5 240.2" fill="none" stroke="#0072B2" stroke-width="2"/><path class="mark-line" d="M 259.5 183 L 332 125.8" fill="none" stroke="#0072B2" stroke-width="2"/><path class="mark-line" d="M 477 240.2 L 549.5 68.6" fill="none" stroke="#0072B2" stroke-width="2"/></g></g></svg>
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 297.4 L 622 297.4" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="301.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2.0</text><path class="grid-line" d="M 42 240.2 L 622 240.2" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="244.2" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4.0</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">3.0</text><path class="grid-line" d="M 42 125.8 L 622 125.8" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="129.8" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6.0</text><path class="grid-line" d="M 42 68.6 L 622 68.6" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="72.6" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">7.0</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Missing values break a line</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 297.4 L 114.5 240.2" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/><path class="mark-line" d="M 259.5 183 L 332 125.8" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/><path class="mark-line" d="M 477 240.2 L 549.5 68.6" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -1 +1 @@
1
- <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 230.67 L 502 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">50</text><path class="grid-line" d="M 42 135.33 L 502 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">100</text><text x="195.33" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="348.67" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="502" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Two latency percentiles</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p50</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p99</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 118.67 245.92 L 195.33 253.55 L 272 228.76 L 348.67 238.29 L 425.33 263.08 L 502 270.71" fill="none" stroke="#0072B2" stroke-width="2"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 118.67 150.59 L 195.33 120.08 L 272 106.73 L 348.67 141.05 L 425.33 169.65 L 502 181.09" fill="none" stroke="#E69F00" stroke-width="2" stroke-dasharray="5 4"/></g></g></svg>
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 230.67 L 502 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">50</text><path class="grid-line" d="M 42 135.33 L 502 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">100</text><text x="195.33" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="348.67" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="502" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Two latency percentiles</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p50</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">p99</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 118.67 245.92 L 195.33 253.55 L 272 228.76 L 348.67 238.29 L 425.33 263.08 L 502 270.71" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 118.67 150.59 L 195.33 120.08 L 272 106.73 L 348.67 141.05 L 425.33 169.65 L 502 181.09" fill="none" stroke="#E69F00" stroke-width="2" stroke-dasharray="5 4" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 306 L 622 306" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="310" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 239.5 L 622 239.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="243.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><path class="grid-line" d="M 42 173 L 622 173" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="177" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><path class="grid-line" d="M 42 106.5 L 622 106.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="110.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><text x="187" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><text x="332" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><text x="477" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="axis-line" d="M 42 40 L 42 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Request latency</text><text x="332" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">ms</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="histogram-mark" x="71" y="73.25" width="108.75" height="232.75" fill="#0072B2"/><rect class="histogram-mark" x="179.75" y="173" width="108.75" height="133" fill="#0072B2"/><rect class="histogram-mark" x="288.5" y="272.75" width="108.75" height="33.25" fill="#0072B2"/><rect class="histogram-mark" x="397.25" y="239.5" width="108.75" height="66.5" fill="#0072B2"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="266"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 217.33 L 622 217.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="221.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 42 128.67 L 622 128.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="132.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">60</text><text x="42" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-01</text><text x="144.46" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-03</text><text x="250.38" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-05</text><text x="356.31" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-07</text><text x="463.98" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-09</text><text x="569.9" y="324" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2026-11</text><path class="axis-line" d="M 42 40 L 42 306 L 622 306" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Monthly active users</text><text x="332" y="355" fill="#20242B" text-anchor="middle" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Month</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 243.93 L 95.83 230.63 L 144.46 235.07 L 198.29 208.47 L 250.38 181.87 L 304.22 168.57 L 356.31 177.43 L 410.14 141.97 L 463.98 119.8 L 516.07 102.07 L 569.9 75.47 L 622 44.43" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 230.67 L 622 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="grid-line" d="M 42 135.33 L 622 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">50</text><path class="grid-line" d="M 114.5 40 L 114.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="114.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.0</text><path class="grid-line" d="M 259.5 40 L 259.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="259.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.1</text><path class="grid-line" d="M 404.5 40 L 404.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="404.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.2</text><path class="grid-line" d="M 549.5 40 L 549.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="549.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">v1.3</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Release performance</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 114.5 287.87 L 259.5 211.6 L 404.5 240.2 L 549.5 87.67" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g><path class="rule-line" d="M 42 183 L 622 183" fill="none" stroke="#D55E00" stroke-width="1.5" stroke-dasharray="5 4"/><text x="618" y="179" fill="#D55E00" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Target</text><path class="rule-line" d="M 404.5 40 L 404.5 326" fill="none" stroke="#0072B2" stroke-width="1.5" stroke-dasharray="5 4"/><text x="408.5" y="52" fill="#0072B2" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Cache enabled</text><text x="549.5" y="87.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">peak</text></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#171B22"/><path class="grid-line" d="M 42 254.5 L 502 254.5" fill="none" stroke="#303744" stroke-width="1"/><text x="34" y="258.5" fill="#A9B2C0" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><path class="grid-line" d="M 42 183 L 502 183" fill="none" stroke="#303744" stroke-width="1"/><text x="34" y="187" fill="#A9B2C0" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">15</text><path class="grid-line" d="M 42 111.5 L 502 111.5" fill="none" stroke="#303744" stroke-width="1"/><text x="34" y="115.5" fill="#A9B2C0" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 88 40 L 88 326" fill="none" stroke="#303744" stroke-width="1"/><text x="88" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Mon</text><path class="grid-line" d="M 180 40 L 180 326" fill="none" stroke="#303744" stroke-width="1"/><text x="180" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Tue</text><path class="grid-line" d="M 272 40 L 272 326" fill="none" stroke="#303744" stroke-width="1"/><text x="272" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Wed</text><path class="grid-line" d="M 364 40 L 364 326" fill="none" stroke="#303744" stroke-width="1"/><text x="364" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Thu</text><path class="grid-line" d="M 456 40 L 456 326" fill="none" stroke="#303744" stroke-width="1"/><text x="456" y="344" fill="#A9B2C0" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Fri</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#A9B2C0" stroke-width="1"/><text x="320" y="22" fill="#E8ECF2" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Dark theme</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#E8ECF2" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Deploys</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#E8ECF2" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Rollbacks</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 88 225.9 L 180 168.7 L 272 197.3 L 364 82.9 L 456 125.8" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 88 283.1 L 180 268.8 L 272 211.6 L 364 225.9 L 456 140.1" fill="none" stroke="#E69F00" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="244"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 284 L 622 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="288" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 223 L 622 223" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="227" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><path class="grid-line" d="M 42 162 L 622 162" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="166" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 42 101 L 622 101" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="105" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><path class="grid-line" d="M 58.11 40 L 58.11 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="58.11" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 58.11 302)">Region 1 very long</text><path class="grid-line" d="M 187 40 L 187 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="187" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 187 302)">Region 5 very long</text><path class="grid-line" d="M 315.89 40 L 315.89 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="315.89" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 315.89 302)">Region 9 very long</text><path class="grid-line" d="M 444.78 40 L 444.78 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="444.78" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 444.78 302)">Region 13 very long</text><path class="grid-line" d="M 573.67 40 L 573.67 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="573.67" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 573.67 302)">Region 17 very long</text><path class="grid-line" d="M 605.89 40 L 605.89 284" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="605.89" y="302" fill="#626B78" text-anchor="end" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'" transform="rotate(-45 605.89 302)">Region 18 very long</text><path class="axis-line" d="M 42 40 L 42 284 L 622 284" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Regional volume</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="bar-mark" x="44.99" y="216.9" width="25.24" height="67.1" fill="#0072B2"/><rect class="bar-mark" x="77.21" y="174.2" width="25.24" height="109.8" fill="#0072B2"/><rect class="bar-mark" x="109.44" y="131.5" width="25.24" height="152.5" fill="#0072B2"/><rect class="bar-mark" x="141.66" y="88.8" width="25.24" height="195.2" fill="#0072B2"/><rect class="bar-mark" x="173.88" y="235.2" width="25.24" height="48.8" fill="#0072B2"/><rect class="bar-mark" x="206.1" y="192.5" width="25.24" height="91.5" fill="#0072B2"/><rect class="bar-mark" x="238.32" y="149.8" width="25.24" height="134.2" fill="#0072B2"/><rect class="bar-mark" x="270.55" y="107.1" width="25.24" height="176.9" fill="#0072B2"/><rect class="bar-mark" x="302.77" y="253.5" width="25.24" height="30.5" fill="#0072B2"/><rect class="bar-mark" x="334.99" y="210.8" width="25.24" height="73.2" fill="#0072B2"/><rect class="bar-mark" x="367.21" y="168.1" width="25.24" height="115.9" fill="#0072B2"/><rect class="bar-mark" x="399.44" y="125.4" width="25.24" height="158.6" fill="#0072B2"/><rect class="bar-mark" x="431.66" y="82.7" width="25.24" height="201.3" fill="#0072B2"/><rect class="bar-mark" x="463.88" y="229.1" width="25.24" height="54.9" fill="#0072B2"/><rect class="bar-mark" x="496.1" y="186.4" width="25.24" height="97.6" fill="#0072B2"/><rect class="bar-mark" x="528.32" y="143.7" width="25.24" height="140.3" fill="#0072B2"/><rect class="bar-mark" x="560.55" y="101" width="25.24" height="183" fill="#0072B2"/><rect class="bar-mark" x="592.77" y="247.4" width="25.24" height="36.6" fill="#0072B2"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 326 L 622 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="330" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 230.67 L 622 230.67" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="234.67" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><path class="grid-line" d="M 42 135.33 L 622 135.33" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="139.33" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><text x="622" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Custom latency ranges</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="histogram-mark" x="42" y="87.67" width="145" height="238.33" fill="#0072B2"/><rect class="histogram-mark" x="187" y="183" width="145" height="143" fill="#0072B2"/><rect class="histogram-mark" x="332" y="183" width="145" height="143" fill="#0072B2"/><rect class="histogram-mark" x="477" y="278.33" width="145" height="47.67" fill="#0072B2"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 305.57 L 622 305.57" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="309.57" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2.0</text><path class="grid-line" d="M 42 264.71 L 622 264.71" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="268.71" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">3.0</text><path class="grid-line" d="M 42 223.86 L 622 223.86" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="227.86" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">5.0</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6.0</text><path class="grid-line" d="M 42 142.14 L 622 142.14" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="146.14" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4.0</text><path class="grid-line" d="M 42 101.29 L 622 101.29" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="105.29" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">7.0</text><path class="grid-line" d="M 42 60.43 L 622 60.43" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="64.43" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">8.0</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><text x="622" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">8</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Bridge short gaps</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 305.57 L 114.5 264.71 L 259.5 223.86 L 332 183 L 477 142.14 L 549.5 101.29 L 622 60.43" fill="none" stroke="#0072B2" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 268.8 L 622 268.8" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="272.8" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">60</text><path class="grid-line" d="M 42 211.6 L 622 211.6" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="215.6" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">80</text><path class="grid-line" d="M 42 154.4 L 622 154.4" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="158.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">100</text><path class="grid-line" d="M 42 97.2 L 622 97.2" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="101.2" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">120</text><text x="42" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><text x="235.33" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><text x="428.67" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><text x="622" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Rate limit changes</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><path class="mark-line" d="M 42 297.4 L 138.67 297.4 L 138.67 297.4 L 235.33 297.4 L 235.33 225.9 L 332 225.9 L 332 225.9 L 428.67 225.9 L 428.67 154.4 L 525.33 154.4 L 525.33 154.4 L 622 154.4 L 622 82.9" fill="none" stroke="#0072B2" stroke-width="2"/></g><path class="rule-line" d="M 42 154.4 L 622 154.4" fill="none" stroke="#626B78" stroke-width="1.5" stroke-dasharray="5 4"/><text x="618" y="150.4" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Current limit</text></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="460" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 326 L 502 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="330" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">0</text><path class="grid-line" d="M 42 254.5 L 502 254.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="258.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><path class="grid-line" d="M 42 183 L 502 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><path class="grid-line" d="M 42 111.5 L 502 111.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="115.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><path class="grid-line" d="M 99.5 40 L 99.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="99.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q1</text><path class="grid-line" d="M 214.5 40 L 214.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="214.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q2</text><path class="grid-line" d="M 329.5 40 L 329.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="329.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q3</text><path class="grid-line" d="M 444.5 40 L 444.5 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="444.5" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Q4</text><path class="axis-line" d="M 42 40 L 42 326 L 502 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Quarterly sales</text><path class="mark-line" d="M 390 54 L 406 54" fill="none" stroke="#0072B2" stroke-width="2"/><text x="412" y="58" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Previous</text><path class="mark-line" d="M 390 72 L 406 72" fill="none" stroke="#E69F00" stroke-width="2"/><text x="412" y="76" fill="#20242B" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Current</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><rect class="bar-mark" x="52.35" y="211.6" width="93.3" height="114.4" fill="#0072B2"/><rect class="bar-mark" x="167.35" y="183" width="93.3" height="143" fill="#0072B2"/><rect class="bar-mark" x="282.35" y="197.3" width="93.3" height="128.7" fill="#0072B2"/><rect class="bar-mark" x="397.35" y="132.95" width="93.3" height="193.05" fill="#0072B2"/></g><g class="series series-1" data-series="1"><path class="mark-line" d="M 99.5 190.15 L 214.5 147.25 L 329.5 154.4 L 444.5 82.9" fill="none" stroke="#E69F00" stroke-width="2" stroke-linecap="butt" stroke-linejoin="miter"/></g></g></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360" width="640" height="360" role="img" class="inkplot"><defs><clipPath id="plot-clip"><rect x="42" y="40" width="580" height="286"/></clipPath></defs><rect x="0" y="0" width="640" height="360" fill="#FFFFFF"/><path class="grid-line" d="M 42 326 L 622 326" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="330" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">2</text><path class="grid-line" d="M 42 254.5 L 622 254.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="258.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">4</text><path class="grid-line" d="M 42 183 L 622 183" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="187" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">6</text><path class="grid-line" d="M 42 111.5 L 622 111.5" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="115.5" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">8</text><path class="grid-line" d="M 42 40 L 622 40" fill="none" stroke="#E7EAF0" stroke-width="1"/><text x="34" y="44" fill="#626B78" text-anchor="end" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">10</text><text x="187" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">20</text><text x="332" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">30</text><text x="477" y="344" fill="#626B78" text-anchor="middle" font-size="10" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">40</text><path class="axis-line" d="M 42 40 L 42 326 L 622 326" fill="none" stroke="#626B78" stroke-width="1"/><text x="320" y="22" fill="#20242B" text-anchor="middle" font-size="15" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">Session length vs. pages</text><g class="series-marks" clip-path="url(#plot-clip)"><g class="series series-0" data-series="0"><circle class="series-point" cx="71" cy="326" r="4" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="158" cy="290.25" r="4.71" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="201.5" cy="218.75" r="5.43" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="288.5" cy="254.5" r="4.71" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="361" cy="147.25" r="6.86" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="448" cy="111.5" r="7.57" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/><circle class="series-point" cx="535" cy="40" r="9" fill="#0072B2" stroke="#FFFFFF" stroke-width="1"/></g><text x="448" y="111.5" fill="#626B78" text-anchor="start" font-size="11" font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif, 'Noto Sans CJK JP'">engaged</text></g></svg>
@@ -8,4 +8,9 @@ Generated by [`../gallery.rb`](../gallery.rb). Run `ruby examples/gallery.rb` fr
8
8
  | Series | ![Multiple series](03-series.svg) | Scatter | ![Scatter plot](04-scatter.svg) |
9
9
  | Bars | ![Bars](05-bars.svg) | Horizontal bars | ![Horizontal bars](06-horizontal-bars.svg) |
10
10
  | Grouped bars | ![Grouped bars](07-grouped-bars.svg) | Stacked bars | ![Stacked bars](08-stacked-bars.svg) |
11
- | Area | ![Area chart](10-area.svg) | Step | ![Step chart](11-step.svg) |
11
+ | Histogram | ![Request latency histogram](09-histogram.svg) | Area | ![Area chart](10-area.svg) |
12
+ | Step | ![Step chart](11-step.svg) | Time scale | ![Time series](12-time.svg) |
13
+ | Annotations | ![Release annotations](13-annotations.svg) | Dark theme | ![Dark theme](14-dark-theme.svg) |
14
+ | Category labels | ![Dense categories](15-category-labels.svg) | Custom bins | ![Custom histogram bins](16-custom-bins.svg) |
15
+ | Connected gaps | ![Connected gaps](17-connected-gaps.svg) | Step series | ![Rate limit step chart](18-step-series.svg) |
16
+ | Combined marks | ![Bars and line](19-combined-marks.svg) | Scatter sizes | ![Scatter size mapping](20-scatter-sizes.svg) |
data/examples/gallery.rb CHANGED
@@ -31,8 +31,40 @@ module InkplotGallery
31
31
  p.bar(%w[Mon Tue Wed Thu Fri], [12, 16, 11, 19, 22], label: "Direct", stacked: true)
32
32
  p.bar(%w[Mon Tue Wed Thu Fri], [8, 9, 13, 10, 14], label: "Search", stacked: true)
33
33
  end],
34
+ ["09-histogram", Inkplot.histogram([12, 14, 15, 15, 16, 18, 19, 20, 22, 24, 25, 31, 35, 42], title: "Request latency", bins: :auto, x_label: "ms")],
34
35
  ["10-area", Inkplot.plot(title: "Build time over a release") { |p| p.area((1..8).to_a, [25, 29, 27, 38, 36, 44, 40, 51], label: "Seconds") }],
35
- ["11-step", Inkplot.plot(title: "Queue depth") { |p| p.step((0..7).to_a, [3, 3, 5, 5, 4, 8, 8, 2], label: "Jobs") }]
36
+ ["11-step", Inkplot.plot(title: "Queue depth") { |p| p.step((0..7).to_a, [3, 3, 5, 5, 4, 8, 8, 2], label: "Jobs") }],
37
+ ["12-time", Inkplot.plot(title: "Monthly active users") do |p|
38
+ p.x_axis(label: "Month", type: :time)
39
+ p.line((0..11).map { |month| Time.utc(2026, month + 1, 1) }, [34, 37, 36, 42, 48, 51, 49, 57, 62, 66, 72, 79], label: "Users")
40
+ end],
41
+ ["13-annotations", Inkplot.plot(title: "Release performance") do |p|
42
+ p.line(%w[v1.0 v1.1 v1.2 v1.3], [34, 42, 39, 55], label: "Requests/s")
43
+ p.hline(45, label: "Target", color: "#D55E00")
44
+ p.vline("v1.2", label: "Cache enabled", color: "#0072B2")
45
+ p.annotate("v1.3", 55, "peak", anchor: :end)
46
+ end],
47
+ ["14-dark-theme", Inkplot.plot(title: "Dark theme", theme: :dark) do |p|
48
+ p.line(%w[Mon Tue Wed Thu Fri], [12, 16, 14, 22, 19], label: "Deploys")
49
+ p.line(%w[Mon Tue Wed Thu Fri], [8, 9, 13, 12, 18], label: "Rollbacks")
50
+ end],
51
+ ["15-category-labels", Inkplot.bar((1..18).to_h { |index| ["Region #{index} very long", ((index * 7) % 31) + 4] }, title: "Regional volume")],
52
+ ["16-custom-bins", Inkplot.histogram([2, 4, 5, 7, 9, 11, 14, 18, 21, 24, 28, 35], bins: [0, 10, 20, 30, 40], title: "Custom latency ranges")],
53
+ ["17-connected-gaps", Inkplot.plot(title: "Bridge short gaps") do |p|
54
+ p.line((0..8).to_a, [2, 3, nil, 5, 6, nil, 4, 7, 8], label: "Estimated", gaps: :connect)
55
+ end],
56
+ ["18-step-series", Inkplot.plot(title: "Rate limit changes") do |p|
57
+ p.step((0..6).to_a, [50, 50, 75, 75, 100, 100, 125], label: "Requests/min")
58
+ p.hline(100, label: "Current limit")
59
+ end],
60
+ ["19-combined-marks", Inkplot.plot(title: "Quarterly sales") do |p|
61
+ p.bar(%w[Q1 Q2 Q3 Q4], [16, 20, 18, 27], label: "Previous")
62
+ p.line(%w[Q1 Q2 Q3 Q4], [19, 25, 24, 34], label: "Current")
63
+ end],
64
+ ["20-scatter-sizes", Inkplot.plot(title: "Session length vs. pages") do |p|
65
+ p.scatter([12, 18, 21, 27, 32, 38, 44], [2, 3, 5, 4, 7, 8, 10], size: [1, 2, 3, 2, 5, 6, 8], label: "Sessions")
66
+ p.annotate(38, 8, "engaged")
67
+ end]
36
68
  ]
37
69
  end
38
70
  end