]> git.draconx.ca Git - homepage.git/blob - content/style.scss
Solar Eclipse in Ottawa on 2021-06-10.
[homepage.git] / content / style.scss
1 /*!
2  * Nick's web site: default stylesheet
3  *
4  * Copyright © 2018-2021 Nick Bowler
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 // colour definitions
21 $backgroundcolour:  #ffffff;
22 $foregroundcolour:  #000000;
23
24 $linkdefaultcolour: #0000cd;
25 $linkactivecolour:  #ff0000;
26 $linkvisitedcolour: #800080;
27
28 $ruledefaultcolour: #d3d3d3;
29 $rulestrongcolour:  #696969;
30
31 $annotationcolour:  #708090;
32
33 $tableshadecolour:  #f5f5f5;
34
35 @mixin header_size($maxwidth, $fontsize) {
36     font-size: $fontsize;
37     max-width: 1em * ($maxwidth / $fontsize);
38 }
39
40 body {
41     background-color: $backgroundcolour;
42     color: $foregroundcolour;
43     font-family: sans-serif;
44     margin: 1em;
45 }
46
47 a:link { color: $linkdefaultcolour; border-color: $linkdefaultcolour; }
48 a:visited { color: $linkvisitedcolour; border-color: $linkvisitedcolour; }
49 a:active { color: $linkactivecolour; border-color: $linkactivecolour; }
50
51 h1 { @include header_size(60em, 2em); }
52 h2 { @include header_size(60em, 1.5em); }
53 h5 { @include header_size(60em, 1em); }
54
55 p.img {
56     text-align: center;
57
58     img {
59         vertical-align: bottom;
60         max-width: 40em;
61         width: 100%;
62         height: auto;
63     }
64
65     a {
66         text-decoration: none;
67         display: inline-block;
68         border: solid 2px;
69     }
70
71     small {
72         color: $foregroundcolour;
73         text-align: justify;
74         @media (max-width: 24em) { text-align: left; }
75         padding: 0.5ex;
76         display: block;
77         font-size: 0.9em;
78     }
79 }
80
81 p, dt, dd, li {
82     text-align: justify;
83     @media (max-width: 28em) { text-align: left; }
84     padding: 0;
85     margin: 0;
86 }
87
88 p, table, div, ul, ol, dl, hr {
89     max-width: 50em;
90     padding: 0;
91     margin: 0;
92 }
93
94 p, table, body>div, h5 { margin: 1em 0; }
95 blockquote {
96     @media (max-width: 28em) { margin: 1em 0.5em; }
97     margin: 1em;
98 }
99
100 li { margin: 0 0 0 2em; }
101 dd { margin: 0 0 0 1em; }
102
103 hr {
104     clear: both;
105     margin: 0.5em 0;
106     border: 0;
107     border-top: 1px solid $ruledefaultcolour;
108 }
109
110 kbd {
111     font-family: monospace;
112     font-size: 0.95em;
113     &:before { content: "% "; }
114     &>span { white-space: nowrap; }
115
116     blockquote & {
117         display: block;
118         text-align: left;
119         padding-left: 3em;
120         text-indent: -3em;
121     }
122 }
123
124 .permalink {
125     font-size: small;
126     color: $annotationcolour;
127
128     a:link, a:visited { color: inherit; }
129     @media not screen { visibility: hidden; }
130 }
131
132 // General table styles.
133 table {
134     border: 1px solid $ruledefaultcolour;
135     border-collapse: collapse;
136     width: 100%;
137 }
138
139 table>* { font-size: 0.9em; }
140 caption {
141     caption-side: top;
142     font-weight: bold;
143     font-size: 1em;
144     text-align: left;
145     margin: 0 0 0.5em 0;
146 }
147
148 td, th {
149     vertical-align: middle;
150     text-align: left;
151     padding: 1ex;
152     margin: 0;
153 }
154
155 thead>tr, tbody>tr { border: solid $ruledefaultcolour; }
156 th, thead>tr { border-bottom: 1px solid $rulestrongcolour; }
157 tbody+tbody { border-bottom: 1px solid $ruledefaultcolour; }
158 *>table, *>th { border: none; }
159 thead>tr { border-width: 1px; }
160 tbody>tr { border-width: 0 1px; }
161
162 td + td { box-shadow: -1px 0 $backgroundcolour; }
163
164 tbody>tr {
165     &:nth-of-type(even) { background-color: $tableshadecolour; }
166     &:last-child { border-bottom: solid 1px $ruledefaultcolour; }
167 }
168
169 // Specific table styles
170 table.cc {
171     &>tr>*:first-child, &>*>tr>*:first-child {
172         &+* { text-align: center; }
173         text-align: center;
174     }
175 }
176
177 // CSS rules for stortable clicky table headers: Update the display of
178 // the /table based on the current state.  Each column has its own set
179 // nearly-identical rules, only the class names differ.
180 //
181 // The clickytables.xsl stylesheet generates two inputs for each column.
182 // These inputs are siblings of the table and all precede it in document
183 // order.  Moreover, the inputs for a column are ordered with respect to
184 // each other, in this sequence:
185 //
186 //   input.clicky-NAME     -- checked iff NAME is selected for sorting.
187 //   input.clicky-NAME-rev -- checked to select reverse order.
188 //
189 // One of the column selection inputs will have a 'checked' attribute to
190 // indicate the default order.  This input is always first in document
191 // order.  No other inputs begin checked.
192 //
193 // The table itself consists of a thead (where the header labels are
194 // located) and two tbody elements.  The bulk of these rules relate
195 // to updating the headers to visually indicate the current state.
196 //
197 // A sortable column's th element has the .clicky-NAME class, matching
198 // its corresponding inputs, and has two label children.  The first label
199 // is visible only when the column is unselected, and is linked to the
200 // .clicky-NAME input to activate that column.  The second label is visible
201 // only on the selected column and is linked to the .clicky-NAME-rev input
202 // to toggle the reverse order.
203 //
204 // For the table body, the first tbody contains the default ordering
205 // and is not styled by these rules (except to hide it when alternate
206 // orderings are selected).  The second tbody contains rows for all
207 // alternate orderings, and is revealed by these rules.  When revealed,
208 // rows with the NAMEfwd or NAMErev class (for the forward and reverse
209 // orderings, respectively) are shown and other rows are hidden.
210
211 $clickynames: name, date, size;
212 @each $col in $clickynames {
213     input.clicky-#{$col} {
214         &:checked {
215             &~table {
216                 // Update table header state
217                 & th.clicky-#{$col} {
218                     label~label {
219                         display: -moz-inline-box !important;
220                         display: inline-block !important;
221                     }
222                     label { display: none; }
223                 }
224
225                 // Show only appropriate items from the sort body (forward)
226                 &>tbody+tbody>tr.#{$col}fwd { display: table-row; }
227                 &>tbody+tbody>tr { display: none; }
228
229                 // Unhide sort body
230                 &>tbody {
231                     &+tbody { display: table-row-group !important; }
232                     display: none;
233                 }
234             }
235
236             // reverse state for selected sort column
237             &~input.clicky-#{$col}-rev {
238                 &:checked ~ table {
239                     // Show only appropriate items from sort body (reversed)
240                     &>tbody+tbody>tr.#{$col}rev { display: table-row; }
241                     &>tbody+tbody>tr { display: none; }
242
243                     // Unhide sort body
244                     &>tbody {
245                         &+tbody { display: table-row-group !important; }
246                         display: none;
247                     }
248                 }
249
250                 // Unhide to allow keyboard navigation to this input
251                 display: block !important;
252             }
253         }
254
255         // If default input element is the only one selected, match it to
256         // return to default view (overriding the changes above).  It is
257         // always the first input element among all the sibling elements.
258         // This seems to interoperate better than using the [checked] or
259         // :first-of-type selectors.
260         @at-root &:first-child, :not(input)+& {
261             &:checked~table>tbody {
262                 &+tbody { display: none !important; }
263                 display: table-row-group;
264             }
265         }
266
267         &:focus ~ table th.clicky-#{$col}>label~label>span:first-child {
268             border-color: $foregroundcolour;
269         }
270
271         // Unhide to allow keyboard navigation
272         display: block !important;
273         pointer-events: none;
274         position: absolute;
275         opacity: 0;
276         z-index: -1;
277     }
278
279     input.clicky-#{$col}-rev {
280         &:checked ~ table {
281             // Update table header state
282             & th.clicky-#{$col} {
283                 .svg+.svg {
284                     display: -moz-inline-box !important;
285                     display: inline-block !important;
286                 }
287                 .svg { display: none; }
288             }
289         }
290
291         &:focus ~ table th.clicky-#{$col}>label~label .svg {
292             border-color: $foregroundcolour;
293         }
294
295         pointer-events: none;
296         position: absolute;
297         opacity: 0;
298         z-index: -2;
299     }
300 }
301
302 thead.clicky label {
303     white-space: nowrap;
304     line-height: 1.5em;
305     cursor: pointer;
306
307     &>* {
308         display: -moz-inline-box;
309         display: inline-block;
310         border: 1px dotted transparent;
311         vertical-align: middle;
312     }
313
314     // Expand the first label a bit so the table (hopefully)
315     // does not reshape as columns are selected.
316     &:first-child {
317         margin-right: 1.75em;
318         padding-right: 2px;
319     }
320
321     &:active { color: $linkactivecolour; }
322     &:first-child:active>span, &~label:active>.svg {
323         border-color: $linkactivecolour;
324     }
325
326     .svg {
327         margin-left: 0.25em;
328     }
329
330     .svg, svg, img.svgfallback {
331         height: 1.5em;
332         width: auto;
333     }
334     .svg svg { width: 1.5em; }
335 }
336
337 table.filelist {
338     &>*>tr>*:first-child {
339         &+* { width: 50%; }
340         // chrome doesn't like width: 0 for some reason
341         width: 0.1px;
342     }
343
344     tbody {
345         .svg, svg, img.svgfallback {
346             vertical-align: middle;
347             height: 1.5em;
348             width: auto;
349         }
350
351         .svg {
352             svg { width: 1.5em; }
353             display: inline-block;
354         }
355     }
356 }
357
358 // Site header rules
359 #breadcrumbs>*, #sitetitle>* { font-size: 0.8em; }
360 #breadcrumbs {
361     * {
362         display: inline;
363         list-style-type: none;
364         vertical-align: top;
365         padding: 0;
366         margin: 0;
367     }
368
369     li + li:before { content: "/ "; }
370 }
371 #sitetitle * {
372     display: inline-block;
373     float: right;
374 }
375
376 // Site footer rules
377 #footer, #article-info {
378     text-align: center;
379     max-width: 44em;
380     padding: 0 3em;
381     margin: 0;
382
383     p {
384         display: inline-block;
385         font-size: 0.8em;
386         max-width: 100%;
387         margin: 0.2em 0;
388     }
389 }
390
391 #footer p { color: $annotationcolour; }
392 #article-info p { font-style: italic; }
393
394 .wbr:after { content: "\200b"; }
395
396 // "unordered" lists with explicit ordering in content
397 ul.ordered > {
398     li { list-style: none; }
399     li>span:first-child, li>*:first-child>span:first-child {
400         display: inline-block;
401         text-align: right;
402         margin-left: -1.8em;
403         min-width: 1.8em;
404     }
405 }
406
407 @media (max-width: 512px) {
408     body { margin: 0.6em; }
409     ul ul { margin-left: -1.2em; }
410     dd { margin: 0; }
411 }
412
413 @media (max-width: 35em) {
414     #sitetitle * { float: none; }
415     #footer { padding: 0 1em; }
416 }