diff --git a/html/ui/app.css b/html/ui/app.css
new file mode 100644
index 0000000..f3a6bab
--- /dev/null
+++ b/html/ui/app.css
@@ -0,0 +1,42 @@
+
+.view-links > span {
+ display: inline-block;
+ white-space: nowrap;
+ margin-right: 1ex;
+ margin-bottom: 1ex;
+ padding: 0.5ex;
+ border: 1pt solid;
+ border-radius: 1ex;
+ cursor: pointer;
+}
+
+.downloads, .download-links {
+ & > * {
+ display: inline-block;
+ margin-right: 1ex;
+ margin-bottom: 1ex;
+ padding: 0.5ex;
+ border: 1px solid;
+ border-radius: 1ex;
+ cursor: pointer;
+ }
+}
+
+.downloads, .view-links {
+ & > .selected {
+ color: var(--link);
+ }
+}
+
+.text-and-file {
+ position:relative;
+
+ textarea {
+ width: 64em;
+ }
+
+ input[type="file"] {
+ position:absolute;
+ bottom:0;right:0;
+ }
+}
diff --git a/html/ui/index.html b/html/ui/index.html
index 774f6d4..9e68416 100644
--- a/html/ui/index.html
+++ b/html/ui/index.html
@@ -6,245 +6,9 @@
-
-
+
diff --git a/html/ui/style.css b/html/ui/style.css
new file mode 100644
index 0000000..9c02019
--- /dev/null
+++ b/html/ui/style.css
@@ -0,0 +1,195 @@
+:root {
+ --bg: #eee;
+ --color: black;
+ --bevel-dark: darkgray;
+ --bevel-light: lightgray;
+ --link: blue;
+ --input-bg: #ddd;
+ --input-text: white;
+ --btn-bg: #eee;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --bg: black;
+ --color: orange;
+ --bevel-dark: #402900;
+ --bevel-light: #805300;
+ --link: #31b0fa;
+ --input-bg: #111;
+ --input-text: #ddd;
+ --btn-bg: #222;
+ }
+}
+
+body {
+ background: var(--bg);
+ color: var(--color);
+}
+
+button[disabled] {
+ opacity: 0.5;
+}
+
+a[href], a[href]:visited, button.link {
+ border: none;
+ color: var(--link);
+ background: none;
+ cursor: pointer;
+ text-decoration: none;
+}
+
+table {
+ border-collapse: collapse;
+}
+th, td {
+ border-left: dotted 1pt;
+ border-right: dotted 1pt;
+ border-bottom: dotted 1pt;
+ padding: 2pt 4pt;
+}
+tr:first-child > th {
+ border-top: dotted 1pt;
+}
+th, tr:last-child > td {
+ border-bottom: solid 1pt;
+}
+
+.flat > * { margin-left: 1ex; }
+.flat > *:first-child { margin-left: 0; }
+
+.green { color: green; }
+.red { color: red; }
+
+@media (prefers-color-scheme: dark) {
+ .red { color: #c00; }
+}
+
+textarea, select, input {
+ background: var(--input-bg);
+ color: var(--input-text);
+ border: solid 1pt;
+ border-color: var(--bevel-light);
+ border-top-color: var(--bevel-dark);
+ border-left-color: var(--bevel-dark);
+ margin: 1pt;
+
+ &:focus {
+ outline: solid 1pt var(--color);
+ }
+ }
+
+button, input[type=button], input[type=submit], ::file-selector-button {
+ background: var(--btn-bg);
+ color: var(--color);
+ border: solid 2pt;
+ border-color: var(--bevel-dark);
+ border-top-color: var(--bevel-light);
+ border-left-color: var(--bevel-light);
+
+ &:hover {
+ background: var(--bevel-dark);
+ }
+ &:active {
+ background: var(--bevel-dark);
+ border-color: var(--bevel-light);
+ }
+}
+
+header {
+ display: flex;
+ align-items: center;
+ border-bottom: 2pt solid;
+ margin: 0 0 1em 0;
+ padding: 1ex;
+ justify-content: space-between;
+}
+#logo > img {
+ vertical-align: middle;
+}
+header .utils > * {
+ margin-left: 1ex;
+}
+
+.error {
+ display: flex;
+ position: relative;
+ background: rgba(255,0,0,0.2);
+ border: 1pt solid red;
+ justify-content: space-between;
+ align-items: center;
+}
+.error .btn-close,
+.error .code {
+ background: #600;
+ color: white;
+ font-weight: bold;
+ border: none;
+ align-self: stretch;
+ padding: 1ex 1em;
+}
+.error .code {
+ order: 1;
+
+ display: flex;
+ align-items: center;
+ text-align: center;
+}
+.error .message {
+ order: 2;
+ padding: 1ex 2em;
+}
+.error .btn-close {
+ order: 3;
+}
+
+.sheets {
+ display: flex;
+ align-items: stretch;
+}
+.sheets > div {
+ margin: 0 1ex;
+ border: 1pt solid;
+ border-radius: 6pt;
+}
+.sheets .title {
+ text-align: center;
+ font-weight: bold;
+ font-size: large;
+ padding: 2pt 6pt;
+ background: rgba(127,127,127,0.5);
+}
+.sheets .section {
+ padding: 2pt 6pt 2pt 6pt;
+ font-weight: bold;
+ border-top: 1px dotted;
+}
+.sheets section {
+ margin: 2pt 6pt 6pt 6pt;
+}
+.sheets > *:last-child > table:last-child > tr:last-child > td {
+ border-bottom: none;
+}
+
+.notif {
+ display: inline-block;
+ position: relative;
+}
+.notif > div:first-child {
+ position: absolute;
+ min-width: 100%; height: 100%;
+ background: white;
+ opacity: 75%;
+ text-align: center;
+}
+
+.links > * { margin-left: 1ex; }
+.links > *:first-child { margin-left: 0; }
+
+@media (prefers-color-scheme: dark) {
+ .notif > div:first-child {
+ background: black;
+ }
+}
+
+.copy { font-size: small; }
diff --git a/ui/index.html b/ui/index.html
index 7f2215a..0d699ce 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -6,8 +6,9 @@
-
-
+
+
+