mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-03 10:28:37 +00:00
335 lines
7.2 KiB
CSS
335 lines
7.2 KiB
CSS
/* Design system for the supporter-badge checkout site.
|
|
|
|
Served from web/ rather than from dist/, so that an edit is picked up
|
|
without a rebuild when the service runs with [web] web_dir set.
|
|
|
|
Two rules bind every edit to this file:
|
|
|
|
1. No double-at token belongs here — the syntax index.html names its assets
|
|
with. Only index.html is substituted, so such a token in a CSS rule would
|
|
reach the browser as literal text. The two logos are <img> elements in
|
|
index.html; this file only chooses which of them is shown.
|
|
2. No cross-origin URL belongs here either. The service sends
|
|
Content-Security-Policy: default-src 'self' (D4), so a webfont or a
|
|
remote image would be blocked at runtime with nothing to see. The font
|
|
stack below is the system one for that reason.
|
|
|
|
Every colour is defined on bare :root. The dark block only *redefines*
|
|
tokens that already exist: a colour introduced there alone would be
|
|
undefined in light mode, which is where most of this site is read, and the
|
|
browser would fall back to nothing rather than to an error. */
|
|
|
|
:root {
|
|
color-scheme: light dark;
|
|
|
|
/* Accent: primary-light and primary-dark from website/tailwind.config.js. */
|
|
--accent: #0053D0;
|
|
--accent-hover: #1661D1;
|
|
--on-accent: #FFFFFF;
|
|
|
|
--bg: #FFFFFF;
|
|
--card-bg: #FFFFFF;
|
|
--text: #0D0E12;
|
|
--text-secondary: #3F484B;
|
|
--border: #DFE4EA;
|
|
--focus-ring: #0053D0;
|
|
|
|
--error-bg: #FDECEC;
|
|
--error-text: #8C1C13;
|
|
--error-border: #E0A5A0;
|
|
|
|
--gutter: 20px;
|
|
--radius: 16px;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--accent: #70F0F9;
|
|
--accent-hover: #66D9E2;
|
|
--on-accent: #000832;
|
|
|
|
--bg: #000832;
|
|
/* The app's PeriodCard tints its card in dark mode and leaves it flush
|
|
with the page in light mode; these two match that. */
|
|
--card-bg: #071C46;
|
|
--text: #FFFFFF;
|
|
--text-secondary: #A9BAD4;
|
|
--border: #0B2A59;
|
|
--focus-ring: #70F0F9;
|
|
|
|
--error-bg: #3A1113;
|
|
--error-text: #FFB3AD;
|
|
--error-border: #7A2B2B;
|
|
}
|
|
}
|
|
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
font-size: 17px;
|
|
line-height: 1.5;
|
|
/* A long code or address must wrap rather than widen the page: the narrow
|
|
layout this site is read on has no horizontal room to give. */
|
|
overflow-wrap: break-word;
|
|
}
|
|
|
|
img {
|
|
max-width: 100%;
|
|
}
|
|
|
|
/* One centred column, the whole site. */
|
|
.column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 32px;
|
|
width: 100%;
|
|
max-width: 560px;
|
|
min-height: 100vh;
|
|
margin: 0 auto;
|
|
padding: 40px var(--gutter) 56px;
|
|
}
|
|
|
|
.masthead {
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.logo {
|
|
display: block;
|
|
width: auto;
|
|
height: 34px;
|
|
}
|
|
|
|
.logo--dark {
|
|
display: none;
|
|
}
|
|
|
|
#app {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
}
|
|
|
|
.screen {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24px;
|
|
animation: screen-fade-in 150ms ease-out;
|
|
}
|
|
|
|
@keyframes screen-fade-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.screen {
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
.screen__heading {
|
|
margin: 0;
|
|
font-size: 1.625rem;
|
|
font-weight: 600;
|
|
line-height: 1.25;
|
|
text-align: center;
|
|
}
|
|
|
|
.prose {
|
|
margin: 0;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24px;
|
|
margin: 0;
|
|
}
|
|
|
|
/* A plain block fieldset: a flex or grid fieldset moves its rendered legend
|
|
out of normal flow in some engines, and the legend is a real one here. */
|
|
.options {
|
|
margin: 0;
|
|
padding: 0;
|
|
border: 0;
|
|
}
|
|
|
|
.options__legend {
|
|
margin: 0 0 12px;
|
|
padding: 0;
|
|
color: var(--text-secondary);
|
|
font-size: 0.9375rem;
|
|
}
|
|
|
|
/* The radio card, following PeriodCard in BadgesPayView.kt: a 2px border that
|
|
turns accent when selected. The input stays in the accessibility tree and
|
|
in the tab order; only its own rendering is hidden. */
|
|
.option {
|
|
display: block;
|
|
cursor: pointer;
|
|
/* The containing block for the clipped radio below. Harmless while its
|
|
offsets are auto, and the difference between a 1px box inside this card
|
|
and one in the corner of the page the moment anyone sets top or left. */
|
|
position: relative;
|
|
}
|
|
|
|
.option + .option {
|
|
margin-top: 12px;
|
|
}
|
|
|
|
.option__input {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
margin: 0;
|
|
padding: 0;
|
|
border: 0;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
clip-path: inset(50%);
|
|
}
|
|
|
|
.option__body {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
padding: 16px 18px;
|
|
border: 2px solid var(--border);
|
|
border-radius: var(--radius);
|
|
background: var(--card-bg);
|
|
}
|
|
|
|
.option__input:checked + .option__body {
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
.option__input:focus-visible + .option__body {
|
|
outline: 2px solid var(--focus-ring);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
.option__input:disabled + .option__body {
|
|
cursor: default;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.option__label {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.option__detail {
|
|
color: var(--text-secondary);
|
|
font-size: 0.9375rem;
|
|
}
|
|
|
|
.option__input:checked + .option__body .option__detail {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.summary {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 8px 16px;
|
|
margin: 0;
|
|
}
|
|
|
|
.summary__term {
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.summary__value {
|
|
margin: 0;
|
|
text-align: right;
|
|
}
|
|
|
|
.button {
|
|
width: 100%;
|
|
padding: 14px 24px;
|
|
border: 0;
|
|
border-radius: 999px;
|
|
background: var(--accent);
|
|
color: var(--on-accent);
|
|
font: inherit;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.button:hover {
|
|
background: var(--accent-hover);
|
|
}
|
|
|
|
/* Nothing here fails to a blank screen: a failed fetch or an unanswered
|
|
question says so in this banner. */
|
|
.banner {
|
|
margin: 0;
|
|
padding: 12px 16px;
|
|
border: 1px solid var(--error-border);
|
|
border-radius: 12px;
|
|
background: var(--error-bg);
|
|
color: var(--error-text);
|
|
}
|
|
|
|
.footer {
|
|
margin-top: auto;
|
|
font-size: 0.9375rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.footer a {
|
|
color: var(--accent);
|
|
}
|
|
|
|
/* The only focus styling in this file, and nothing suppresses it: there is no
|
|
`outline: none` anywhere here. */
|
|
:focus-visible {
|
|
outline: 2px solid var(--focus-ring);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
/* Forced colours replace every author colour with a system one, so the accent
|
|
border stops distinguishing the selected card from the others. Border
|
|
*style* is not overridden, so selection is carried by it as well. Not an
|
|
outline: the focus ring is an outline on this same element, and one would
|
|
erase the other while a card is focused. */
|
|
@media (forced-colors: active) {
|
|
.option__body {
|
|
border-style: dotted;
|
|
}
|
|
|
|
.option__input:checked + .option__body {
|
|
border-style: solid;
|
|
border-color: Highlight;
|
|
}
|
|
}
|
|
|
|
/* LAST IN THE FILE, DELIBERATELY, and everything below this line must stay
|
|
below the defaults it overrides. These four selectors are all specificity
|
|
(0,1,0); @media adds none and does not reorder its contents, so a rule here
|
|
wins only by appearing after `.logo` and `.logo--dark` above. Moved up, the
|
|
toggle silently stops working and dark mode shows the dark-blue logo on the
|
|
navy background — no error, nothing in the console. */
|
|
@media (prefers-color-scheme: dark) {
|
|
.logo--light {
|
|
display: none;
|
|
}
|
|
|
|
.logo--dark {
|
|
display: block;
|
|
}
|
|
}
|