8e4fa6448e
Closes #136. Spec #136 end to end: `finished` becomes a fact about the Series, written only by the owner, and the reader-facing Lifecycle bucket is gone. ## What landed - **#157** — `series.finished_at bigint NOT NULL DEFAULT 0` plus the migration whose statement order is load-bearing (seed from the buckets, then flip them); both Lane queries lose the `HAVING COUNT(*) FILTER (WHERE b.status <> 'finished')` clause and gate on `finished_at = 0` instead, with the due-query/eligible-count force asymmetry kept deliberate and commented; `StatusFinished`, its API special-case 400, the web tab and the templates' Finished bucket deleted. - **#158** — owner Finish control on the Series detail page: confirm-gated finish, instant un-finish, admin accent (never ember, nothing is destroyed), `Store.SetSeriesFinished`, the two routes behind the owner gate, and the state displayed on the list row without offering the control there. - **#160** — reader side: derived `finished` bool on the flat Bookmark (`s.finished_at > 0`), rendered as a text-only label in both userscripts and on the web card; read-only inbound by omission from `Upsert`'s explicit `series` column list, same mechanism that already protects `cover`. - **#161** — glossary and the stale Reader-count divergence note catch up. - **#159** — `finished` joins the admin filter vocabulary (predicate `finished_at > 0`, label `Finished`, own aggregate count, figure last in the stats block as informational); the four clock-driven hygiene predicates (stale, never-checked, no-cover, no-chapter) exclude finished Series while unpollable, orphan and sighting-raised deliberately do not. ## Verification `go vet ./...` and `go test ./...` green on the merged branch (Docker-backed, throwaway `postgres:17-alpine` per package). Each ticket also passed a two-axis review (spec + standards) on its own branch before merge. Reviewed-on: #163 Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com> Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
875 lines
16 KiB
CSS
875 lines
16 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;
|
|
}
|
|
|
|
/* The finish confirm is the one calm row on the admin sheet: a reversible
|
|
move wears the recessed ash, never the remove wash above, and its
|
|
affirmative takes the sheet's patina accent (issue #158). */
|
|
.admin-sheet .confirm-row.calm {
|
|
background: var(--ash);
|
|
}
|
|
|
|
.admin-sheet .confirm-row.calm span {
|
|
color: var(--paper-dim);
|
|
}
|
|
|
|
.admin-sheet .confirm-row.calm .go {
|
|
background: var(--patina);
|
|
color: var(--ink);
|
|
}
|
|
|
|
.admin-sheet .tbl.series .row-msg {
|
|
grid-column: 1 / -1;
|
|
margin-top: 6px;
|
|
color: var(--danger-soft);
|
|
font: 400 13px/1.4 var(--font-body);
|
|
}
|
|
|
|
.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 .dform input {
|
|
min-width: 0;
|
|
padding: 8px 10px;
|
|
border: 1px solid var(--field-line);
|
|
background: var(--ink);
|
|
color: var(--paper);
|
|
font: 500 14px var(--font-mono);
|
|
outline: none;
|
|
}
|
|
/* Focus follows the chapter form's idiom — paper, not heat: a red border on
|
|
a valid number field reads as "invalid". */
|
|
.admin-sheet .dform input:focus {
|
|
border-color: var(--paper);
|
|
}
|
|
.admin-sheet .dform .hint {
|
|
margin: 0;
|
|
color: var(--mute-2);
|
|
font: 500 12px/1.4 var(--font-mono);
|
|
letter-spacing: .04em;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
}
|