905 lines
15 KiB
CSS
905 lines
15 KiB
CSS
:root {
|
|
color-scheme: light dark;
|
|
--bg: #f4f5f7;
|
|
--surface: #ffffff;
|
|
--header-bg: #eaf0f8;
|
|
--card-bg: #fafafa;
|
|
--text: #1d2330;
|
|
--muted: #5f6878;
|
|
--border: #d9dde4;
|
|
--accent: #2f6fd6;
|
|
--accent-text: #ffffff;
|
|
--ok: #1f7a45;
|
|
--ok-bg: #e3f4ea;
|
|
--warn: #8a5a00;
|
|
--warn-bg: #fff2d6;
|
|
--err: #b3261e;
|
|
--err-bg: #fbe4e2;
|
|
--info: #22529e;
|
|
--info-bg: #e2ecfb;
|
|
--ins-bg: #dcf5e3;
|
|
--del-bg: #fbe0de;
|
|
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
/* Text sizes. They use rem, so they do not shrink when one small element sits in another. */
|
|
--text-sm: 0.875rem;
|
|
--text-xs: 0.8rem;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--bg: #14171c;
|
|
--surface: #1d2128;
|
|
--header-bg: #202b3d;
|
|
--card-bg: #262626;
|
|
--text: #e3e6eb;
|
|
--muted: #9aa3b2;
|
|
--border: #343a45;
|
|
--accent: #6b9cf0;
|
|
--accent-text: #0e1420;
|
|
--ok: #74d49a;
|
|
--ok-bg: #1d3527;
|
|
--warn: #f0c060;
|
|
--warn-bg: #3a2f14;
|
|
--err: #f28b82;
|
|
--err-bg: #3d1f1d;
|
|
--info: #9cbcf5;
|
|
--info-bg: #1f2c44;
|
|
--ins-bg: #1c3a26;
|
|
--del-bg: #43211f;
|
|
}
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
font-size: 15px;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font: 1rem/1.5 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
}
|
|
|
|
a {
|
|
color: var(--accent);
|
|
}
|
|
|
|
a:focus-visible,
|
|
button:focus-visible,
|
|
summary:focus-visible {
|
|
outline: 2px solid var(--accent);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
h1,
|
|
h2,
|
|
p {
|
|
margin: 0 0 8px;
|
|
}
|
|
|
|
h1,
|
|
h2 {
|
|
line-height: 1.3;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 1.4rem;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 1.1rem;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
h1 + h2 {
|
|
margin-top: 16px;
|
|
}
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
th,
|
|
td {
|
|
text-align: left;
|
|
padding: 6px 8px;
|
|
border-bottom: 1px solid var(--border);
|
|
vertical-align: top;
|
|
}
|
|
|
|
th {
|
|
font-weight: 600;
|
|
color: var(--muted);
|
|
font-size: var(--text-sm);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
tbody tr:last-child > td,
|
|
tbody tr:last-child > th {
|
|
border-bottom: 0;
|
|
}
|
|
|
|
td.actions {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
td.actions button + button {
|
|
margin-left: 6px;
|
|
}
|
|
|
|
fieldset {
|
|
border: 0;
|
|
margin: 0 0 12px;
|
|
padding: 0;
|
|
}
|
|
|
|
legend {
|
|
font-weight: 600;
|
|
padding: 0;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
input[type='checkbox'] {
|
|
width: 1rem;
|
|
height: 1rem;
|
|
margin: 0;
|
|
vertical-align: -2px;
|
|
accent-color: var(--accent);
|
|
}
|
|
|
|
progress {
|
|
width: 100%;
|
|
margin-top: 6px;
|
|
}
|
|
|
|
/* Layout */
|
|
|
|
header,
|
|
main {
|
|
width: min(1100px, calc(100% - 32px));
|
|
margin: 0px auto;
|
|
}
|
|
|
|
header,
|
|
main:not(.login) {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
box-shadow: 0 4px 16px rgb(0 0 0 / 5%);
|
|
}
|
|
main:not(.login) {
|
|
border-top: 0px;
|
|
}
|
|
|
|
header {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 16px 24px;
|
|
padding: 20px 24px 0;
|
|
background: var(--header-bg);
|
|
border-top-left-radius: 12px;
|
|
border-top-right-radius: 12px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
/* min-width: 0 lets the nav get narrower than its tabs, so on a phone the story tab shrinks
|
|
to an ellipsis instead of pushing the nav past the edge of the header. */
|
|
header nav {
|
|
display: flex;
|
|
flex-basis: 100%;
|
|
min-width: 0;
|
|
gap: 4px;
|
|
margin-bottom: -1px;
|
|
}
|
|
|
|
header nav a {
|
|
padding: 10px 18px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px 8px 0 0;
|
|
background: var(--bg);
|
|
color: var(--muted);
|
|
font-weight: 600;
|
|
text-decoration: none;
|
|
}
|
|
|
|
header nav a:hover {
|
|
background: var(--surface);
|
|
color: var(--text);
|
|
}
|
|
|
|
header nav a[aria-current='page'] {
|
|
background: var(--surface);
|
|
border-bottom-color: var(--surface);
|
|
color: var(--text);
|
|
}
|
|
|
|
/* A long story title ends in an ellipsis. The title attribute shows all of it. */
|
|
header nav a.story-tab {
|
|
max-width: 24ch;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 1.1rem;
|
|
font-weight: 700;
|
|
color: var(--text);
|
|
text-decoration: none;
|
|
}
|
|
|
|
header .brand {
|
|
font-size: 1.65rem;
|
|
line-height: 1.2;
|
|
letter-spacing: -0.025em;
|
|
}
|
|
|
|
header .brand img {
|
|
width: 32px;
|
|
height: 32px;
|
|
}
|
|
|
|
main {
|
|
padding: 20px;
|
|
border-bottom-left-radius: 12px;
|
|
border-bottom-right-radius: 12px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
main > :last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
main.login {
|
|
max-width: 400px;
|
|
margin-top: 64px;
|
|
}
|
|
|
|
.card {
|
|
background: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
padding: 16px 20px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
header,
|
|
main {
|
|
width: calc(100% - 24px);
|
|
padding: 12px;
|
|
}
|
|
|
|
header {
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
.card {
|
|
padding: 14px;
|
|
}
|
|
}
|
|
|
|
.card-danger {
|
|
border-color: var(--err);
|
|
}
|
|
|
|
details > summary {
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Adjoining margins collapse to the largest one, and the fieldset above ends in a p.hint with
|
|
an 8px bottom margin. These both go to 0, so that 8px is the whole gap: the smallest this
|
|
space can be without changing the hint's own margin. */
|
|
fieldset:has(+ .force-fields) {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.force-fields {
|
|
margin: 0 0 12px;
|
|
}
|
|
|
|
/* A card that folds shut, such as "Import chapters from an epub". Scoped to .card so it does not
|
|
change the small "Site value differs" fold of a metadata field. */
|
|
details.card > summary {
|
|
list-style: none;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
details.card > summary::-webkit-details-marker {
|
|
display: none;
|
|
}
|
|
|
|
details.card > summary::before {
|
|
content: '▸';
|
|
flex: none;
|
|
color: var(--muted);
|
|
transition: transform 0.15s ease;
|
|
}
|
|
|
|
details.card[open] > summary::before {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
details.card > summary h2 {
|
|
flex: 1;
|
|
min-width: 0;
|
|
/* Without this, the h2's own bottom margin throws off the vertical centering of the
|
|
arrow next to it, and leaves extra space under the heading. */
|
|
margin: 0;
|
|
}
|
|
|
|
details[open] > summary {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
/* The Download card offers this button even while closed. Once open, the controls below repeat it. */
|
|
details.card[open] > summary .summary-action {
|
|
display: none;
|
|
}
|
|
|
|
.controls,
|
|
.section-heading,
|
|
.account,
|
|
.job-heading,
|
|
.rule-actions,
|
|
.field-overrides,
|
|
.library-search,
|
|
.library-results > li {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 8px 12px;
|
|
}
|
|
|
|
.controls,
|
|
.field-overrides,
|
|
.library-search,
|
|
.library-results > li {
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.section-heading {
|
|
justify-content: space-between;
|
|
}
|
|
|
|
/* Stays visible while the chapter list scrolls, so the buttons need no scrolling back up to
|
|
reach, but only once a chapter is selected. Otherwise it would cover the top of the list for
|
|
no reason. It stops following once the Chapters card itself scrolls out of view. */
|
|
.card:has(.chapters-table input:checked) .chapter-actions {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 1;
|
|
background: var(--card-bg);
|
|
padding: 8px 0;
|
|
border-bottom: 1px solid var(--border);
|
|
/* Without its own compositing layer, some phone browsers repaint a stuck element with
|
|
several stacked children wrong while scrolling, showing only the last child. */
|
|
transform: translateZ(0);
|
|
}
|
|
|
|
.login form,
|
|
.login label:has(> input:not([type='checkbox'])) {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.account {
|
|
margin-left: auto;
|
|
color: var(--muted);
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.library-search > input {
|
|
flex-grow: 1;
|
|
}
|
|
|
|
label:has(> input[type='radio']) {
|
|
display: block;
|
|
}
|
|
|
|
.library-results {
|
|
list-style: none;
|
|
margin: 8px 0 0;
|
|
padding: 0;
|
|
}
|
|
|
|
/* Text */
|
|
|
|
.hint {
|
|
max-width: 80ch;
|
|
color: var(--muted);
|
|
font-size: var(--text-sm);
|
|
margin: 4px 0 8px;
|
|
}
|
|
|
|
.controls .hint,
|
|
.controls .error {
|
|
margin: 0;
|
|
}
|
|
|
|
.notice {
|
|
margin: 12px 0;
|
|
padding: 10px 14px;
|
|
border-left: 3px solid var(--warn);
|
|
border-radius: 6px;
|
|
background: var(--warn-bg);
|
|
}
|
|
|
|
.notice p {
|
|
margin: 0;
|
|
}
|
|
|
|
.notice ul {
|
|
margin: 4px 0 0;
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.byline,
|
|
.last-check,
|
|
.story-site,
|
|
.field-default,
|
|
small,
|
|
.date,
|
|
.job time {
|
|
color: var(--muted);
|
|
}
|
|
|
|
small,
|
|
.date,
|
|
.job time,
|
|
.breadcrumbs {
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.breadcrumbs {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.ini,
|
|
.story-urls,
|
|
.rule input:not(.rule-note) {
|
|
font-family: var(--mono);
|
|
}
|
|
|
|
/* A monospace font looks larger than the text font at the same size. The line height keeps these fields as tall as
|
|
the note field in the same row. */
|
|
.rule input:not(.rule-note) {
|
|
font-size: var(--text-sm);
|
|
line-height: 1.5rem;
|
|
}
|
|
|
|
.date {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.error {
|
|
color: var(--err);
|
|
}
|
|
|
|
.error:empty {
|
|
display: none;
|
|
}
|
|
|
|
.empty {
|
|
color: var(--muted);
|
|
font-style: italic;
|
|
}
|
|
|
|
.chapter-excluded {
|
|
opacity: 0.6;
|
|
}
|
|
|
|
/* Controls */
|
|
|
|
button,
|
|
a[download] {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
padding: 6px 14px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
background: var(--surface);
|
|
color: var(--text);
|
|
font: inherit;
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
}
|
|
|
|
button:hover:not(:disabled),
|
|
a[download]:hover {
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
button.primary:hover:not(:disabled) {
|
|
filter: brightness(1.08);
|
|
}
|
|
|
|
button.danger:hover:not(:disabled) {
|
|
border-color: var(--err);
|
|
background: var(--err-bg);
|
|
}
|
|
|
|
button:disabled {
|
|
opacity: 0.55;
|
|
cursor: default;
|
|
}
|
|
|
|
button.primary {
|
|
background: var(--accent);
|
|
border-color: var(--accent);
|
|
color: var(--accent-text);
|
|
}
|
|
|
|
button.danger {
|
|
border-color: var(--err);
|
|
color: var(--err);
|
|
}
|
|
|
|
:is(.account, .actions, .rule-actions, .job, .library-results) button {
|
|
padding: 2px 10px;
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.field-site .controls button {
|
|
padding: 0;
|
|
border: 0;
|
|
background: none;
|
|
color: var(--accent);
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* One metadata field: a stacked card, so it stays readable on a narrow phone screen. */
|
|
.field-grid {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 14px;
|
|
}
|
|
|
|
.field-grid > .field {
|
|
padding-bottom: 14px;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.field-grid > .field:last-child {
|
|
padding-bottom: 0;
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.field-head {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
/* On a wide screen, the label sits beside the field instead of above it, so a short value such
|
|
as a title does not stretch across the whole card. */
|
|
@media (min-width: 700px) {
|
|
.field {
|
|
display: grid;
|
|
grid-template-columns: 11em minmax(0, 1fr);
|
|
column-gap: 16px;
|
|
}
|
|
|
|
.field-head {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: 6px;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.field > :not(.field-head) {
|
|
grid-column: 2;
|
|
}
|
|
}
|
|
|
|
.field-label {
|
|
font-weight: 600;
|
|
}
|
|
|
|
.lock-toggle {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 3px 10px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 999px;
|
|
font-size: var(--text-sm);
|
|
color: var(--muted);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.lock-toggle:has(input:checked) {
|
|
border-color: var(--info);
|
|
background: var(--info-bg);
|
|
color: var(--info);
|
|
}
|
|
|
|
/* The site's current value, folded away so a long description does not push other fields down. */
|
|
.field-site {
|
|
margin-top: 6px;
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.field-site summary {
|
|
cursor: pointer;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.field-site p {
|
|
margin: 6px 0 0;
|
|
color: var(--text);
|
|
}
|
|
|
|
input:not([type='checkbox'], [type='radio']),
|
|
select,
|
|
textarea {
|
|
padding: 6px 8px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font: inherit;
|
|
min-width: 0;
|
|
max-width: 100%;
|
|
}
|
|
|
|
input:not([type='checkbox'], [type='radio']):focus,
|
|
select:focus,
|
|
textarea:focus {
|
|
outline: 2px solid var(--accent);
|
|
outline-offset: -1px;
|
|
}
|
|
|
|
input[type='number'] {
|
|
width: 6em;
|
|
}
|
|
|
|
textarea {
|
|
width: 100%;
|
|
resize: vertical;
|
|
line-height: 1.45;
|
|
}
|
|
|
|
.metadata input:not([type='checkbox']) {
|
|
width: 100%;
|
|
max-width: 32em;
|
|
}
|
|
|
|
.ini,
|
|
.story-urls {
|
|
font-size: var(--text-sm);
|
|
}
|
|
|
|
.badge {
|
|
display: inline-block;
|
|
padding: 0 7px;
|
|
border-radius: 10px;
|
|
font-size: var(--text-xs);
|
|
line-height: 1.6;
|
|
font-weight: 600;
|
|
background: var(--info-bg);
|
|
color: var(--info);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.badge-ok {
|
|
background: var(--ok-bg);
|
|
color: var(--ok);
|
|
}
|
|
|
|
.badge-err {
|
|
background: var(--err-bg);
|
|
color: var(--err);
|
|
}
|
|
|
|
.badge-warn {
|
|
background: var(--warn-bg);
|
|
color: var(--warn);
|
|
}
|
|
|
|
.badge-muted {
|
|
background: var(--bg);
|
|
color: var(--muted);
|
|
}
|
|
|
|
.badges .badge {
|
|
margin-right: 4px;
|
|
}
|
|
|
|
.table-wrap {
|
|
overflow-x: auto;
|
|
}
|
|
|
|
/* Jobs */
|
|
|
|
.jobs {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
max-height: 420px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.job {
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
padding: 8px 10px;
|
|
}
|
|
|
|
.job-heading > time {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.job > p {
|
|
margin: 0;
|
|
font-size: var(--text-sm);
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
/* Rules */
|
|
|
|
.rules {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
|
|
/* A rule is a card, like a row of the chapter list, the same at every width. The pattern and the
|
|
replacement each need the room of their own line, so nothing here shares a line with them. */
|
|
.rule {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
padding: 10px 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.rule-top,
|
|
.rule-bottom {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
/* Fits its 4-character maximum, and no more. */
|
|
.rule-flags {
|
|
width: 4.5em;
|
|
flex: none;
|
|
}
|
|
|
|
.rule-top .rule-note {
|
|
flex: 1;
|
|
}
|
|
|
|
.rule-actions {
|
|
display: flex;
|
|
flex: 1;
|
|
gap: 4px;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
/* The site cover sits at the top left of the story page, beside the title. */
|
|
.story-summary {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 20px;
|
|
}
|
|
|
|
.story-heading {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.story-summary .cover {
|
|
flex: none;
|
|
width: 140px;
|
|
height: auto;
|
|
border-radius: 6px;
|
|
box-shadow: 0 2px 8px rgb(0 0 0 / 20%);
|
|
}
|
|
|
|
@media (max-width: 600px) {
|
|
.story-summary {
|
|
gap: 12px;
|
|
}
|
|
|
|
.story-summary .cover {
|
|
width: 88px;
|
|
}
|
|
}
|
|
|
|
.rule-invalid {
|
|
outline: 2px solid var(--err);
|
|
}
|
|
|
|
.preview {
|
|
margin-top: 12px;
|
|
}
|
|
|
|
/* Toasts */
|
|
|
|
#toasts {
|
|
position: fixed;
|
|
right: 16px;
|
|
bottom: 16px;
|
|
z-index: 10;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
max-width: min(480px, calc(100vw - 32px));
|
|
}
|
|
|
|
.toast {
|
|
padding: 10px 16px;
|
|
border: 1px solid var(--accent);
|
|
border-radius: 8px;
|
|
background: var(--surface);
|
|
white-space: pre-line;
|
|
box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
|
|
}
|
|
|
|
.toast-error {
|
|
border-color: var(--err);
|
|
color: var(--err);
|
|
}
|
|
|
|
/* The server builds diff HTML with these classes, and escapes all text in it. */
|
|
|
|
.diff {
|
|
max-height: 70vh;
|
|
overflow-y: auto;
|
|
margin-top: 10px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
padding: 4px 12px;
|
|
}
|
|
|
|
.diff p {
|
|
margin: 6px 0;
|
|
padding: 2px 6px;
|
|
border-radius: 4px;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.diff .diff-eq {
|
|
color: var(--muted);
|
|
}
|
|
|
|
.diff .diff-ins,
|
|
.diff ins {
|
|
background: var(--ins-bg);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.diff .diff-del,
|
|
.diff del {
|
|
background: var(--del-bg);
|
|
}
|
|
|
|
.diff .diff-del {
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.diff .diff-skip {
|
|
text-align: center;
|
|
color: var(--muted);
|
|
font-style: italic;
|
|
font-size: var(--text-sm);
|
|
}
|