+ say '<style>';
+ for my $row (pairs @table) {
+ my ($id, $info) = @{$row};
+ my $style = $info->{style} or next;
+ ref $style or $style = [$style];
+ say "\t", !/^@/ && "#$id ", $_ for @{$style};
+ }
+ say "</style>\n";
+
+ my %VOWELCOLS = (map { ($_ => 1) } 0, 4, 8, 14, 20, 24);
+ say '<table class="glyphs">';
+ say '<thead><tr><th># <small>ASCII − 64</small>';
+ print '<td>', $_ for 1 .. 26;
+ say '</thead>';
+
+ for my $row (pairs @table) {
+ my ($id, $info) = @{$row};
+
+ printf '<tr id="%s">', $id;
+ my $th = 'th';
+ $th .= sprintf ' title="%s"', $_ for $info->{title} || ();
+ say "<$th>", $info->{name} // ucfirst $id;
+
+ my $colspan = 1;
+ my $col = 0;
+ for (@{ $info->{list} }) {
+ $col++;
+ if ($_ eq '>') {
+ $colspan++;
+ next;
+ }
+ my @class;
+ push @class ,'l0' if $VOWELCOLS{$col - $colspan};
+ push @class, $_ ? 'ex' : 'u-invalid' if s/^-//;
+
+ print "\t<td";
+ if ($col > 26) {
+ # special character for sample generation
+ print ' hidden'; # sample only
+ }
+ else {
+ print ' title=', chr($col + ord('A') - $colspan);
+ }
+ if ($colspan > 1) {
+ print " colspan=$colspan";
+ $colspan = 1;
+ }
+ printf ' class="%s"', "@class" if @class;
+ print '>';
+ say;
+ }
+ }
+ say "</table>\n";