adds slightly less-ugly global stylesheet; improves mobile compat
This commit is contained in:
parent
1b68ad7c6f
commit
3012aa651e
|
@ -0,0 +1,349 @@
|
|||
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the `main` element consistently in IE.
|
||||
*/
|
||||
|
||||
main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background on active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57-
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers.
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
[type="button"],
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE 10+.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10.
|
||||
* 2. Remove the padding in IE 10.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||
*/
|
||||
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Misc
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10+.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
/* modified https://github.com/oxalorg/sakura */
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
body {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: #c9c9c9;
|
||||
background-color: #222222;
|
||||
padding: 13px;
|
||||
}
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: 1.53rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
small,
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
hr {
|
||||
border-color: #ffffff;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
a:visited {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
a:hover {
|
||||
color: #c9c9c9;
|
||||
text-decoration: underline;
|
||||
}
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
blockquote {
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid #ffffff;
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: #4a4a4a;
|
||||
}
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
img,
|
||||
video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
pre {
|
||||
background-color: #4a4a4a;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: #4a4a4a;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
td,
|
||||
th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid #4a4a4a;
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid #c9c9c9;
|
||||
}
|
||||
input:focus,
|
||||
textarea:focus {
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"],
|
||||
input[type="file"]::file-selector-button {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: #ffffff;
|
||||
color: #222222;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #ffffff;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.button[disabled],
|
||||
button[disabled],
|
||||
input[type="submit"][disabled],
|
||||
input[type="reset"][disabled],
|
||||
input[type="button"][disabled],
|
||||
input[type="file"][disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover,
|
||||
input[type="file"]::file-selector-button:hover {
|
||||
background-color: #c9c9c9;
|
||||
color: #222222;
|
||||
outline: 0;
|
||||
}
|
||||
.button:focus-visible,
|
||||
button:focus-visible,
|
||||
input[type="submit"]:focus-visible,
|
||||
input[type="reset"]:focus-visible,
|
||||
input[type="button"]:focus-visible,
|
||||
input[type="file"]::file-selector-button:focus-visible {
|
||||
outline-style: solid;
|
||||
outline-width: 2px;
|
||||
}
|
||||
textarea,
|
||||
select,
|
||||
input {
|
||||
color: #c9c9c9;
|
||||
padding: 6px 10px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #4a4a4a;
|
||||
border: 1px solid #4a4a4a;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea:focus,
|
||||
select:focus,
|
||||
input:focus {
|
||||
border: 1px solid #ffffff;
|
||||
outline: 0;
|
||||
}
|
||||
input[type="checkbox"]:focus {
|
||||
outline: 1px dotted #ffffff;
|
||||
}
|
||||
label,
|
||||
legend,
|
||||
fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
/* modified https://github.com/oxalorg/sakura */
|
||||
:root {
|
||||
--accent-color: #4a4a4a;
|
||||
--accent-color-hover: #5a5a5a;
|
||||
--link-color: #58739c;
|
||||
--link-visted-color: #6f5e6f;
|
||||
}
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
}
|
||||
body {
|
||||
font-size: 1.8rem;
|
||||
line-height: 1.618;
|
||||
max-width: 38em;
|
||||
margin: auto;
|
||||
color: #4a4a4a;
|
||||
background-color: #f9f9f9;
|
||||
padding: 13px;
|
||||
}
|
||||
@media (max-width: 684px) {
|
||||
body {
|
||||
font-size: 1.53rem;
|
||||
}
|
||||
}
|
||||
@media (max-width: 382px) {
|
||||
body {
|
||||
font-size: 1.35rem;
|
||||
}
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
"Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.35em;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
h5 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
}
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
small,
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
}
|
||||
hr {
|
||||
border-color: var(--accent-color);
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--link-color);
|
||||
}
|
||||
a:visited {
|
||||
color: var(--link-visted-color);
|
||||
}
|
||||
a:hover {
|
||||
color: var(--accent-color-hover);
|
||||
text-decoration: underline;
|
||||
}
|
||||
ul {
|
||||
padding-left: 1.4em;
|
||||
margin-top: 0;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
blockquote {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
padding-left: 1em;
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.8em;
|
||||
padding-right: 0.8em;
|
||||
border-left: 5px solid var(--accent-color);
|
||||
margin-bottom: 2.5rem;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
blockquote p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
img,
|
||||
video {
|
||||
height: auto;
|
||||
max-width: 100%;
|
||||
margin-top: 0;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
pre {
|
||||
background-color: #f1f1f1;
|
||||
display: block;
|
||||
padding: 1em;
|
||||
overflow-x: auto;
|
||||
margin-top: 0;
|
||||
margin-bottom: 2.5rem;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.5em;
|
||||
background-color: #f1f1f1;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
pre > code {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
white-space: pre;
|
||||
font-size: 1em;
|
||||
}
|
||||
table {
|
||||
text-align: justify;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
td,
|
||||
th {
|
||||
padding: 0.5em;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
}
|
||||
input,
|
||||
textarea {
|
||||
border: 1px solid #4a4a4a;
|
||||
}
|
||||
input:focus,
|
||||
textarea:focus {
|
||||
border: 1px solid var(--accent-color);
|
||||
}
|
||||
textarea {
|
||||
width: 100%;
|
||||
}
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"],
|
||||
input[type="file"]::file-selector-button {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: var(--accent-color);
|
||||
color: #f9f9f9;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--accent-color);
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.button[disabled],
|
||||
button[disabled],
|
||||
input[type="submit"][disabled],
|
||||
input[type="reset"][disabled],
|
||||
input[type="button"][disabled],
|
||||
input[type="file"][disabled] {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover,
|
||||
input[type="file"]::file-selector-button:hover {
|
||||
background-color: var(--accent-color-hover);
|
||||
color: #f9f9f9;
|
||||
outline: 0;
|
||||
}
|
||||
.button:focus-visible,
|
||||
button:focus-visible,
|
||||
input[type="submit"]:focus-visible,
|
||||
input[type="reset"]:focus-visible,
|
||||
input[type="button"]:focus-visible,
|
||||
input[type="file"]::file-selector-button:focus-visible {
|
||||
outline-style: solid;
|
||||
outline-width: 2px;
|
||||
}
|
||||
textarea,
|
||||
select,
|
||||
input {
|
||||
color: #4a4a4a;
|
||||
padding: 6px 10px;
|
||||
margin-bottom: 10px;
|
||||
background-color: #f1f1f1;
|
||||
border: 1px solid #f1f1f1;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
textarea:focus,
|
||||
select:focus,
|
||||
input:focus {
|
||||
border: 1px solid var(--accent-color);
|
||||
outline: 0;
|
||||
}
|
||||
input[type="checkbox"]:focus {
|
||||
outline: 1px dotted var(--accent-color);
|
||||
}
|
||||
label,
|
||||
legend,
|
||||
fieldset {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
|
@ -5,18 +5,6 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
#statsForm div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
#statsForm div label {
|
||||
width: 6em;
|
||||
text-align: right;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
#statsForm ul {
|
||||
margin: 0;
|
||||
padding-left: 2em;
|
||||
|
@ -33,17 +21,17 @@
|
|||
}
|
||||
</style>
|
||||
<h1>Download Stats</h1>
|
||||
<p>
|
||||
Download usage statistics to a Markdown document. You can paste this into a service like Rentry.org to share it.
|
||||
</p>
|
||||
<p>Download usage statistics to a Markdown document. You can paste this into a service like Rentry.org to share it.</p>
|
||||
<div>
|
||||
<h3>Options</h3>
|
||||
<form id="statsForm" action="/admin/manage/generate-stats" method="post"
|
||||
style="display: flex; flex-direction: column;">
|
||||
<form
|
||||
id="statsForm"
|
||||
action="/admin/manage/generate-stats"
|
||||
method="post"
|
||||
style="display: flex; flex-direction: column">
|
||||
<input id="_csrf" type="hidden" name="_csrf" value="<%= csrfToken %>" />
|
||||
<div>
|
||||
<label for="anon">Anonymize</label>
|
||||
<input id="anon" type="checkbox" name="anon" value="true" />
|
||||
<label for="anon"><input id="anon" type="checkbox" name="anon" value="true" /> <span>Anonymize</span></label>
|
||||
</div>
|
||||
<div>
|
||||
<label for="sort">Sort</label>
|
||||
|
@ -64,11 +52,12 @@
|
|||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="format">Custom Format <ul>
|
||||
<li><code>{{header}}</code></li>
|
||||
<li><code>{{stats}}</code></li>
|
||||
<li><code>{{time}}</code></li>
|
||||
</ul></label>
|
||||
<label for="format">Custom Format</label>
|
||||
<ul>
|
||||
<li><code>{{header}}</code></li>
|
||||
<li><code>{{stats}}</code></li>
|
||||
<li><code>{{time}}</code></li>
|
||||
</ul>
|
||||
<textarea id="format" name="format" rows="10" cols="50" placeholder="{{stats}}">
|
||||
# Stats
|
||||
{{header}}
|
||||
|
@ -115,33 +104,35 @@
|
|||
loadDefaults();
|
||||
|
||||
async function fetchAndCopy() {
|
||||
const form = document.getElementById('statsForm');
|
||||
const form = document.getElementById("statsForm");
|
||||
const formData = new FormData(form);
|
||||
|
||||
const response = await fetch(form.action, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
credentials: 'same-origin',
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
credentials: "same-origin",
|
||||
body: new URLSearchParams(formData),
|
||||
});
|
||||
|
||||
|
||||
if (response.ok) {
|
||||
const content = await response.text();
|
||||
copyToClipboard(content);
|
||||
} else {
|
||||
throw new Error('Failed to fetch generated stats. Try reloading the page.');
|
||||
throw new Error("Failed to fetch generated stats. Try reloading the page.");
|
||||
}
|
||||
}
|
||||
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
alert('Copied to clipboard');
|
||||
}).catch(err => {
|
||||
alert('Failed to copy to clipboard. Try downloading the file instead.');
|
||||
});
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
alert("Copied to clipboard");
|
||||
})
|
||||
.catch((err) => {
|
||||
alert("Failed to copy to clipboard. Try downloading the file instead.");
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('copyButton').addEventListener('click', fetchAndCopy);
|
||||
document.getElementById("copyButton").addEventListener("click", fetchAndCopy);
|
||||
</script>
|
||||
<%- include("partials/admin-footer") %>
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
<% if (users.length === 0) { %>
|
||||
<p>No users found.</p>
|
||||
<% } else { %>
|
||||
<input type="checkbox" id="toggle-nicknames" onchange="toggleNicknames()" />
|
||||
<label for="toggle-nicknames">Show Nicknames</label>
|
||||
<table class="striped" style="width: calc(100vw - 3em)">
|
||||
<label for="toggle-nicknames"><input type="checkbox" id="toggle-nicknames" onchange="toggleNicknames()" /> Show Nicknames</label>
|
||||
<table class="striped full-width">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>User</th>
|
||||
|
|
|
@ -63,27 +63,33 @@ export function renderPage(info: ServiceInfo) {
|
|||
const title = getServerTitle();
|
||||
const headerHtml = buildInfoPageHeader(info);
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
return `<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="robots" content="noindex" />
|
||||
<title>${title}</title>
|
||||
<link rel="stylesheet" href="/res/css/reset.css" media="screen" />
|
||||
<link rel="stylesheet" href="/res/css/sakura.css" media="screen" />
|
||||
<link rel="stylesheet" href="/res/css/sakura-dark.css" media="screen and (prefers-color-scheme: dark)" />
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
padding: 1em;
|
||||
max-width: 900px;
|
||||
margin: 0;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #222;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
a:link, a:visited {
|
||||
color: #bbe;
|
||||
}
|
||||
|
||||
.self-service-links {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 1em;
|
||||
padding: 0.5em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.self-service-links a {
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -152,9 +158,9 @@ function getSelfServiceLinks() {
|
|||
links.unshift(["Request a user token", "/user/captcha"]);
|
||||
}
|
||||
|
||||
return `<div style="font-size: 0.8em;">${links
|
||||
return `<div class="self-service-links"">${links
|
||||
.map(([text, link]) => `<a target="_blank" href="${link}">${text}</a>`)
|
||||
.join(" / ")}</div><hr />`;
|
||||
.join(" | ")}</div>`;
|
||||
}
|
||||
|
||||
function getServerTitle() {
|
||||
|
|
|
@ -70,7 +70,7 @@ app.set("views", [
|
|||
app.use("/user_content", express.static(USER_ASSETS_DIR, { maxAge: "2h" }));
|
||||
app.use(
|
||||
"/res",
|
||||
express.static(path.join(__dirname, "..", "public"), { etag: true })
|
||||
express.static(path.join(__dirname, "..", "public"), { maxAge: "2h", etag: false })
|
||||
);
|
||||
|
||||
app.get("/health", (_req, res) => res.sendStatus(200));
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="csrf-token" content="<%= csrfToken %>" />
|
||||
<title><%= title %></title>
|
||||
<link rel="stylesheet" href="/res/css/reset.css" media="screen" />
|
||||
<link rel="stylesheet" href="/res/css/sakura.css" media="screen" />
|
||||
<link rel="stylesheet" href="/res/css/sakura-dark.css" media="screen and (prefers-color-scheme: dark)" />
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background-color: #f0f0f0;
|
||||
padding: 1em;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #e0e6f6;
|
||||
details summary {
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a:visited:hover {
|
||||
background-color: #e7e0f6;
|
||||
details > *:not(summary) {
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
|
@ -30,6 +33,7 @@
|
|||
.pagination li a {
|
||||
display: block;
|
||||
padding: 0.5em 1em;
|
||||
border-bottom: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
.pagination li.active a {
|
||||
|
@ -37,18 +41,18 @@
|
|||
color: #fff;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
table.striped tr:nth-child(even) {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
table td,
|
||||
table th {
|
||||
border: 1px solid #ccc;
|
||||
padding: 0.25em 0.5em;
|
||||
table.full-width {
|
||||
width: calc(100vw - 4em);
|
||||
position: relative;
|
||||
left: 50%;
|
||||
right: 50%;
|
||||
margin-left: calc(-50vw + 2em);
|
||||
margin-right: calc(-50vw + 2em);
|
||||
}
|
||||
|
||||
th.active {
|
||||
background-color: #e0e6f6;
|
||||
}
|
||||
|
@ -73,32 +77,17 @@
|
|||
padding: 0.5em;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
table td,
|
||||
table th {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
table.full-width {
|
||||
width: 100%;
|
||||
position: static;
|
||||
left: auto;
|
||||
right: auto;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #222;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
a:link,
|
||||
a:visited {
|
||||
color: #bbe;
|
||||
}
|
||||
|
||||
a:link:hover,
|
||||
a:visited:hover {
|
||||
background-color: #446;
|
||||
}
|
||||
|
||||
table.striped tr:nth-child(even) {
|
||||
background-color: #333;
|
||||
}
|
||||
|
@ -111,3 +100,5 @@
|
|||
</head>
|
||||
<body>
|
||||
<%- include("partials/shared_flash", { flashData: flash }) %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
<script>
|
||||
function getPageSize() {
|
||||
var match = window.location.search.match(/perPage=(\d+)/);
|
||||
const match = window.location.search.match(/perPage=(\d+)/);
|
||||
if (match) return parseInt(match[1]); else return document.cookie.match(/perPage=(\d+)/)?.[1] ?? 10;
|
||||
}
|
||||
function setPageSize(size) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<a href="#" id="ip-list-toggle">Show all (<%- user.ip.length %>)</a>
|
||||
<ol id="ip-list" style="display: none; padding-left: 1em; margin: 0">
|
||||
<ol id="ip-list" style="display: none">
|
||||
<% user.ip.forEach((ip) => { %>
|
||||
<li><code><%- shouldRedact ? redactIp(ip) : ip %></code></li>
|
||||
<% }) %>
|
||||
|
|
|
@ -10,15 +10,11 @@
|
|||
}
|
||||
@media (max-width: 1000px) {
|
||||
#captcha-container {
|
||||
margin: 20px;
|
||||
max-width: unset;
|
||||
margin: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
#captcha-container p {
|
||||
padding: 2px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
#captcha-container details {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
@ -44,6 +40,13 @@
|
|||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
#captcha-progress-text {
|
||||
width: 100%;
|
||||
height: 18rem;
|
||||
resize: vertical;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
#captcha-progress-container {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
@ -66,32 +69,39 @@
|
|||
width: 0;
|
||||
height: 100%;
|
||||
background-color: #76c7c0;
|
||||
transition: width 0.2s;
|
||||
}
|
||||
</style>
|
||||
<div style="display: none" id="captcha-container">
|
||||
<p>
|
||||
Your device needs to perform a verification task before you can receive access. This might take anywhere from a few
|
||||
Your device needs to perform a verification task before you can receive a token. This might take anywhere from a few
|
||||
seconds to a few minutes, depending on your device and the proxy's security settings.
|
||||
</p>
|
||||
<p>Click the button below to start.</p>
|
||||
<details>
|
||||
<summary>What is this?</summary>
|
||||
<p>
|
||||
This is an anti-abuse measure designed to slow down automated requests. It requires your device's CPU to find a
|
||||
solution to a cryptographic puzzle, after which a user token will be issued.
|
||||
This is a <a href="https://en.wikipedia.org/wiki/Proof_of_work" target="_blank">proof-of-work</a> verification
|
||||
task designed to slow down automated abuse. It requires your device's CPU to find a solution to a cryptographic
|
||||
puzzle, after which a user token will be issued.
|
||||
</p>
|
||||
</details>
|
||||
<details>
|
||||
<summary>How long does verification take?</summary>
|
||||
<p>
|
||||
It on the device you're using and the verification task's difficulty level (currently
|
||||
<strong><%= difficultyLevel %></strong>). It could take anywhere from a few seconds to a few minutes.
|
||||
It depends on the device you're using and the current difficulty level (<code><%= difficultyLevel %></code>). The
|
||||
faster your device, the quicker it will solve the task.
|
||||
</p>
|
||||
<p>
|
||||
An estimate will be displayed once verification starts. Because the task is probabilistic, your device could solve
|
||||
it more quickly or take longer than the estimate.
|
||||
</p>
|
||||
</details>
|
||||
<details>
|
||||
<summary>How often do I need to do this?</summary>
|
||||
<p>Once you've earned a user token, you can use it for <%= tokenLifetime %> hours before it expires.</p>
|
||||
<p>
|
||||
Once you've earned a user token, you can use it for <strong><%= `${tokenLifetime} hours` %></strong> before it
|
||||
expires.
|
||||
</p>
|
||||
<p>
|
||||
You can refresh an expired token by returning to this page and verifying again. Subsequent verifications will go
|
||||
faster than the first one.
|
||||
|
@ -100,26 +110,28 @@
|
|||
<details>
|
||||
<summary>What is the "Workers" setting?</summary>
|
||||
<p>
|
||||
This controls how many CPU cores will be used to solve the verification task. By default, all of your device's
|
||||
cores will be used to solve the task as quickly as possible.
|
||||
This controls how many CPU cores will be used to solve the verification task. If your device gets too hot or slows
|
||||
down too much during verification, reduce the number of workers.
|
||||
</p>
|
||||
<p>
|
||||
If your device gets too hot or you want to use it for other tasks while verification is in progress, reduce the
|
||||
number of workers to lower the CPU load at the cost of slower verification.
|
||||
For fastest verification, set this to the number of physical CPU cores in your device. Setting more workers than
|
||||
you have actual cores will generally only slow down verification.
|
||||
</p>
|
||||
<p>If you don't understand what this means, leave it at the default setting.</p>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Other important information</summary>
|
||||
<ul>
|
||||
<li>Verification must be submitted from the same device and IP address that started the verification.</li>
|
||||
<li>Don't close this tab until verification is complete or you will need to start over.</li>
|
||||
<li>You can pause the task, but verification must be finished <strong>within 30 minutes</strong> of issuance.</li>
|
||||
<li>Don't change your IP address during verification.</li>
|
||||
<li>Don't close this tab until verification is complete.</li>
|
||||
<li>
|
||||
Up to <strong><%= tokenMaxIps || "unlimited" %></strong> IP addresses can be associated with a user token at
|
||||
once.
|
||||
Verification must be finished within <strong><%= `${challengeTimeout} minutes` %></strong>.
|
||||
</li>
|
||||
<li>Your user token will be registered to your current IP address.</li>
|
||||
<li>
|
||||
Up to <strong><%= tokenMaxIps || "unlimited" %></strong> IP addresses total can be registered to your user
|
||||
token.
|
||||
</li>
|
||||
<li>JavaScript is required to complete verification.</li>
|
||||
<li>If the proxy is restarted, any verification tasks currently in progress will be invalidated.</li>
|
||||
</ul>
|
||||
</details>
|
||||
<form id="captcha-form" style="display: none">
|
||||
|
@ -129,7 +141,7 @@
|
|||
<div id="captcha-control">
|
||||
<div>
|
||||
<label for="workers">Workers:</label>
|
||||
<input type="number" id="workers" value="1" min="1" max="16" onchange="spawnWorkers()" />
|
||||
<input type="number" id="workers" value="1" min="1" max="32" onchange="spawnWorkers()" />
|
||||
</div>
|
||||
<button id="worker-control" onclick="toggleWorker()">Start verification</button>
|
||||
</div>
|
||||
|
@ -138,7 +150,7 @@
|
|||
<div id="captcha-progress" class="progress-bar">
|
||||
<div class="progress"></div>
|
||||
</div>
|
||||
<textarea disabled id="captcha-progress-text" style="width: 100%; height: 100px; resize: none"></textarea>
|
||||
<textarea disabled id="captcha-progress-text"></textarea>
|
||||
</div>
|
||||
<div id="captcha-result"></div>
|
||||
</div>
|
||||
|
@ -245,7 +257,7 @@
|
|||
workers = [];
|
||||
|
||||
const selectedWorkers = document.getElementById("workers").value;
|
||||
const workerCount = Math.min(16, Math.max(1, parseInt(selectedWorkers)));
|
||||
const workerCount = Math.min(32, Math.max(1, parseInt(selectedWorkers)));
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
const worker = new Worker("/res/js/hash-worker.js");
|
||||
worker.onmessage = handleWorkerMessage;
|
||||
|
|
Loading…
Reference in New Issue