889f0f3f38
Spec #134, all ten tickets. Closes #134. ## What ships The admin surface becomes four bookmarkable addresses behind one nav row, and Lane observability stops dying with the process. - **#138** `/admin` splits into Overview, Lanes, Readers, Series, each a real route with the active tab underlined. - **#139** `poll_passes` and `poll_lanes` land as durable tables with their store surface. - **#140** cross-Series admin read model, with the privacy boundary in the projection: the Reader id that raised a Latest Chapter never leaves the store package. - **#141** the poller records exactly one pass row per exit, with a skip reason and outcome counts. - **#142** Series list: eight hygiene filters, Site and Library narrowing, paging — all of it in the query string, so a filtered list is a bookmark. - **#143** Overview: a three-state verdict line and a stats block where every non-zero figure links to the list that counts it. - **#144** per-Series detail page, keyed by the `site:series_id` composite the rest of the system already uses. - **#145** the Lanes page reads the database; the in-memory Lane state, `web.LaneReporter` and `latest.Status` are deleted. - **#146** Forced Poll: *Check now* stamps `series.force_poll_at` and never commands the poller. - **#147** pause and resume one Site's Lane, with a mandatory 1h/6h/24h expiry. ## Shape of the design Two decisions carry the rest. **Commands go through the database, never at the poller**: both *Check now* and a Lane pause write a row the next pass reads, so they survive a restart and the whole surface stays testable with no poller running. And **pending is derived, never stored** — the request stamp being newer than the check stamp — which self-clears on the check stamp with no second write and no sweeper, because the check stamp is written before the fetch. ADRs: `docs/adr/0012-persisted-lane-state.md`, `docs/adr/0013-commands-through-the-database.md`. ## Verification `go test ./...` green on the merged base (`264839e`), all packages, Docker-backed. `gofmt -l` and `go vet` clean. Every ticket was reviewed on both axes (`cr-spec` + `cr-standards`) before merge. ## Known, non-blocking - **#143** the verdict ignores never-reported Lanes when other Lanes have reported, and the per-Site table lists Sites that have Series rather than the whole registry. The ticket prose asks for eight hygiene figures per Site; the design mock and the landed `.tbl.sites` grid both say six columns, and the mock won. - **#146** two `SeriesPage` scans per press instead of a keyed read — `ponytail:`-commented in-tree with the upgrade path. - **#147** a paused Site with no pass row yet renders no row and so no control, since the Lanes page lists Sites that have passed. - **#141** a sibling browser Lane declining at the top of a pass records as `sidecar-down`. Specified deliberately; the later spec in this series settles it. Reviewed-on: #148 Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com> Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
831 lines
15 KiB
CSS
831 lines
15 KiB
CSS
:root {
|
|
--measure-wide: 1080px;
|
|
}
|
|
|
|
@media (prefers-color-scheme: light) {
|
|
:root {
|
|
--measure-wide: 1080px;
|
|
}
|
|
}
|
|
|
|
.admin-sheet {
|
|
max-width: var(--measure-wide);
|
|
}
|
|
|
|
.admin-sheet .brand em {
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .brand .mark > g > g:last-child {
|
|
stroke: var(--patina);
|
|
}
|
|
|
|
.topbar-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 18px;
|
|
margin-left: auto;
|
|
}
|
|
|
|
.navrow {
|
|
display: flex;
|
|
gap: 18px;
|
|
padding: 2px 20px 0;
|
|
overflow-x: auto;
|
|
overflow-y: hidden;
|
|
scrollbar-width: none;
|
|
border-bottom: 1px solid var(--rule);
|
|
}
|
|
|
|
.navrow::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.navrow a {
|
|
flex: none;
|
|
display: flex;
|
|
align-items: center;
|
|
min-width: 44px;
|
|
padding: 8px 0 12px;
|
|
color: var(--mute);
|
|
font: 400 17px var(--font-display);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.navrow a:hover {
|
|
color: var(--paper-dim);
|
|
}
|
|
|
|
.navrow a.active {
|
|
color: var(--paper);
|
|
border-bottom: 2px solid var(--paper);
|
|
margin-bottom: -1px;
|
|
}
|
|
|
|
.admin-page {
|
|
padding: 0 20px 40px;
|
|
}
|
|
|
|
.admin-page > .sec,
|
|
.admin-sheet .readers h2,
|
|
.admin-sheet .lanes h2 {
|
|
position: relative;
|
|
margin: 0;
|
|
padding: 26px 0 8px;
|
|
font: 500 11px/1 var(--font-mono);
|
|
letter-spacing: .2em;
|
|
text-transform: uppercase;
|
|
color: var(--mute-2);
|
|
}
|
|
|
|
.admin-page > .sec::before,
|
|
.admin-sheet .readers h2::before,
|
|
.admin-sheet .lanes h2::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 14px;
|
|
left: 0;
|
|
width: 34px;
|
|
height: 2px;
|
|
background: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .readers,
|
|
.admin-sheet .lanes {
|
|
margin: 0;
|
|
padding: 0 0 16px;
|
|
border-bottom: none;
|
|
}
|
|
|
|
.admin-sheet .readerlist,
|
|
.admin-sheet .lanelist {
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.admin-sheet .readerlist li,
|
|
.admin-sheet .lanelist li {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 4px 16px;
|
|
min-height: 48px;
|
|
padding: 10px 0;
|
|
border-top: 1px solid var(--rule);
|
|
}
|
|
|
|
.admin-sheet .reader-actions {
|
|
display: flex;
|
|
flex: 0 0 auto;
|
|
gap: 18px;
|
|
margin-left: auto;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.admin-sheet .reader-actions .ghost,
|
|
.admin-sheet .c-act .ghost {
|
|
font-size: 12px;
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .reader-actions .ghost.danger,
|
|
.admin-sheet .c-act .ghost.danger {
|
|
color: var(--danger);
|
|
}
|
|
|
|
.admin-sheet .readerlist form {
|
|
margin: 0;
|
|
}
|
|
|
|
.admin-sheet .lane-browser {
|
|
padding: 12px 0 0;
|
|
}
|
|
|
|
.admin-sheet .ghost.danger {
|
|
color: var(--danger);
|
|
}
|
|
|
|
.admin-sheet .ghost.danger:hover {
|
|
color: var(--danger);
|
|
border-bottom-color: var(--danger);
|
|
}
|
|
|
|
.admin-sheet .reader-id {
|
|
font: 500 15px/1.5 var(--font-mono);
|
|
letter-spacing: .01em;
|
|
color: var(--paper);
|
|
}
|
|
|
|
.admin-sheet .reader-sessions,
|
|
.admin-sheet .reader-sightings,
|
|
.admin-sheet .reader-blocked,
|
|
.admin-sheet .lane-fact,
|
|
.admin-sheet .lane-mark {
|
|
font: 500 13px/1.4 var(--font-mono);
|
|
letter-spacing: .06em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.admin-sheet .reader-sessions {
|
|
color: var(--paper-dim);
|
|
}
|
|
|
|
.admin-sheet .reader-sightings,
|
|
.admin-sheet .lane-fact {
|
|
color: var(--mute);
|
|
}
|
|
|
|
.admin-sheet .reader-blocked,
|
|
.admin-sheet .lane-mark {
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .lane-site {
|
|
font: 400 19px/1.2 var(--font-display);
|
|
color: var(--paper-dim);
|
|
}
|
|
|
|
.admin-sheet .lanelist li.attention .lane-site {
|
|
color: var(--danger);
|
|
}
|
|
|
|
/* A single grid keeps row rules continuous; cell padding supplies gutters. */
|
|
.admin-sheet .sechead {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
gap: 20px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.admin-sheet .sechead .statusline {
|
|
padding: 0 0 8px;
|
|
font-size: 11px;
|
|
letter-spacing: .14em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.admin-sheet .statusline {
|
|
margin: 0;
|
|
padding: 0 0 10px;
|
|
font: 500 12px/1 var(--font-mono);
|
|
letter-spacing: .04em;
|
|
color: var(--mute-2);
|
|
}
|
|
|
|
/* The verdict line is set in the data face, not the display face: it is
|
|
three counts, not a page title. The judgement is the only bright thing. */
|
|
.admin-sheet .verdict {
|
|
padding: 16px 0 12px;
|
|
border-bottom: 1px solid var(--rule);
|
|
font: 500 15px/1.6 var(--font-mono);
|
|
letter-spacing: .04em;
|
|
color: var(--mute);
|
|
}
|
|
|
|
.admin-sheet .verdict .attn {
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .verdict .counts b {
|
|
color: var(--paper);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.admin-sheet .tbl {
|
|
display: grid;
|
|
grid-template-columns: minmax(240px, 1fr) 156px 92px 110px 76px minmax(150px, 220px) 140px;
|
|
column-gap: 0;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
.admin-sheet .tbl .thead {
|
|
display: contents;
|
|
}
|
|
|
|
.admin-sheet .tbl .thead > * {
|
|
padding: 10px 14px 8px 0;
|
|
border-bottom: 1px solid var(--rule);
|
|
font: 500 12px/1 var(--font-mono);
|
|
letter-spacing: .12em;
|
|
text-transform: uppercase;
|
|
color: var(--mute-2);
|
|
}
|
|
|
|
.admin-sheet .tbl .trow {
|
|
display: contents;
|
|
}
|
|
|
|
.admin-sheet .tbl .trow > * {
|
|
padding: 11px 14px 11px 0;
|
|
border-bottom: 1px solid var(--rule);
|
|
font: 500 15px/1.5 var(--font-mono);
|
|
letter-spacing: .01em;
|
|
color: var(--paper-dim);
|
|
}
|
|
|
|
.admin-sheet .tbl .thead > *:last-child,
|
|
.admin-sheet .tbl .trow > *:last-child {
|
|
padding-right: 0;
|
|
}
|
|
|
|
.admin-sheet .tbl .c-title,
|
|
.admin-sheet .tbl .c-site {
|
|
font: 400 18px/1.35 var(--font-display);
|
|
letter-spacing: 0;
|
|
color: var(--paper);
|
|
}
|
|
|
|
.admin-sheet .tbl .c-title a:hover,
|
|
.admin-sheet .tbl .c-act .ghost:hover {
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .tbl .trow.attention .c-title {
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .tbl .c-ch,
|
|
.admin-sheet .tbl .c-rd {
|
|
text-align: right;
|
|
padding-right: 26px;
|
|
}
|
|
|
|
.admin-sheet .tbl .trow .c-note .mark {
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.admin-sheet .tbl .c-act {
|
|
text-align: right;
|
|
}
|
|
|
|
.admin-sheet .tbl .c-act .ghost + .ghost {
|
|
margin-left: 12px;
|
|
}
|
|
|
|
.admin-sheet .tbl .trow > .confirm-row {
|
|
grid-column: 1 / -1;
|
|
padding: 10px 12px;
|
|
border-bottom: none;
|
|
}
|
|
|
|
.admin-sheet .stats {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
|
|
margin: 4px 0 0;
|
|
border-bottom: 1px solid var(--rule);
|
|
}
|
|
|
|
.admin-sheet .stat {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: baseline;
|
|
gap: 16px;
|
|
padding: 11px 24px 11px 0;
|
|
}
|
|
|
|
.admin-sheet .stat .lbl {
|
|
font: 500 13px/1.3 var(--font-mono);
|
|
letter-spacing: .1em;
|
|
text-transform: uppercase;
|
|
color: var(--mute-2);
|
|
}
|
|
|
|
.admin-sheet .stat .fig {
|
|
font: 500 19px/1 var(--font-mono);
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--paper);
|
|
}
|
|
|
|
.admin-sheet .stat .fig.zero {
|
|
color: var(--mute);
|
|
}
|
|
|
|
.admin-sheet .stat a.fig {
|
|
/* The hover rule below sets the border on :hover only, which shifts the
|
|
row a pixel on hover; the transparent baseline holds the layout. */
|
|
border-bottom: 1px solid transparent;
|
|
}
|
|
|
|
.admin-sheet .stat a.fig:hover {
|
|
color: var(--patina);
|
|
border-bottom: 1px solid var(--patina);
|
|
}
|
|
|
|
.admin-sheet .mark,
|
|
.admin-sheet .mark-faint {
|
|
font: 500 13px/1 var(--font-mono);
|
|
letter-spacing: .06em;
|
|
text-transform: uppercase;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.admin-sheet .mark {
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .mark-faint {
|
|
color: var(--mute-2);
|
|
}
|
|
|
|
.admin-sheet .mark.mark-strong {
|
|
font-size: 13px;
|
|
letter-spacing: .14em;
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .mark.mark-strong::before {
|
|
content: "";
|
|
display: inline-block;
|
|
width: 7px;
|
|
height: 7px;
|
|
border-radius: 50%;
|
|
background: var(--patina);
|
|
margin-right: 8px;
|
|
vertical-align: .08em;
|
|
}
|
|
|
|
.admin-sheet .mark.bad {
|
|
color: var(--danger);
|
|
}
|
|
|
|
.admin-sheet .tbl.sites {
|
|
grid-template-columns: 170px repeat(4, 106px) minmax(180px, 1fr);
|
|
}
|
|
|
|
.admin-sheet .tbl.sites .c-site,
|
|
.admin-sheet .tbl.lanes .c-site {
|
|
font: 400 18px/1.35 var(--font-display);
|
|
letter-spacing: 0;
|
|
color: var(--paper);
|
|
}
|
|
|
|
.admin-sheet .tbl.sites .c-state {
|
|
color: var(--patina);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.admin-sheet .tbl.sites .c-state.bad,
|
|
.admin-sheet .tbl.lanes .c-skip .bad,
|
|
.admin-sheet .tbl.lanes .trow.attention .c-site {
|
|
color: var(--danger);
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .c-skip .ok {
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .tbl.sites .thead > *:nth-child(n+2):nth-child(-n+5),
|
|
.admin-sheet .tbl.sites .trow > *:nth-child(n+2):nth-child(-n+5) {
|
|
padding-right: 0;
|
|
text-align: center;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes {
|
|
grid-template-columns: 150px 62px 88px 66px 118px minmax(0, 1fr) 168px;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .c-skip {
|
|
white-space: normal;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .c-skip > * {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .c-ctrl {
|
|
text-align: right;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .thead > *:nth-child(n+2):nth-child(-n+4),
|
|
.admin-sheet .tbl.lanes .trow > *:nth-child(n+2):nth-child(-n+4) {
|
|
padding-right: 26px;
|
|
text-align: right;
|
|
}
|
|
|
|
.admin-sheet .tbl.series {
|
|
grid-template-columns: 150px 84px 104px 76px minmax(120px, 1fr) 212px;
|
|
row-gap: 4px;
|
|
}
|
|
|
|
.admin-sheet .tbl.series .thead > *:first-child {
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.admin-sheet .tbl.series .thead > *:last-child {
|
|
padding-right: 20px;
|
|
}
|
|
|
|
/* The site cell's colour is a class, never an inline style: site is
|
|
client-supplied and unvalidated, and a hostile value reaching a CSS
|
|
context would render ZgotmplZ, while an unknown class degrades to the
|
|
unstyled cell. */
|
|
.admin-sheet .tbl .c-site.site-asura {
|
|
color: var(--asura);
|
|
}
|
|
|
|
.admin-sheet .tbl .c-site.site-demonic {
|
|
color: var(--demonic);
|
|
}
|
|
|
|
.admin-sheet .tbl .c-site.site-comix {
|
|
color: var(--comix);
|
|
}
|
|
|
|
.admin-sheet .tbl .c-site.site-kagane {
|
|
color: var(--kagane);
|
|
}
|
|
|
|
.admin-sheet .tbl .c-site.site-novelfull {
|
|
color: var(--novelfull);
|
|
}
|
|
|
|
.admin-sheet .tbl .c-site.site-lightnovelworld {
|
|
color: var(--lightnovelworld);
|
|
}
|
|
|
|
.admin-sheet .tbl.series .trow {
|
|
display: grid;
|
|
grid-column: 1 / -1;
|
|
grid-template-columns: subgrid;
|
|
padding: 13px 20px 14px;
|
|
}
|
|
|
|
.admin-sheet .tbl.series .trow.band {
|
|
background: var(--hover);
|
|
}
|
|
|
|
.admin-sheet .tbl.series .trow > * {
|
|
padding: 0 14px 0 0;
|
|
border-bottom: none;
|
|
}
|
|
|
|
.admin-sheet .tbl.series .c-title {
|
|
display: flex;
|
|
grid-column: 1 / -1;
|
|
align-items: baseline;
|
|
gap: 16px;
|
|
padding: 0 0 4px;
|
|
}
|
|
|
|
.admin-sheet .tbl.series .c-title .mark {
|
|
margin-left: auto;
|
|
}
|
|
|
|
.admin-sheet .filterbar {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 14px 22px;
|
|
padding: 16px 0 14px;
|
|
border-bottom: 1px solid var(--rule);
|
|
}
|
|
|
|
.admin-sheet .fsel {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 10px;
|
|
}
|
|
|
|
.admin-sheet .fsel > span {
|
|
font: 500 11px/1 var(--font-mono);
|
|
letter-spacing: .14em;
|
|
text-transform: uppercase;
|
|
color: var(--mute-2);
|
|
}
|
|
|
|
.admin-sheet .fsel select,
|
|
.admin-sheet .pausebar select {
|
|
color-scheme: dark;
|
|
background: var(--ink);
|
|
border: none;
|
|
border-bottom: 1px solid var(--field-line);
|
|
color: var(--paper);
|
|
font: 400 16px/1.4 var(--font-display);
|
|
padding: 4px 4px 5px 0;
|
|
}
|
|
|
|
.admin-sheet .fsel select:hover,
|
|
.admin-sheet .pausebar select:hover {
|
|
border-bottom-color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .fsel select option,
|
|
.admin-sheet .pausebar select option {
|
|
background: var(--ink);
|
|
color: var(--paper);
|
|
}
|
|
|
|
.admin-sheet .segrow {
|
|
display: inline-flex;
|
|
gap: 2px;
|
|
}
|
|
|
|
.admin-sheet .segrow a {
|
|
padding: 6px 11px 7px;
|
|
border-bottom: 2px solid transparent;
|
|
color: var(--mute);
|
|
font: 500 14px/1 var(--font-mono);
|
|
}
|
|
|
|
.admin-sheet .segrow a.active {
|
|
border-bottom-color: var(--patina);
|
|
color: var(--patina);
|
|
}
|
|
|
|
.admin-sheet .listhead {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 12px;
|
|
padding: 16px 0 4px;
|
|
color: var(--paper);
|
|
font: 400 18px/1.2 var(--font-display);
|
|
}
|
|
|
|
.admin-sheet .listhead .lbl {
|
|
color: var(--mute);
|
|
}
|
|
|
|
.admin-sheet .listhead .lbl em {
|
|
color: var(--patina);
|
|
font-style: normal;
|
|
}
|
|
|
|
.admin-sheet .pager {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
padding: 14px 0 0;
|
|
color: var(--mute-2);
|
|
font: 500 11px/1 var(--font-mono);
|
|
letter-spacing: .14em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.admin-sheet .pager .pg {
|
|
color: var(--paper-dim);
|
|
}
|
|
|
|
.admin-sheet .pager .pg:hover {
|
|
color: var(--paper);
|
|
}
|
|
|
|
.admin-sheet .pager .pg.disabled {
|
|
color: var(--faint);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.admin-sheet .empty {
|
|
padding: 28px 0;
|
|
text-align: center;
|
|
}
|
|
|
|
.admin-sheet .empty strong {
|
|
color: var(--paper);
|
|
font: 400 20px var(--font-display);
|
|
}
|
|
|
|
.admin-sheet .empty p {
|
|
margin: 6px 0 0;
|
|
font: 14px/1.5 var(--font-body);
|
|
color: var(--mute);
|
|
}
|
|
|
|
.admin-sheet .confirm-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 10px 12px;
|
|
background: var(--danger-wash);
|
|
}
|
|
|
|
.admin-sheet .confirm-row span {
|
|
flex: 1 1 16ch;
|
|
color: var(--danger-soft);
|
|
font: 400 15px/1.3 var(--font-display);
|
|
}
|
|
|
|
.admin-sheet .confirm-row div {
|
|
display: flex;
|
|
flex: none;
|
|
gap: 12px;
|
|
margin-left: auto;
|
|
}
|
|
|
|
.admin-sheet .detail-back {
|
|
display: inline-block;
|
|
margin: 18px 0 0;
|
|
}
|
|
|
|
.admin-sheet .detail-title {
|
|
margin: 10px 0 2px;
|
|
color: var(--paper);
|
|
font: 400 28px/1.25 var(--font-display);
|
|
}
|
|
|
|
.admin-sheet .detail-key {
|
|
margin: 0;
|
|
color: var(--mute-2);
|
|
font: 500 11px/1.4 var(--font-mono);
|
|
letter-spacing: .08em;
|
|
}
|
|
|
|
.admin-sheet .detail-meta {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 4px 14px;
|
|
margin: 10px 0 0;
|
|
color: var(--mute-2);
|
|
font: 500 12px/1.5 var(--font-mono);
|
|
letter-spacing: .08em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.admin-sheet .cover {
|
|
width: 160px;
|
|
aspect-ratio: 3 / 4;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 18px 0 4px;
|
|
background: var(--hatch);
|
|
color: var(--mute-2);
|
|
font: 500 10px/1 var(--font-mono);
|
|
letter-spacing: .2em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.admin-sheet .detail-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 0 28px;
|
|
}
|
|
|
|
.admin-sheet .dform {
|
|
padding: 14px 0 0;
|
|
}
|
|
|
|
.admin-sheet .dform h3 {
|
|
margin: 0 0 4px;
|
|
color: var(--mute-2);
|
|
font: 500 10px/1 var(--font-mono);
|
|
letter-spacing: .2em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.admin-sheet .dform .field {
|
|
display: flex;
|
|
gap: 10px;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.admin-sheet .pausebar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
}
|
|
|
|
@media (max-width: 719px) {
|
|
.admin-sheet .topbar {
|
|
flex-wrap: wrap;
|
|
row-gap: 12px;
|
|
}
|
|
|
|
.admin-sheet .brand {
|
|
flex: 1 1 100%;
|
|
}
|
|
|
|
.admin-sheet .topbar-actions {
|
|
margin-left: auto;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 1019px) {
|
|
.admin-sheet .tbl.lanes {
|
|
display: block;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .thead {
|
|
display: none;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .trow {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: baseline;
|
|
gap: 4px 16px;
|
|
padding: 12px 0;
|
|
border-bottom: 1px solid var(--rule);
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .trow > * {
|
|
padding: 0;
|
|
border-bottom: none;
|
|
text-align: left;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .c-site {
|
|
width: 100%;
|
|
padding-bottom: 2px;
|
|
}
|
|
|
|
.admin-sheet .tbl.lanes .c-ctrl {
|
|
margin-left: auto;
|
|
text-align: right;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 899px) {
|
|
.admin-sheet .tbl,
|
|
.admin-sheet .tbl.lanes {
|
|
display: block;
|
|
}
|
|
|
|
.admin-sheet .tbl .thead {
|
|
display: none;
|
|
}
|
|
|
|
.admin-sheet .tbl .trow {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 2px 10px;
|
|
padding: 11px 0;
|
|
border-bottom: 1px solid var(--rule);
|
|
}
|
|
|
|
.admin-sheet .tbl .trow > * {
|
|
padding: 0;
|
|
border-bottom: none;
|
|
text-align: left;
|
|
}
|
|
|
|
.admin-sheet .tbl .c-ch,
|
|
.admin-sheet .tbl .c-rd {
|
|
padding-right: 0;
|
|
text-align: left;
|
|
}
|
|
|
|
.admin-sheet .tbl .c-title {
|
|
width: 100%;
|
|
padding-bottom: 2px;
|
|
}
|
|
|
|
.admin-sheet .tbl.series .trow {
|
|
display: flex;
|
|
}
|
|
|
|
.admin-sheet .tbl.series .trow > * {
|
|
padding: 0;
|
|
}
|
|
|
|
.admin-sheet .detail-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.admin-sheet .tbl .c-act {
|
|
margin-left: auto;
|
|
}
|
|
}
|