Files
selfpost/docs/assets/panel-redesign/panel/theme.css
T
mixandClaude Opus 5.5 0feaa552d1 design: health-setup-checks - the name check a tag beside Names
The owner, 2026-10-16: "Может match ставить бэйджем в заголовок names?"
The certificate card loses its own "Matches the hostname" row: a tag
beside Names says it - "matches", or "not for the hostname" in red. A
fact's label may carry a tag (sp-facts dt .tag keeps the tag's own type),
shown on the kit page. Help says where the verdict is. check.py: 0
violations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 23:31:01 +03:00

366 lines
24 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* The accepted direction: C ("Counter", Bulma) as the base, the postal
signature of A (postmark, numbered mono section heads, the stamp's
perforation) and the icons of B. Bulma carries navbar, dropdowns, columns,
boxes, tables, tags, menu, forms; what follows is brand mapping plus the
handful of components that are SelfPost's own. */
:root {
--bulma-family-primary: var(--sp-sans);
--bulma-family-secondary: var(--sp-sans);
--bulma-family-code: var(--sp-mono);
--bulma-primary-h: 10deg; --bulma-primary-s: 45%; --bulma-primary-l: 33%;
--bulma-link-h: 10deg; --bulma-link-s: 45%; --bulma-link-l: 33%;
--bulma-success-h: 138deg; --bulma-success-s: 42%; --bulma-success-l: 30%;
--bulma-warning-h: 36deg; --bulma-warning-s: 85%; --bulma-warning-l: 55%;
--bulma-danger-h: 4deg; --bulma-danger-s: 76%; --bulma-danger-l: 40%;
--bulma-radius: 6px; --bulma-radius-large: 10px;
--bulma-body-size: 16px;
/* The type scale. Three sizes carry all running text; nothing a person has
to read is below 13px. check.py enforces the floor.
body 16px text, inputs, buttons, menus, table cells
s 14px supporting text: labels, help, notes, footers, mono values, logs
xs 13px upper-case mono micro-labels and tags only */
--sp-fs-s: .875rem;
--sp-fs-xs: .8125rem;
--bulma-link-text: var(--sp-brick);
--bulma-link-text-hover: var(--sp-brick-dark);
}
/* Bulma picks a button's text colour from the lightness of its fill; our brick
and our red are dark enough to land on the wrong side and get near-black
text (3:1). Solid buttons are white on colour; the light variants keep
Bulma's dark-on-tint. */
.button.is-primary:not(.is-light), .button.is-primary:not(.is-light):hover,
.button.is-danger:not(.is-light), .button.is-danger:not(.is-light):hover { color: #fff; }
a strong { color: inherit; }
html, body { background: var(--sp-paper); }
body { color: var(--sp-ink); min-height: 100vh; display: flex; flex-direction: column; }
main { flex: 1; }
code { background: var(--sp-well); color: var(--sp-ink); border-radius: 3px; padding: .1em .35em; font-size: .95em; }
.ti { font-size: 1.15em; vertical-align: -.12em; }
.button .ti { margin-right: .35rem; }
.sp-muted { color: var(--sp-muted); }
/* Bulma ships these at .75rem; on the scale they are s or xs. `sp-small`
replaces Bulma's `is-size-7` helper, which is .75rem and !important. */
.help, .label { font-size: var(--sp-fs-s); }
.tag, .menu-label { font-size: var(--sp-fs-xs); }
.menu-label { color: var(--sp-muted); } /* Bulma's grey is 4.2:1 on the paper */
.sp-small { font-size: var(--sp-fs-s); }
.sp-mono { font-family: var(--sp-mono); }
.sp-nowrap { white-space: nowrap; }
/* ---- navbar, the perforated edge under it, sibling pages below */
.navbar.is-primary { --bulma-navbar-height: 4rem; }
/* The name, not the stamp: at this size the stamp's perforation is under a
pixel and its brick field dissolves into the bar. The stamp stays where it
has room — sign-in, setup, the favicon. */
.navbar-brand img { max-height: none; height: 1.45rem; }
.navbar.is-primary .navbar-item, .navbar.is-primary .navbar-link { color: var(--sp-on-brick); font-weight: 500; }
.navbar.is-primary .navbar-link::after { border-color: var(--sp-on-brick); }
.navbar.is-primary .navbar-link .ti { margin-right: .4rem; }
/* Bulma shrinks dropdown items to .875rem; a menu entry is read as often as
the bar it hangs from, so it gets the bar's size. */
.navbar-dropdown { border-top: 0; box-shadow: 0 8px 24px rgb(18 22 28 / .14); font-size: 1rem; }
.navbar.is-primary .navbar-dropdown .navbar-item { color: var(--sp-ink); font-weight: 400; padding-right: 2rem; }
.navbar.is-primary .navbar-dropdown .navbar-item .ti { margin-right: .6rem; color: var(--sp-muted); }
.navbar.is-primary .navbar-dropdown .navbar-item.is-active { color: var(--sp-brick); font-weight: 600; background: var(--sp-brick-tint); }
.navbar.is-primary .navbar-dropdown .navbar-item.is-active .ti { color: var(--sp-brick); }
/* Sign out is a POST, so it is a form with a button rather than a link. Bulma
tints only a.navbar-item; the button is handed the same variables, and the
form stretches it across the menu, so it answers the pointer, the keyboard
and a press exactly like the entries above it. */
.navbar-dropdown form { display: flex; }
.navbar-dropdown button.navbar-item { flex: 1; cursor: pointer; }
.navbar-dropdown button.navbar-item:hover, .navbar-dropdown button.navbar-item:focus { --bulma-navbar-item-background-l-delta: var(--bulma-navbar-item-hover-background-l-delta); }
.navbar-dropdown button.navbar-item:active { --bulma-navbar-item-background-l-delta: var(--bulma-navbar-item-active-background-l-delta); }
.navbar.is-primary .sp-current > .navbar-link, .navbar.is-primary a.navbar-item.sp-current { background: rgb(0 0 0 / .18); }
/* Below 1024 px Bulma hides the bar's menu (navbar-menu without is-active)
and the touch navigation takes its place: Menu at the right of the brand
opens a panel over the page, its sections folded but the current one.
<details> all through, so it needs no script (owner, 2026-10-16: the menu
had been a sheet of every section open, filling the first screen). */
.sp-touchnav { display: none; }
.sp-touchnav summary { list-style: none; cursor: pointer; }
.sp-touchnav summary::-webkit-details-marker { display: none; }
.sp-touchnav summary::after { content: "›"; display: inline-block; margin-left: .5rem; font-size: 1.3rem; line-height: 1; transform: rotate(90deg); transition: transform .15s; }
.sp-touchnav[open] > summary::after, .sp-touchnav-group[open] > summary::after { transform: rotate(-90deg); }
.sp-touchnav > summary { display: flex; align-items: center; padding: 0 1rem; color: var(--sp-on-brick); font-weight: 500; }
.sp-touchnav-panel { position: absolute; top: 100%; left: 0; right: 0; z-index: 30; background: var(--sp-brick); box-shadow: 0 12px 28px rgb(18 22 28 / .22); padding-bottom: .4rem; }
.sp-touchnav-panel > a, .sp-touchnav-group > summary { display: flex; align-items: center; gap: .45rem; padding: .75rem 1rem; color: var(--sp-on-brick); font-weight: 500; }
.sp-touchnav-group > summary::after { margin-left: auto; }
.sp-touchnav-panel > a[aria-current], .sp-touchnav-group[open] > summary { background: rgb(0 0 0 / .18); }
.sp-touchnav-group a, .sp-touchnav-group button { display: flex; align-items: center; gap: .6rem; padding: .65rem 1rem .65rem 2rem; background: #fff; color: var(--sp-ink); border: 0; font: inherit; text-align: left; cursor: pointer; }
.sp-touchnav-group form { display: flex; }
.sp-touchnav-group button { flex: 1; }
.sp-touchnav-group .ti { color: var(--sp-muted); }
.sp-touchnav-group a[aria-current] { color: var(--sp-brick); font-weight: 600; background: var(--sp-brick-tint); }
.sp-touchnav-group a[aria-current] .ti { color: var(--sp-brick); }
/* The header is built like the mark: a brick field, then the stamp's paper
margin, and the perforation runs along the outer edge of that margin — round
holes, flat teeth, the mark's ink hairline (perf-edge.svg is one tooth and
one hole at the mark's 2.2 / 7.03 ratio). On the mark the margin is one
pitch deep and a tenth of the brick field's height; here that is 8px under
a 60px bar — a little over a tenth, so a 2.5px hole still reads as round. */
.sp-perf {
height: 8px;
background:
url("perf-edge.svg") repeat-x left bottom / 8px 4px,
linear-gradient(var(--sp-stamp-paper), var(--sp-stamp-paper)) no-repeat left top / 100% 4px;
}
.sp-subnav { border-bottom: 1px solid var(--sp-rule); margin-top: -1px; }
.sp-subnav .container { display: flex; gap: 1.8rem; overflow-x: auto; }
.sp-subnav a { color: var(--sp-muted); padding: .75rem 0 .65rem; white-space: nowrap; border-bottom: 2px solid transparent; }
.sp-subnav a .ti { margin-right: .4rem; }
.sp-subnav a:hover { color: var(--sp-ink); }
.sp-subnav a[aria-current] { color: var(--sp-ink); font-weight: 600; border-bottom-color: var(--sp-brick); }
/* ---- page head */
.sp-page { padding-block: 1.8rem 2.5rem; }
.sp-head { display: flex; align-items: center; gap: 1.2rem; flex-wrap: wrap; margin-bottom: 1.5rem; }
.sp-head .sp-grow { flex: 1; min-width: 14rem; }
.sp-kicker { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--sp-muted); }
.sp-kicker a { color: inherit; }
.sp-kicker a:hover { color: var(--sp-brick); }
.title { color: var(--sp-ink); font-weight: 600; }
.sp-head .title { margin: 0; overflow-wrap: anywhere; }
.sp-head .sp-lead { color: var(--sp-muted); margin-top: .2rem; max-width: 48rem; }
.sp-head .buttons { margin: 0; }
.sp-head .buttons > * { margin-bottom: 0; }
/* ---- postmark */
.sp-postmark {
flex: none; width: 6rem; height: 6rem; border-radius: 50%; transform: rotate(-9deg);
border: 2px solid currentColor; outline: 1px solid currentColor; outline-offset: 3px; margin: .3rem .5rem;
display: grid; place-content: center; text-align: center; color: var(--sp-ok);
font-family: var(--sp-mono); font-weight: 600; letter-spacing: .08em; line-height: 1.15;
}
.sp-postmark.sp-warn { color: var(--sp-warn); }
.sp-postmark.sp-fail { color: var(--sp-fail); }
.sp-postmark b { font-size: 1.3rem; display: block; }
/* Below the floor on purpose: an imprint, and the heading beside it says the same in words. */
.sp-postmark span { font-size: .6rem; display: block; }
/* ---- box with a numbered mono head */
.box { box-shadow: none; border: 1px solid var(--sp-rule); padding: 0; overflow: hidden; }
.box > .sp-box-head {
display: flex; flex-wrap: wrap; align-items: center; gap: .7rem; padding: .7rem 1.25rem; border-bottom: 1px solid var(--sp-rule);
}
.sp-box-head form.sp-end { justify-content: flex-end; }
/* Bulma's .input is 100% wide; in the filter row it takes a flex basis instead, so it sits beside the selects. */
.sp-box-head form.sp-end > .input { flex: 0 1 10.5rem; }
.sp-box-head .sp-no { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); font-weight: 600; color: var(--sp-brick); }
.sp-box-head h2 { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); font-weight: 600; letter-spacing: .1em; text-transform: uppercase; margin: 0; }
.sp-box-head .sp-end { margin-left: auto; color: var(--sp-muted); font-size: var(--sp-fs-s); display: flex; gap: .6rem; align-items: center; }
.sp-box-head .sp-help { color: var(--sp-muted); line-height: 1; }
.sp-box-head .sp-help:hover { color: var(--sp-brick); }
.sp-box-head .sp-end + .sp-help { margin-left: 0; }
.sp-box-head h2 + .sp-help { margin-left: auto; }
.notification { border: 1px solid transparent; padding: .8rem 1.25rem; }
.notification.is-success.is-light { border-color: var(--sp-ok-rule); }
.notification.is-danger.is-light { border-color: var(--sp-fail-rule); }
.notification .ti { margin-right: .5rem; }
.box > .sp-box-body { padding: 1.25rem; }
.box > .sp-box-body > :last-child { margin-bottom: 0; }
/* A table never sits bare in a box: the container lets a wide one scroll
sideways instead of being cut off by the box's rounded overflow. */
.box > .table-container, .box > .table-container > .table { margin: 0; }
.sp-box-foot .sp-end { margin-left: auto; }
/* A filter form in the head keeps full-size controls; the head gives up its
own padding to them instead of shrinking the text. */
.sp-box-head form.sp-end { margin-block: -.35rem; font-size: 1rem; }
.box > .sp-box-foot {padding: .7rem 1.25rem; border-top: 1px solid var(--sp-rule); color: var(--sp-muted); font-size: var(--sp-fs-s); display: flex; gap: 1rem; align-items: center; }
.box.sp-danger-zone { border-color: var(--sp-fail-rule); }
.box.sp-danger-zone .sp-box-head { background: var(--sp-fail-bg); border-color: var(--sp-fail-rule); }
.box.sp-credential { border-color: #e0c874; }
.box.sp-credential .sp-box-head { background: #fcf6e4; border-color: #e0c874; }
.table { background: transparent; }
.table thead th { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); font-weight: 400; letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); }
/* Addresses in tables carry a <wbr> after the @ (one template function), so a
long one breaks where it reads naturally and its column can still shrink;
`overflow-wrap: anywhere` would do it too, but mid-word. */
.table td, .table th { vertical-align: middle; padding: .55rem .6rem; }
.box > .table-container td:first-child, .box > .table-container th:first-child { padding-left: 1.25rem; }
.box > .table-container td:last-child, .box > .table-container th:last-child { padding-right: 1.25rem; }
.table td.sp-actions { text-align: right; white-space: nowrap; }
/* An action that changes state (New password, Delete) is a POST, so it is a form
with a button, not a link. The form sits inline like the links beside it and
the button is handed the link's colour and type; Bulma already resets the
button and shares the pointer and the focus ring between a and button, and a
link here has no hover colour of its own. */
.table td.sp-actions a, .table td.sp-actions form { margin-left: .9rem; }
.table td.sp-actions form { display: inline; }
.table td.sp-actions button { color: var(--bulma-link-text); font: inherit; }
.table td.sp-clip { max-width: 13rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag { font-family: var(--sp-mono); font-weight: 600; letter-spacing: .04em; }
.sp-empty { padding: 2.2rem 1.25rem; text-align: center; color: var(--sp-muted); }
.sp-empty .ti { font-size: 2rem; display: block; margin-bottom: .4rem; color: var(--sp-rule-strong); }
/* ---- health cards */
/* Six cards: six, three or two columns — never a count that leaves one card alone on a row. */
.sp-health { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0; }
.sp-health > a {
display: flex; gap: .7rem; align-items: center; padding: .75rem 1rem; color: var(--sp-ink); min-width: 0;
border-right: 1px solid var(--sp-rule); border-bottom: 1px solid var(--sp-rule); margin: 0 -1px -1px 0;
}
.sp-health > a:hover { background: var(--sp-paper); }
.sp-health > a > span:last-child { min-width: 0; }
.sp-h-icon { flex: none; width: 2.1rem; height: 2.1rem; border-radius: 7px; display: grid; place-content: center; background: var(--sp-ok-bg); color: var(--sp-ok); }
.sp-h-icon .ti { font-size: 1.25rem; vertical-align: 0; }
.sp-health > a.sp-warn { background: var(--sp-warn-bg); }
.sp-health > a.sp-warn .sp-h-icon { background: #f6e2b8; color: #8a5510; }
.sp-health > a.sp-fail { background: var(--sp-fail-bg); }
.sp-health > a.sp-fail .sp-h-icon { background: #f5d3cc; color: var(--sp-fail); }
/* Each line is a block with its own tight line height; a verdict is two or
three words and never wraps — a wrapped card would stretch the whole row. */
.sp-h-name, .sp-h-value, .sp-h-sub { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sp-h-name { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); line-height: 1.3; }
.sp-h-value { font-weight: 600; line-height: 1.3; }
.sp-h-sub { font-size: var(--sp-fs-s); color: var(--sp-muted); line-height: 1.3; }
/* ---- facts, records, side menu */
.sp-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 1rem 1.5rem; margin: 0; }
.sp-facts dt { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); }
.sp-facts dd { margin: 0; overflow-wrap: anywhere; }
/* A label may carry a tag, the verdict on its value (the certificate's
names against the hostname); it keeps the tag's own type. */
.sp-facts dt .tag { margin-left: .4rem; text-transform: none; letter-spacing: 0; vertical-align: 1px; }
/* A fact that takes the whole row: a line a server wrote, read as one. */
.sp-facts .sp-wide { grid-column: 1 / -1; }
.sp-facts dd.sp-big { font-size: 1.5rem; font-weight: 600; line-height: 1.2; }
.sp-side { position: sticky; top: 1.5rem; }
.menu-label { font-family: var(--sp-mono); letter-spacing: .1em; }
.menu-list a { display: flex; align-items: center; gap: .55rem; }
.menu-list a .ti { color: var(--sp-muted); }
.menu-list a.is-active .ti { color: inherit; }
.menu-list a .tag { margin-left: auto; }
.sp-record { padding: 1.25rem; }
.sp-record + .sp-record { border-top: 1px solid var(--sp-rule); }
.sp-record-head { display: flex; align-items: center; gap: .6rem; margin-bottom: .75rem; }
.sp-record-head h3 { font-size: 1rem; font-weight: 600; margin: 0; }
.sp-record-head small { margin-left: auto; color: var(--sp-muted); text-align: right; }
/* A record DNS already holds as shown is folded to its head: a <details>
whose summary is the head, opened without script. */
details.sp-record > summary { list-style: none; cursor: pointer; }
details.sp-record > summary::-webkit-details-marker { display: none; }
details.sp-record:not([open]) > summary { margin-bottom: 0; }
details.sp-record:not([open]) > summary small { display: none; }
details.sp-record[open] .sp-record-head small + .sp-record-toggle { margin-left: 0; }
.sp-record-toggle { margin-left: auto; display: inline-flex; align-items: center; gap: .3rem; color: var(--sp-brick); font-size: var(--sp-fs-s); white-space: nowrap; }
.sp-record-toggle span + span { display: none; }
details.sp-record[open] .sp-record-toggle span { display: none; }
details.sp-record[open] .sp-record-toggle span + span { display: inline; }
.sp-record .label, .sp-form .label { font-weight: 500; color: var(--sp-ink-2); margin-bottom: .25rem; }
.sp-record .label { font-weight: 400; color: var(--sp-muted); }
.input[readonly], .textarea[readonly] { font-family: var(--sp-mono); font-size: var(--sp-fs-s); background: var(--sp-well); box-shadow: none; }
/* Bulma sizes a control from its own font; the smaller mono text made the
value shorter than the Copy button joined to it. */
.input[readonly] { height: 2.5rem; }
.textarea[readonly] { min-height: 2.5rem; }
.textarea[readonly] { resize: none; min-height: 0; }
.sp-record .field:not(:last-child) { margin-bottom: .6rem; }
.sp-row { display: grid; grid-template-columns: 1fr 7rem; gap: .75rem; }
.sp-pair { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; }
/* ---- logs, timeline, help */
.sp-log {
margin: 0; padding: 1rem 1.25rem; background: #191c21; color: #d9d5cc; border-radius: 0;
font-family: var(--sp-mono); font-size: var(--sp-fs-s); line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere;
}
/* One line of a log: long ones wrap inside the pane, the rest of the line
indented under its start, so nothing scrolls sideways - a phone drew the
scroll bars over the text (owner, 2026-10-16). */
.sp-log .sp-ll { display: block; padding-left: 4ch; text-indent: -4ch; }
.sp-log .sp-w { color: #e0b15c; } .sp-log .sp-e { color: #ef8f82; } .sp-log .sp-d { color: #7f8894; }
.sp-timeline { list-style: none; margin: 0; padding: 0; }
.sp-timeline li { position: relative; padding: 0 0 1.1rem 1.6rem; border-left: 2px solid var(--sp-rule); margin-left: .4rem; }
.sp-timeline li:last-child { padding-bottom: 0; border-left-color: transparent; }
.sp-timeline li::before { content: ""; position: absolute; left: -7px; top: .25rem; width: 12px; height: 12px; border-radius: 50%; background: var(--sp-ok); box-shadow: 0 0 0 3px #fff; }
.sp-timeline li.sp-warn::before { background: #d9962b; }
.sp-timeline li.sp-fail::before { background: var(--sp-fail); }
.sp-timeline li.sp-pending::before { background: #fff; border: 2px solid var(--sp-rule-strong); }
.sp-timeline time { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); color: var(--sp-muted); display: block; }
.sp-route { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; font-family: var(--sp-mono); font-size: var(--sp-fs-s); margin-top: .3rem; }
.sp-help-topic + .sp-help-topic { border-top: 1px solid var(--sp-rule); }
.sp-help-topic { padding: 1rem 1.25rem; }
.sp-help-topic h3 { font-weight: 600; margin-bottom: .3rem; }
.sp-list-check { list-style: none; margin: 0 0 1rem; }
.sp-list-check li { padding-left: 1.7rem; position: relative; margin-bottom: .45rem; }
.sp-list-check li .ti { position: absolute; left: 0; top: .15rem; color: var(--sp-fail); }
/* ---- signed-out pages */
.sp-signin { min-height: 100vh; margin: 0; }
.sp-signin-brand { background: var(--sp-brick); display: grid; place-content: center; text-align: center; padding: 3rem; position: relative; }
.sp-signin-brand::after {
content: ""; position: absolute; top: 0; bottom: 0; right: -7px; width: 7px; z-index: 1;
background: radial-gradient(circle at 0 7px, var(--sp-brick) 5px, transparent 5.6px); background-size: 7px 14px;
}
.sp-signin-brand img { width: 20rem; max-width: 100%; height: auto; }
.sp-signin-brand p { font-family: var(--sp-mono); letter-spacing: .18em; font-size: var(--sp-fs-xs); color: var(--sp-on-brick); margin-top: 1.6rem; }
.sp-signin-form { display: flex; flex-direction: column; justify-content: center; padding: 3rem; }
.sp-signin-form .sp-form { width: 22rem; max-width: 100%; margin-inline: auto; }
.sp-foot { color: var(--sp-muted); font-size: var(--sp-fs-s); padding-block: 1.5rem 0; }
.sp-foot a { color: inherit; text-decoration: underline; }
.sp-signin-form .sp-foot { text-align: center; margin-top: 2.5rem; }
@media (max-width: 1407px) { .sp-health { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 1023px) {
.sp-box-head form.sp-end { flex-wrap: wrap; }
.sp-touchnav { display: flex; margin-left: auto; }
/* Bulma gives a container side margins only from 1024 px: below it the
page met the screen's edge. */
.sp-subnav .container, .container.sp-page { padding-inline: 1rem; }
}
@media (max-width: 768px) {
.sp-health { grid-template-columns: repeat(2, 1fr); }
.sp-row, .sp-pair { grid-template-columns: 1fr; }
.sp-record-head { flex-wrap: wrap; }
.sp-record-head small { margin-left: 0; text-align: left; flex-basis: 100%; order: 1; }
details.sp-record[open] .sp-record-head small + .sp-record-toggle { margin-left: auto; }
.sp-postmark { display: none; }
.sp-cards { display: flex; flex-direction: column; padding-inline: .75rem; }
.sp-cards > .column { display: contents; }
.sp-cards .box { margin-bottom: 1.5rem; }
.sp-cards [data-order="1"] { order: 1; }
.sp-cards [data-order="2"] { order: 2; }
.sp-cards [data-order="3"] { order: 3; }
.sp-cards [data-order="4"] { order: 4; }
.sp-cards [data-order="5"] { order: 5; }
.sp-cards [data-order="6"] { order: 6; }
.sp-cards [data-order="7"] { order: 7; }
.sp-cards [data-order="8"] { order: 8; }
.sp-cards [data-order="9"] { order: 9; }
.sp-cards [data-order="10"] { order: 10; }
.sp-cards [data-order="11"] { order: 11; }
.sp-cards [data-order="12"] { order: 12; }
}
/* cards: two stacks of boxes that are read in rows - the odd ones on the left,
the even ones on the right, each stack closed up so a short box leaves no
gap beside a tall one. On a phone the stacks dissolve and the boxes come in
the order of their numbers: each box carries data-order, its own number (the
rules above, up to twelve), wherever it stands in its stack. */
/* sheet: what does not fit a table row, opened over the page from the row's
tag. It is the browser's own popover (the tag is a button with
popovertarget), so it needs no script: Esc, a click outside and the close
button all shut it, and focus returns to the tag. It rises from the bottom
edge across the whole window - the one component that is not laid out by the
page, hence the widths - with its content, a table of name and value, in a
column of reading width in the middle. */
.sp-sheet {
inset: auto 0 0 0; width: auto; margin: 0; padding: 0; border: 0; border-top: 3px solid var(--sp-brick);
max-height: 75vh; overflow: auto; background: #fff; color: inherit; box-shadow: 0 -12px 40px rgba(40, 20, 15, .22);
}
.sp-sheet-in { max-width: 44rem; margin: 0 auto; padding: 0 1.25rem; }
.sp-sheet::backdrop { background: rgba(40, 20, 15, .38); }
.sp-sheet-head { display: flex; align-items: center; gap: .7rem; padding: 1rem 0 .8rem; border-bottom: 1px solid var(--sp-rule); }
.sp-sheet-head h2 { font-size: 1.15rem; font-weight: 600; margin-right: auto; }
.sp-sheet-head button { border: 0; background: none; cursor: pointer; font-size: 1.3rem; color: var(--sp-muted); }
.sp-sheet-body { padding: .4rem 0 1.4rem; }
/* The sheet's content is a table of name and value: the name is a label, set like the dt of facts. */
.sp-sheet .table th { font-family: var(--sp-mono); font-size: var(--sp-fs-xs); font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--sp-muted); white-space: nowrap; vertical-align: top; width: 1%; padding-right: 2rem; }
.sp-sheet .table td { overflow-wrap: anywhere; }
/* A tag that opens a sheet is a button: it keeps the tag's look and says it can
be pressed with the dotted underline links to more detail carry. */
button.tag { border: 0; cursor: pointer; text-decoration: underline dotted; text-underline-offset: 3px; }