+} || $get{q};
+
+say "<h1>$title</h1>";
+
+if (!$query) {
+ Abort(["Unicode group not found", $@], '404 no matches');
+};
+
+for ($parent || 'Unicode range') {
+ my %CATDESC = (
+ block => '<a href="/charset/unicode">Unicode block</a>',
+ script => 'Unicode script',
+ category => 'Unicode category',
+ table => '<a href="/unicode">Unicode preset group</a>',
+ );
+ say sprintf('<p>List %s in selected %s.</p>',
+ 'characters and <a href="/font">font support</a>',
+ $CATDESC{$parent} || $parent,
+ );
+}
+
+my @chars;
+for (map { split /[^\d-]/ } $query) {
+ my @range = split /-/, $_, 2;
+ m/^[0-9]+$/ or Abort("Invalid code point $_ in query $query", 400)
+ for @range;
+ push @chars, chr $_ for $range[0] .. ($range[1] // $range[0]);