Files
uncensored-send/web/static/style.css
T
2026-09-13 12:12:45 +02:00

315 lines
8.7 KiB
CSS

/* Hand-written, no build step, no framework. */
:root {
--bg: #f6f6f4;
--fg: #1b1b18;
--muted: #6b6b63;
--card: #ffffff;
--line: #dcdcd5;
--accent: #2f6f4f;
--accent-fg: #ffffff;
/* Red reads as text and as a button surface, and one value cannot do both:
see the pair below, kept in step per theme. */
--danger: #9b2c2c;
--danger-bg: #991b1b;
--danger-fg: #ffffff;
--warn-bg: #fdf6e3;
--radius: 10px;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #16161a;
--fg: #e8e8e3;
--muted: #9a9a92;
--card: #1f1f25;
--line: #33333c;
--accent: #5fae86;
--accent-fg: #10241a;
--danger: #e07070;
--danger-bg: #d32f2f;
--danger-fg: #ffffff;
--warn-bg: #2a2418;
}
}
* { box-sizing: border-box; }
body {
margin: 0;
padding: 0 1rem 3rem;
background: var(--bg);
color: var(--fg);
font: 16px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
}
header, main, footer { max-width: 42rem; margin: 0 auto; }
header { padding: 1.5rem 0; }
footer { padding-top: 2rem; color: var(--muted); font-size: .875rem; }
.brand {
font-weight: 600;
font-size: 1.125rem;
color: var(--fg);
text-decoration: none;
}
h1 { font-size: 1.375rem; margin: 0 0 .75rem; }
h2 { font-size: 1rem; margin: 0 0 .5rem; }
a { color: var(--accent); }
.card, .limits, .cli {
background: var(--card);
border: 1px solid var(--line);
border-radius: var(--radius);
padding: 1.25rem;
margin-bottom: 1.25rem;
}
.field { display: block; margin-bottom: 1rem; }
.field > span { display: block; font-size: .8125rem; color: var(--muted); margin-bottom: .25rem; }
.field em { font-style: normal; opacity: .7; }
input[type=text], input[type=password] {
width: 100%;
padding: .5rem .625rem;
font: inherit;
color: var(--fg);
background: var(--bg);
border: 1px solid var(--line);
border-radius: 6px;
}
.row { display: flex; gap: 1rem; flex-wrap: wrap; }
.row > .field { flex: 1 1 12rem; }
/* The file input must be the last part in the submitted body, so it sits last
in the markup and is lifted back to the top here. Only the painting order
moves; the server depends on the markup's. */
#upload { display: flex; flex-direction: column; }
#upload > .drop { order: -1; }
#upload > button { align-self: flex-start; }
/* An author `display` beats the browser's own [hidden] rule, so anything given
a display here has to say what hidden means for it. */
#upload[hidden] { display: none; }
.drop {
border: 2px dashed var(--line);
border-radius: var(--radius);
padding: 1.5rem;
text-align: center;
margin-bottom: 1rem;
transition: border-color .15s, background .15s;
}
.drop.over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.drop input[type=file] { max-width: 100%; }
button, .button {
display: inline-block;
padding: .5rem 1rem;
font: inherit;
font-weight: 500;
color: var(--accent-fg);
background: var(--accent);
border: 0;
border-radius: 6px;
cursor: pointer;
text-decoration: none;
}
button:disabled { opacity: .55; cursor: default; }
button.danger { background: var(--danger-bg); color: var(--danger-fg); }
.progress .bar {
height: .5rem;
background: var(--line);
border-radius: 999px;
overflow: hidden;
margin-bottom: .375rem;
}
.progress .fill { height: 100%; width: 0; background: var(--accent); transition: width .1s linear; }
.hint { color: var(--muted); font-size: .875rem; margin: .25rem 0 0; }
#error:not([hidden]) { color: var(--danger); }
dl { display: grid; grid-template-columns: auto 1fr; gap: .25rem 1rem; margin: 0; }
dt { color: var(--muted); font-size: .875rem; }
dd { margin: 0; }
.mono, pre, code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .8125rem; }
.wrap { overflow-wrap: anywhere; }
.filename { overflow-wrap: anywhere; }
pre {
margin: 0;
padding: .75rem;
background: var(--bg);
border: 1px solid var(--line);
border-radius: 6px;
overflow-x: auto;
}
.warn {
margin: 1.25rem 0;
padding: 1rem;
background: var(--warn-bg);
border: 1px solid var(--line);
border-radius: var(--radius);
}
.warn p { margin: .25rem 0 .75rem; font-size: .875rem; }
.result .field { margin-top: 1rem; }
.check { display: flex; align-items: center; gap: .5rem; margin-bottom: 1rem; font-size: .875rem; }
.check input { margin: 0; }
.notice {
margin: 0 0 1rem;
padding: .625rem .875rem;
background: var(--card);
border: 1px solid var(--line);
border-left: 3px solid var(--accent);
border-radius: 6px;
font-size: .875rem;
}
.notice .forget-form, .notice form { display: inline; }
button.link {
padding: 0;
background: none;
border: 0;
color: var(--accent);
font: inherit;
text-decoration: underline;
cursor: pointer;
}
.result .links { margin: 1.25rem 0 0; }
.result .links .field { margin-bottom: 1rem; }
.copyrow { display: flex; gap: .5rem; align-items: stretch; }
.copyrow input { flex: 1 1 auto; min-width: 0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .8125rem; }
.copyrow .copy { flex: 0 0 auto; }
.result dl { margin-top: 1.75rem; padding-top: 1.25rem; border-top: 1px solid var(--line); }
.result dl dd { margin-bottom: .25rem; }
.result .actions { margin: 1.5rem 0 0; }
@media (max-width: 26rem) {
.copyrow { flex-wrap: wrap; }
.copyrow input { flex-basis: 100%; }
}
header { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
header nav {
margin-left: auto;
display: flex;
align-items: baseline;
gap: .875rem;
font-size: .875rem;
}
header nav form { display: inline; }
header nav .who { color: var(--muted); }
header nav .who::before { content: "\1F511\00a0"; }
/* A listing needs far more room than the reading measure a form wants. */
body.wide header,
body.wide main,
body.wide footer { max-width: 72rem; }
dl.stats { grid-template-columns: auto 1fr; }
dl.stats em { font-style: normal; color: var(--muted); }
table.admin { border-collapse: collapse; width: 100%; font-size: .8125rem; }
table.admin th,
table.admin td {
padding: .45rem .5rem;
text-align: left;
vertical-align: top;
border-bottom: 1px solid var(--line);
}
table.admin th { color: var(--muted); font-weight: 500; white-space: nowrap; }
table.admin th a { color: inherit; text-decoration: none; }
table.admin th a:hover { color: var(--accent); text-decoration: underline; }
table.admin tr:last-child td { border-bottom: 0; }
table.admin .num { text-align: right; }
table.admin .nowrap { white-space: nowrap; }
table.admin form { margin: 0; }
table.admin .actions-cell { text-align: right; width: 1%; }
table.admin .filecell a { overflow-wrap: anywhere; font-weight: 500; }
table.admin .filecell .id {
display: block;
font-size: .6875rem;
color: var(--muted);
overflow-wrap: anywhere;
}
button.small { padding: .2rem .5rem; font-size: .75rem; }
.visually-hidden {
position: absolute;
width: 1px; height: 1px;
margin: -1px; padding: 0; border: 0;
clip-path: inset(50%);
overflow: hidden;
}
/* One card per row beats a horizontal scrollbar, which is unusable for picking
a row and pressing a button in it. */
@media (max-width: 46rem) {
table.admin,
table.admin tbody,
table.admin tr,
table.admin td { display: block; width: 100%; }
table.admin thead { display: none; }
table.admin tr {
padding: .625rem 0;
border-bottom: 1px solid var(--line);
}
table.admin td { border: 0; padding: .1rem 0; }
table.admin td[data-label]::before {
content: attr(data-label) ": ";
color: var(--muted);
}
table.admin .num,
table.admin .actions-cell { text-align: left; width: auto; }
table.admin .actions-cell { padding-top: .5rem; }
table.admin .filecell::before { content: none; }
}
.cli code, .hint code { background: var(--bg); padding: .1rem .3rem; border-radius: 4px; }
/* Disclosure panels. Open, a panel needs an edge, or there is no telling where
its contents end. */
details.panel {
border: 1px solid var(--line);
border-radius: var(--radius);
margin-bottom: 1rem;
}
details.panel > summary {
padding: .625rem .75rem;
font-weight: 400;
font-size: .875rem;
color: var(--muted);
cursor: pointer;
}
details.panel[open] > summary {
border-bottom: 1px solid var(--line);
margin-bottom: .75rem;
}
details.panel > :not(summary) { padding-left: .75rem; padding-right: .75rem; }
details.panel[open] { padding-bottom: .75rem; }
details.panel > :last-child { margin-bottom: 0; }
details.panel .field { max-width: 24rem; }
/* A hint before a control explains what follows, so it must not sit against
it. */
.hint + form, .hint + .field { margin-top: .75rem; }
.limits .hint { margin-top: .75rem; }
.limits dl, .card dl { row-gap: .375rem; }
.actions { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.actions form { margin: 0; }