2 * Nick's web site: default stylesheet
4 * Copyright © 2018-2022 Nick Bowler
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 @import "lib/colourmap.scss";
23 ( $background: #ffffff #000000
24 , $foreground: #000000 #ffffff
26 , $linkdefault: #0000cd #a3aaff
27 , $linkactive: #ff0000
28 , $linkvisited: #800080 #e493f7
31 , $annotation: #708090
32 , $tableshade: #f5f5f5 #101010
34 , $ruledefault: #d3d3d3 #494949
35 , $rulestrong: #696969 #939393
38 @mixin header_size($maxwidth, $fontsize) {
40 max-width: 1em * ($maxwidth / $fontsize);
43 html { @include usecolours($background-color: background); }
45 @include usecolours($color: foreground);
46 font-family: sans-serif;
51 @include usecolours($color: linkdefault, $border-color: linkdefault);
54 @include usecolours($color: linkvisited, $border-color: linkvisited);
57 @include usecolours($color: linkactive, $border-color: linkactive);
60 @supports (outline-style: auto) {
61 a:link { border-width: 0; }
62 a:focus { @include usecolour(outline, focusring, auto); }
63 li, td, dt { &>a:link { border: solid 1px transparent; } }
66 h1 { @include header_size(60em, 2em); }
67 h2 { @include header_size(60em, 1.5em); }
68 h5 { @include header_size(60em, 1em); }
70 h1, h2 { abbr { text-decoration: none; } }
72 @supports (display: grid) {
76 grid-template-columns: repeat( auto-fill, minmax(18em, 1fr) );
79 p.img { margin: 0.5em 0; }
82 @media (max-width: 45em) {
86 a { max-width: 24em; }
97 vertical-align: bottom;
104 text-decoration: none;
105 display: inline-block;
109 a.left { margin: 0 1em 0.5em 0; float: left; clear: left; }
110 a.right { margin: 0 0 0.5em 1em; float: right; clear: right; }
112 @media (max-width: 45em) { float: none; margin: 0; }
118 @include usecolours($color: foreground);
119 @media (max-width: 24em) { text-align: left; }
122 display: -moz-inline-box;
123 display: inline-block;
131 @media (max-width: 28em) { text-align: left; }
136 p, table, div, ul, ol, dl, hr {
142 p, table, body>div, h5 { margin: 1em 0; }
144 @media (max-width: 28em) { margin: 1em 0.5em; }
148 li { margin: 0 0 0 2em; }
149 dd { margin: 0 0 0 1em; }
155 @include usecolour(border-top, ruledefault, 1px solid);
159 font-family: monospace;
161 &:before { content: "% "; }
162 &.ok:before { content: "ok "; }
163 &>span { white-space: nowrap; }
167 & + br { display: none; }
175 @include usecolours($color: annotation);
178 a:link, a:visited { color: inherit; }
179 a:active { @include usecolours($color: linkactive); }
180 @media not screen { visibility: hidden; }
183 // General table styles.
185 @include usecolour(border-top, ruledefault, 1px solid);
186 border-collapse: collapse;
191 table>* { font-size: 0.9em; }
201 vertical-align: middle;
207 thead>tr, tbody>tr { @include usecolour(border, ruledefault, solid); }
208 th, thead>tr { @include usecolour(border-bottom, rulestrong, 1px solid); }
209 tbody+tbody { @include usecolour(border-bottom, ruledefault, 1px solid); }
210 *>table, *>th { border: none; }
211 thead>tr { border-width: 1px; }
212 tbody>tr { border-width: 0 1px; }
215 @include usecolour(box-shadow, background, -1px 0);
219 &:nth-of-type(even) { @include usecolours($background-color: tableshade); }
220 &:last-child { @include usecolour(border-bottom, ruledefault, solid 1px); }
223 // Specific table styles
225 &>tr>*:first-child, &>*>tr>*:first-child {
226 &+* { text-align: center; }
231 // CSS rules for sortable clicky table headers: Update the display of
232 // the table based on the current state. Each column has its own set
233 // nearly-identical rules, only the class names differ.
235 // The clickytables.xsl stylesheet generates two inputs for each column.
236 // These inputs are siblings of the table and all precede it in document
237 // order. Moreover, the inputs for a column are ordered with respect to
238 // each other, in this sequence:
240 // input.clicky-NAME -- checked iff NAME is selected for sorting.
241 // input.clicky-NAME-rev -- checked to select reverse order.
243 // One of the column selection inputs will have a 'checked' attribute to
244 // indicate the default order. This input is always first in document
245 // order. No other inputs begin checked.
247 // The table itself consists of a thead (where the header labels are
248 // located) and two tbody elements. The bulk of these rules relate
249 // to updating the headers to visually indicate the current state.
251 // A sortable column's th element has the .clicky-NAME class, matching
252 // its corresponding inputs, and has two label children. The first label
253 // is visible only when the column is unselected, and is linked to the
254 // .clicky-NAME input to activate that column. The second label is visible
255 // only on the selected column and is linked to the .clicky-NAME-rev input
256 // to toggle the reverse order.
258 // For the table body, the first tbody contains the default ordering
259 // and is not styled by these rules (except to hide it when alternate
260 // orderings are selected). The second tbody contains rows for all
261 // alternate orderings, and is revealed by these rules. When revealed,
262 // rows with the NAMEfwd or NAMErev class (for the forward and reverse
263 // orderings, respectively) are shown and other rows are hidden.
265 $clickynames: name, date, size;
266 @each $col in $clickynames {
267 input.clicky-#{$col} {
270 // Update table header state
271 & th.clicky-#{$col} {
273 display: -moz-inline-box !important;
274 display: inline-block !important;
276 label { display: none; }
279 // Show only appropriate items from the sort body (forward)
280 &>tbody+tbody>tr.#{$col}fwd { display: table-row; }
281 &>tbody+tbody>tr { display: none; }
285 &+tbody { display: table-row-group !important; }
290 // reverse state for selected sort column
291 &~input.clicky-#{$col}-rev {
293 // Show only appropriate items from sort body (reversed)
294 &>tbody+tbody>tr.#{$col}rev { display: table-row; }
295 &>tbody+tbody>tr { display: none; }
299 &+tbody { display: table-row-group !important; }
304 // Unhide to allow keyboard navigation to this input
305 display: block !important;
309 // If default input element is the only one selected, match it to
310 // return to default view (overriding the changes above). It is
311 // always the first input element among all the sibling elements.
312 // This seems to interoperate better than using the [checked] or
313 // :first-of-type selectors.
314 @at-root &:first-child, :not(input)+& {
315 &:checked~table>tbody {
316 &+tbody { display: none !important; }
317 display: table-row-group;
321 // Unhide to allow keyboard navigation
322 display: block !important;
323 pointer-events: none;
329 input.clicky-#{$col}-rev {
331 // Update table header state
332 & th.clicky-#{$col} {
334 display: -moz-inline-box !important;
335 display: inline-block !important;
337 .svg { display: none; }
341 pointer-events: none;
347 $focuslabel: ":focus ~ table th.clicky-#{$col}>label~label";
348 #{"input.clicky-#{$col+$focuslabel}"}>span:first-child
349 , #{"input.clicky-#{$col}-rev#{$focuslabel}"} .svg
351 @include usecolours($border-color: foreground);
352 @at-root { @supports (outline-style: auto) { & {
353 @include usecolour(outline, focusring, auto);
354 border-color: transparent !important;
365 display: -moz-inline-box;
366 display: inline-block;
367 border: 1px dotted transparent;
368 vertical-align: middle;
371 // Expand the first label a bit so the table (hopefully)
372 // does not reshape as columns are selected.
374 margin-right: 1.75em;
378 &:active { @include usecolours($color: linkactive); }
379 &:first-child:active>span, &~label:active>.svg {
380 @include usecolours($border-color: linkactive);
381 @at-root { @supports (outline-style: auto) { & {
382 @include usecolour(outline, focusring, auto);
383 border-color: transparent;
391 .svg, svg, img.svgfallback {
395 .svg svg { width: 1.5em; }
399 &>*>tr>*:first-child {
401 // chrome doesn't like width: 0 for some reason
406 .svg, svg, img.svgfallback {
407 vertical-align: middle;
413 svg { width: 1.5em; }
414 display: inline-block;
420 #breadcrumbs>*, #sitetitle>* { font-size: 0.8em; }
424 list-style-type: none;
430 li + li:before { content: "/ "; }
433 display: inline-block;
438 #footer, #article-info {
445 display: inline-block;
452 #footer p { @include usecolours($color: annotation); }
453 #article-info p { font-style: italic; }
455 .wbr:after { content: "\200b"; }
457 // "unordered" lists with explicit ordering in content
459 li { list-style: none; }
460 li>span:first-child, li>*:first-child>span:first-child {
461 display: inline-block;
468 @media (max-width: 512px) {
469 body { margin: 0.6em; }
470 ul ul { margin-left: -1.2em; }
474 @media (max-width: 35em) {
475 #sitetitle * { float: none; }
476 #footer { padding: 0 1em; }
479 // lighten icon shadows in dark mode
480 @media (prefers-color-scheme: dark) {
481 svg.icons { path.shadow, g.shadow>* { opacity: 0.7; } }
482 svg.icons .shadow>stop { stop-color: #aaa; }
483 svg.return path.shadow { opacity: 0.45; }
486 // page-specific dark mode styles
487 @media (prefers-color-scheme: dark) and (min-width: 35em) {
488 #page_weblog_responsive_tables {
489 @each $tN in t6 t7 t8 {
490 ##{$tN}>tbody>tr.#{$tN}-split {
491 @include usecolour_dark_(border-bottom, ruledefault);
493 &:nth-of-type(odd) ~ tr:nth-of-type(odd) {
494 @include usecolour_dark_(background-color, tableshade);