summaryrefslogtreecommitdiff
path: root/frontend/style.css
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/style.css')
-rw-r--r--frontend/style.css353
1 files changed, 353 insertions, 0 deletions
diff --git a/frontend/style.css b/frontend/style.css
new file mode 100644
index 0000000..15c3add
--- /dev/null
+++ b/frontend/style.css
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2024 Runxi Yu <https://runxiyu.org>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ * TODO: Remove all uses of !important. These are obviously bad practice, but
+ * it's not always trivial to get the precedence right.
+ */
+
+:root {
+ --primary-bg: white;
+ --primary-fg: #212529;
+ --border: #ced4da;
+ --anchor-underline-color: lightgray;
+ --anchor-color: #0062cc;
+ --theme: #0062cc;
+ --theme-contrast: white;
+ --box: #f2f2f2;
+ --box-contrast: var(--primary-fg);
+ --danger: #d32535;
+ --danger-contrast: white;
+ --white: white;
+ --white-contrast: #222222;
+ --header-fg: black;
+ --header-bg: #f2f2f2;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --primary-bg: #212529;
+ --primary-fg: #f8f9fa;
+ --border: #495057;
+ --anchor-underline-color: #4F4F4F;
+ --anchor-color: #3294fe;
+ --theme: #0062cc;
+ --theme-contrast: #f8f9fa;
+ --box: #30363B;
+ --box-contrast: #f8f9fa;
+ --danger: #d32535;
+ --danger-contrast: #f8f9fa;
+ --white: #202020;
+ --white-contrast: #f8f9fa;
+ --header-fg: #f8f9fa;
+ --header-bg: #30363b;
+ }
+}
+
+html {
+ font-family: system-ui, sans-serif;
+ line-height: 1.2;
+ background-color: var(--primary-bg);
+ color: var(--primary-fg);
+}
+
+body {
+ margin: 0;
+ padding: 0;
+}
+
+main,
+body > section,
+.reading-width,
+footer {
+ margin: 1rem auto;
+ padding-left: 1rem;
+ padding-right: 1rem;
+ max-width: 60rem;
+}
+
+/*
+ * For accessibility reasons, we still want anchors to be underlined, but
+ * perhaps not as profound of an underline as the default.
+ */
+a {
+ color: var(--anchor-color);
+ text-decoration: underline;
+ text-decoration-color: var(--anchor-underline-color);
+}
+
+/*
+ * However, although the site title will be an anchor, it should not be
+ * underlined.
+ */
+#site-title {
+ text-decoration: none;
+}
+
+/*
+ * Navigation is a simple bulleted list with bullets in the middle only.
+ * This should probably be revamped.
+ */
+nav ul {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+}
+nav ul > li {
+ display: inline-block;
+}
+nav ul > li:not(:last-child)::after {
+ content:"\2000"
+}
+
+/*
+ * The header should stick to the top of the page.
+ */
+header {
+ position: -webkit-sticky;
+ position: sticky;
+ top: 0;
+ left: 0;
+ color: var(--header-fg);
+ background-color: var(--header-bg);
+ z-index: 1000;
+ width: 100%;
+}
+
+/*
+ * We don't want underlined anchors in the header in general, since it should
+ * be obvious that things in it are links.
+ */
+header a {
+ text-decoration: none;
+ color: var(--header-fg);
+}
+.header-content {
+ padding-left: 1rem;
+ padding-right: 1rem;
+ max-width: 60rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin: 0 auto;
+}
+header img {
+ vertical-align: middle;
+ max-height: 40px;
+}
+header h1 {
+ font-size: 25px; /* TODO: Specifying font sizes in pixels is bad */
+}
+
+/*
+ * The table, the most important element in my site design...
+ */
+table {
+ margin-top: 0.4em;
+ margin-bottom: 0.4em;
+ border-collapse: collapse;
+ border: 1px solid var(--border);
+}
+table.wide {
+ width: 100%;
+}
+th[scope~="row"] {
+ text-align: left;
+}
+th[scope~="col"] {
+}
+td {
+ border: 1px solid;
+ text-align: left;
+ height: 1.25rem;
+ border: 1px solid var(--border);
+ padding: 3px 5px;
+}
+table.fat td {
+ padding: 6px 5px;
+}
+td.th-like, th {
+ background-color: var(--box) !important;
+ border: 1px solid var(--border);
+ font-weight: bold;
+ padding: 3px 5px;
+}
+th.min, td.min {
+ width: 0;
+ min-width: fit-content;
+ white-space: nowrap;
+}
+
+/*
+ * Input elements, which are usually in tables anyway
+ */
+textarea {
+ box-sizing: border-box;
+ background-color: var(--box);
+ resize: vertical;
+}
+textarea,
+input[type=text],
+input[type=password] {
+ font-family: sans-serif;
+ font-size: smaller;
+ background-color: var(--box);
+ color: var(--box-contrast);
+ border: none;
+ padding: 0.3rem;
+ width: 100%;
+ box-sizing: border-box;
+}
+td.tdinput, th.tdinput {
+ padding: 0rem !important;
+}
+td.tdinput textarea,
+td.tdinput input[type=text],
+td.tdinput input[type=password],
+th.tdinput textarea,
+th.tdinput input[type=text],
+th.tdinput input[type=password] {
+ background-color: transparent !important;
+}
+
+/*
+ * Button definitions.
+ *
+ * Each button should contain the .btn class and a .btn-type class, where type
+ * is one of primary, danger, white, and normal.
+ */
+.btn-primary {
+ background: var(--theme);
+ color: var(--theme-contrast);
+ border: var(--border) 1px solid;
+ font-weight: bold;
+}
+.btn-danger {
+ background: var(--danger);
+ color: var(--danger-contrast);
+ border: var(--border) 1px solid;
+ font-weight: bold;
+}
+.btn-white {
+ background: var(--white);
+ color: var(--white-contrast);
+ border: var(--border) 1px solid;
+}
+.btn-normal,
+input[type=file]::file-selector-button {
+ background: var(--box-contrast);
+ border: var(--border) 1px solid !important;
+ color: var(--box-contrast);
+}
+.btn,
+input[type=submit],
+input[type=file]::file-selector-button {
+ display: inline-block;
+ width: auto;
+ min-width: fit-content;
+ border-radius: 0;
+ padding: .1rem .75rem;
+ font-size: 0.9rem;
+ transition: background .1s linear;
+ cursor: pointer;
+}
+a.btn {
+ text-decoration: none;
+}
+
+
+/*
+ * Multiple columns, flexible wrapping
+ */
+.multicols {
+ display: flex;
+ flex-direction: row;
+ @media(max-width: 50rem) {
+ flex-wrap: wrap;
+ gap: 0rem;
+ }
+ gap: 2rem;
+ align-items: stretch;
+}
+
+.multicols div {
+ min-width: 18em;
+ /* max-width: 40rem; */
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+/*
+ * Spanning elements across a flex container with equal space in between
+ */
+.flex-justify {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin: 0 auto;
+ border: none;
+}
+
+.message-box {
+ margin: auto;
+ max-width: 30rem;
+ border: solid 1px var(--border);
+ background-color: var(--box);
+ padding: 0rem 1rem;
+}
+
+table#table-of-courses {
+ width: 100%;
+}
+
+/*
+ * .need-connection is the content that should actually display when we are
+ * connected via WebSocket. The JavaScript would change display from none to
+ * block when fully connected to WebSocket.
+ */
+.need-connection {
+ display: none;
+}
+
+/*
+ * Same for script-required, though the JavaScript hides this as soon as it's
+ * loaded.
+ */
+.script-required {
+ display: none;
+}
+
+/*
+ * .broken-connection displays a message telling users to refresh the page,
+ * after their WebSocket connection breaks. It should be hidden by default.
+ */
+.broken-connection {
+ display: none;
+}
+
+/*
+ * This site heavily uses CSS styling to display and hide messages, so by
+ * default we put a big warning about CSS being broken, which disappears
+ * once the main CSS, i.e. this file, is completely loaded. Therefore it's
+ * probably best to put this at the bottom of this file.
+ */
+.broken-styling-warning {
+ display: none;
+}