0.2.75
This commit is contained in:
+513
-105
@@ -22,7 +22,12 @@
|
||||
which is what lets a page distinguish one kind of thing from another without every
|
||||
coloured element reading as a warning. Green means good, amber means look, red means
|
||||
wrong; the other three mean nothing at all, which is the point. A tone is passed, never
|
||||
derived: the library is teal, a person violet, a television blue, on every page. */
|
||||
derived: the library is teal, a person violet, a television blue, on every page.
|
||||
|
||||
Beside the accent is one quieter green, `idle`, which is not a seventh meaning but the
|
||||
accent's meaning held at lower confidence: good, but not this minute. It exists so that
|
||||
"fine and not connected right now" can stop borrowing amber, which is reserved for
|
||||
something an operator should look at. Nothing derives it either. */
|
||||
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
@@ -41,6 +46,13 @@
|
||||
--accent: #2ea043;
|
||||
--accent-ink: #56d364;
|
||||
--accent-wash: rgba(46, 160, 67, 0.16);
|
||||
/* The quiet green: fine, but not this minute. Same hue as the accent and deliberately
|
||||
duller, because it is the accent's own meaning at lower confidence rather than a
|
||||
verdict of its own — a television in ordinary use that happens to be switched off is
|
||||
not something an operator has to do anything about, and amber said it was. */
|
||||
--idle: #4a8f60;
|
||||
--idle-ink: #86c79a;
|
||||
--idle-wash: rgba(74, 143, 96, 0.13);
|
||||
--danger: #e5534b;
|
||||
--danger-ink: #ff9b94;
|
||||
--danger-wash: rgba(229, 83, 75, 0.13);
|
||||
@@ -1030,6 +1042,10 @@ a.tile:hover {
|
||||
background: var(--accent-wash);
|
||||
color: var(--accent-ink);
|
||||
}
|
||||
.glyph[data-tone="idle"] {
|
||||
background: var(--idle-wash);
|
||||
color: var(--idle-ink);
|
||||
}
|
||||
.glyph[data-tone="warn"] {
|
||||
background: var(--warn-wash);
|
||||
color: var(--warn-ink);
|
||||
@@ -1078,6 +1094,11 @@ a.tile:hover {
|
||||
background: var(--accent-wash);
|
||||
color: var(--accent-ink);
|
||||
}
|
||||
.tag[data-tone="idle"] {
|
||||
border-color: rgba(74, 143, 96, 0.35);
|
||||
background: var(--idle-wash);
|
||||
color: var(--idle-ink);
|
||||
}
|
||||
.tag[data-tone="warn"] {
|
||||
border-color: rgba(239, 196, 107, 0.35);
|
||||
background: var(--warn-wash);
|
||||
@@ -1119,6 +1140,9 @@ a.tile:hover {
|
||||
.chip[data-tone="ok"] {
|
||||
color: var(--accent-ink);
|
||||
}
|
||||
.chip[data-tone="idle"] {
|
||||
color: var(--idle-ink);
|
||||
}
|
||||
.chip[data-tone="warn"] {
|
||||
color: var(--warn-ink);
|
||||
}
|
||||
@@ -1744,6 +1768,109 @@ select {
|
||||
|
||||
/* ---------- log / code ---------- */
|
||||
|
||||
/* The log table.
|
||||
|
||||
Six columns, in the order the questions are asked: when, how bad, which part of the
|
||||
server, what happened, did it work, how long did it take. The columns are the whole
|
||||
design — an operator learns where to look once and then reads down a column rather than
|
||||
across a line, which is what makes thirty seconds of watching this page worth anything.
|
||||
|
||||
Monospace is spent deliberately rather than applied to the row. The time, the method,
|
||||
the status and the duration are values to be compared down a column and are set in it;
|
||||
the summary is a sentence and is set in the sans face, because a sentence in monospace
|
||||
is slower to read and looks like a dump of something. */
|
||||
|
||||
.logbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.logbar-filters {
|
||||
display: flex;
|
||||
flex: 1 1 520px;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
.logbar-filters select {
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
height: 30px;
|
||||
padding: 0 26px 0 9px;
|
||||
font-size: 12px;
|
||||
}
|
||||
/* The actions are secondary to the filters and are marked so by weight, not by distance:
|
||||
the previous bar gave Pause and Export the same prominence as the controls that decide
|
||||
what the table contains. */
|
||||
.logbar-actions {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
gap: 6px;
|
||||
margin-left: auto;
|
||||
}
|
||||
.logsearch {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex: 1 1 260px;
|
||||
align-items: center;
|
||||
min-width: 200px;
|
||||
}
|
||||
.logsearch svg {
|
||||
position: absolute;
|
||||
left: 9px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
color: var(--quiet);
|
||||
pointer-events: none;
|
||||
}
|
||||
.logsearch input {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
padding-left: 28px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* One chip per narrowing in force. They are the only place a filter can be removed one at
|
||||
a time, which is what makes drilling in by clicking a value in the table reversible. */
|
||||
.logchips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.logchip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
height: 24px;
|
||||
padding: 0 8px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 999px;
|
||||
background: var(--surface-lift);
|
||||
color: var(--muted);
|
||||
font: 500 11px/1 var(--sans);
|
||||
}
|
||||
.logchip svg {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
opacity: .7;
|
||||
}
|
||||
.logchip:hover:not(:disabled) {
|
||||
border-color: var(--danger);
|
||||
background: var(--danger-wash);
|
||||
color: var(--danger-ink);
|
||||
}
|
||||
.logchip-clear {
|
||||
border-style: dashed;
|
||||
color: var(--quiet);
|
||||
}
|
||||
|
||||
.logshell {
|
||||
position: relative;
|
||||
}
|
||||
.logview {
|
||||
height: 62vh;
|
||||
min-height: 320px;
|
||||
@@ -1751,17 +1878,24 @@ select {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-sm);
|
||||
background: #080a0e;
|
||||
font: 12px/1.6 var(--mono);
|
||||
font: 12px/1.5 var(--sans);
|
||||
contain: layout paint style;
|
||||
}
|
||||
.loghead,
|
||||
.logrow {
|
||||
display: grid;
|
||||
grid-template-columns:
|
||||
92px 52px minmax(150px, 190px) minmax(240px, 1fr)
|
||||
minmax(96px, 150px) 68px;
|
||||
gap: 12px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
.loghead {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
display: grid;
|
||||
grid-template-columns: 150px 46px minmax(180px, 1fr) minmax(240px, 2fr);
|
||||
gap: 12px;
|
||||
padding: 7px 12px;
|
||||
z-index: 2;
|
||||
align-items: center;
|
||||
height: 31px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: #10131a;
|
||||
color: var(--quiet);
|
||||
@@ -1769,142 +1903,413 @@ select {
|
||||
font-weight: 700;
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
min-width: 760px;
|
||||
min-width: 900px;
|
||||
}
|
||||
.loghead > :last-child {
|
||||
text-align: right;
|
||||
}
|
||||
.logbody {
|
||||
position: relative;
|
||||
min-width: 760px;
|
||||
min-width: 900px;
|
||||
}
|
||||
.logline {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
padding: 3px 12px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.03);
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.logline[data-virtual="true"] {
|
||||
|
||||
/* The date is a divider between days rather than a column repeated on every row. A log
|
||||
watched live is almost always one day; printing the date 20,000 times to cover the
|
||||
handful of rows where it changes is the trade the compact timestamp exists to avoid. */
|
||||
.logday {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 150px 46px minmax(180px, 1fr) minmax(240px, 2fr);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 48px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
white-space: nowrap;
|
||||
height: 26px;
|
||||
padding: 0 12px;
|
||||
background: linear-gradient(to bottom, rgba(255, 255, 255, .03), transparent);
|
||||
color: var(--quiet);
|
||||
font: 700 10px/1 var(--sans);
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.logday span {
|
||||
padding-right: 10px;
|
||||
background: #080a0e;
|
||||
}
|
||||
.logday::after {
|
||||
content: '';
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--line-soft);
|
||||
}
|
||||
|
||||
.logrow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, .03);
|
||||
contain: strict;
|
||||
}
|
||||
.logline:hover {
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
.logrow:hover {
|
||||
background: rgba(255, 255, 255, .035);
|
||||
}
|
||||
.logline time {
|
||||
flex: 0 0 auto;
|
||||
.logrow[data-selected] {
|
||||
background: var(--accent-wash);
|
||||
}
|
||||
/* A failure is marked on the row and not only in a column, because the thing an operator
|
||||
is scanning for is a row, and a hairline at the start of one is found faster than a word
|
||||
two thirds of the way along it. INFO is deliberately unmarked: most of the table is INFO
|
||||
and a mark every row carries is a mark that says nothing. */
|
||||
.logrow[data-level="ERROR"] {
|
||||
box-shadow: inset 2px 0 0 var(--danger);
|
||||
background: rgba(229, 83, 75, .05);
|
||||
}
|
||||
.logrow[data-level="WARN"] {
|
||||
box-shadow: inset 2px 0 0 var(--warn);
|
||||
}
|
||||
|
||||
.logrow-time {
|
||||
color: var(--quiet);
|
||||
font: 11px/1 var(--mono);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.logline time small {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 10px;
|
||||
}
|
||||
.logline .lvl {
|
||||
flex: 0 0 46px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.logline[data-level="ERROR"] .lvl {
|
||||
color: var(--danger-ink);
|
||||
}
|
||||
.logline[data-level="WARN"] .lvl {
|
||||
color: var(--warn-ink);
|
||||
}
|
||||
.logline[data-level="INFO"] .lvl {
|
||||
color: var(--info-ink);
|
||||
}
|
||||
.logline[data-level="DEBUG"] .lvl {
|
||||
color: var(--quiet);
|
||||
}
|
||||
.logline .msg {
|
||||
flex: 1 1 auto;
|
||||
|
||||
/* Every structured value in the table is also the control that filters to it. They are
|
||||
buttons rather than links because nothing navigates: the table narrows in place. */
|
||||
.logfacet {
|
||||
height: auto;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.logline .attrs {
|
||||
color: var(--quiet);
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
.logline {
|
||||
display: grid;
|
||||
grid-template-columns: 150px 46px minmax(180px, 1fr) minmax(240px, 2fr);
|
||||
}
|
||||
}
|
||||
.logline .attrs b {
|
||||
color: var(--muted);
|
||||
font-weight: 400;
|
||||
}
|
||||
.logattrs-button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--quiet);
|
||||
background: none;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.logattrs-button:hover:not(:disabled) {
|
||||
.logfacet:hover:not(:disabled) {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--text);
|
||||
background: none;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
.logattrs-button:focus-visible {
|
||||
.logfacet:focus-visible {
|
||||
outline: 1px solid var(--accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.log-inspector {
|
||||
|
||||
.logrow-level {
|
||||
color: var(--quiet);
|
||||
font: 700 10px/1 var(--sans);
|
||||
letter-spacing: .06em;
|
||||
}
|
||||
.logrow-level[data-level="ERROR"] { color: var(--danger-ink); }
|
||||
.logrow-level[data-level="WARN"] { color: var(--warn-ink); }
|
||||
.logrow-level[data-level="INFO"] { color: var(--muted); }
|
||||
.logrow-level[data-level="DEBUG"],
|
||||
.logrow-level[data-level="TRACE"] { color: var(--quiet); }
|
||||
|
||||
/* Service and component. The service is the recognisable half — one word, upper case,
|
||||
always the same colour for the same subsystem — and the component sits beside it in the
|
||||
ordinary text colour, so the pair reads as a place rather than as two tags. The tones
|
||||
are the console's secondary palette only: green, amber and red mean good, look and wrong
|
||||
on every other page and must not start meaning "playback" on this one. */
|
||||
.logrow-place {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 5px;
|
||||
min-width: 0;
|
||||
}
|
||||
.logrow-service {
|
||||
flex: 0 0 auto;
|
||||
max-width: 96px;
|
||||
overflow: hidden;
|
||||
color: var(--quiet);
|
||||
font: 700 10px/1.4 var(--sans);
|
||||
letter-spacing: .07em;
|
||||
text-overflow: ellipsis;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.logrow-service[data-tone="info"] { color: var(--info-ink); }
|
||||
.logrow-service[data-tone="note"] { color: var(--note-ink); }
|
||||
.logrow-service[data-tone="data"] { color: var(--data-ink); }
|
||||
.logrow-service[data-tone="idle"] { color: var(--idle-ink); }
|
||||
.logrow-service[data-tone="quiet"] { color: var(--muted); }
|
||||
.logrow-sep {
|
||||
flex: 0 0 auto;
|
||||
color: var(--line);
|
||||
}
|
||||
.logrow-component {
|
||||
flex: 1 1 auto;
|
||||
color: var(--quiet);
|
||||
font-size: 11.5px;
|
||||
}
|
||||
|
||||
/* The summary is the row. It is a button because selecting the row is what opens the
|
||||
record, and the whole width of the column should be the target. */
|
||||
.logrow-summary {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
background: none;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
}
|
||||
.logrow-summary:hover:not(:disabled) {
|
||||
border: 0;
|
||||
background: none;
|
||||
}
|
||||
.logrow-summary:focus-visible {
|
||||
outline: 1px solid var(--accent);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
.logrow-line {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
.logrow-action {
|
||||
flex: 0 0 auto;
|
||||
color: var(--muted);
|
||||
font: 600 10.5px/1.4 var(--mono);
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
.logrow-action[data-method="POST"],
|
||||
.logrow-action[data-method="PUT"],
|
||||
.logrow-action[data-method="PATCH"] { color: var(--info-ink); }
|
||||
.logrow-action[data-method="DELETE"] { color: var(--danger-ink); }
|
||||
.logrow-text {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: var(--text);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* The reason a failure needs no drawer. */
|
||||
.logrow-error {
|
||||
overflow: hidden;
|
||||
color: var(--danger-ink);
|
||||
font-size: 11px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.logrow-context {
|
||||
overflow: hidden;
|
||||
color: var(--quiet);
|
||||
font-size: 11px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* A result is a word, not a badge. A success is understated to the point of being ignorable
|
||||
— which is the correct amount of attention for the four hundredth 200 in a row — and only
|
||||
a failure is given a fill. */
|
||||
.logrow-result {
|
||||
min-width: 0;
|
||||
}
|
||||
.logrow-verdict {
|
||||
display: inline-block;
|
||||
max-width: 100%;
|
||||
color: var(--quiet);
|
||||
font: 500 11px/1.5 var(--mono);
|
||||
}
|
||||
.logrow-verdict[data-tone="ok"] { color: var(--muted); }
|
||||
.logrow-verdict[data-tone="info"] { color: var(--info-ink); }
|
||||
.logrow-verdict[data-tone="data"] { color: var(--data-ink); }
|
||||
.logrow-verdict[data-tone="warn"],
|
||||
.logrow-verdict[data-tone="bad"] {
|
||||
padding: 1px 6px;
|
||||
border-radius: var(--radius-xs);
|
||||
font-weight: 600;
|
||||
}
|
||||
.logrow-verdict[data-tone="warn"] {
|
||||
background: var(--warn-wash);
|
||||
color: var(--warn-ink);
|
||||
}
|
||||
.logrow-verdict[data-tone="bad"] {
|
||||
background: var(--danger-wash);
|
||||
color: var(--danger-ink);
|
||||
}
|
||||
|
||||
.logrow-duration {
|
||||
color: var(--quiet);
|
||||
font: 11px/1 var(--mono);
|
||||
font-variant-numeric: tabular-nums;
|
||||
text-align: right;
|
||||
}
|
||||
.logrow-duration[data-tone="warn"] { color: var(--warn-ink); }
|
||||
.logrow-duration[data-tone="bad"] {
|
||||
color: var(--danger-ink);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Offered only once the operator has left the tail, which is the only time following the
|
||||
log automatically would be taking the page away from them. */
|
||||
.logtail {
|
||||
position: absolute;
|
||||
right: 18px;
|
||||
bottom: 14px;
|
||||
z-index: 3;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
height: 28px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--accent);
|
||||
border-radius: 999px;
|
||||
background: var(--surface-lift);
|
||||
color: var(--accent-ink);
|
||||
font: 600 11px/1 var(--sans);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, .5);
|
||||
}
|
||||
.logtail svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.logtail:hover:not(:disabled) {
|
||||
border-color: var(--accent);
|
||||
background: var(--accent-wash);
|
||||
color: var(--accent-ink);
|
||||
}
|
||||
|
||||
/* The drawer answers "exactly how and why". Sections rather than one alphabetical list,
|
||||
and a field with no value is omitted rather than printed as `unknown`. */
|
||||
.logdrawer {
|
||||
margin-top: 12px;
|
||||
padding: 12px;
|
||||
padding: 14px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--surface);
|
||||
}
|
||||
.log-inspector-head {
|
||||
.logdrawer-head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.log-inspector-head > div {
|
||||
.logdrawer-head > div:first-child {
|
||||
min-width: 0;
|
||||
}
|
||||
.log-inspector-head b,
|
||||
.log-inspector-head span {
|
||||
.logdrawer-head b {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
font-size: 14px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.log-inspector-head span {
|
||||
margin-top: 3px;
|
||||
.logdrawer-place {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 5px;
|
||||
margin: 0;
|
||||
color: var(--quiet);
|
||||
font: 11px/1.5 var(--mono);
|
||||
font-size: 11px;
|
||||
}
|
||||
.log-inspector dl {
|
||||
.logdrawer-error {
|
||||
margin: 6px 0 0;
|
||||
color: var(--danger-ink);
|
||||
font: 12px/1.5 var(--mono);
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.logdrawer-actions {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
gap: 6px;
|
||||
}
|
||||
.logdrawer-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(130px, max-content) minmax(0, 1fr);
|
||||
gap: 5px 14px;
|
||||
margin: 12px 0 0;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--line);
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
gap: 16px 24px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.logdrawer-section h4 {
|
||||
margin: 0 0 6px;
|
||||
color: var(--quiet);
|
||||
font: 700 10px/1 var(--sans);
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.logdrawer-section dl {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(88px, max-content) minmax(0, 1fr);
|
||||
gap: 4px 12px;
|
||||
margin: 0;
|
||||
font: 12px/1.5 var(--mono);
|
||||
}
|
||||
.log-inspector dt { color: var(--muted); }
|
||||
.log-inspector dd { min-width: 0; margin: 0; overflow-wrap: anywhere; }
|
||||
.logdrawer-section dt { color: var(--muted); }
|
||||
.logdrawer-section dd { min-width: 0; margin: 0; overflow-wrap: anywhere; }
|
||||
.logdrawer-raw {
|
||||
margin-top: 14px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.logdrawer-raw summary {
|
||||
cursor: pointer;
|
||||
color: var(--quiet);
|
||||
font: 700 10px/1 var(--sans);
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.logdrawer-raw pre {
|
||||
max-height: 320px;
|
||||
margin: 10px 0 0;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-xs);
|
||||
background: #080a0e;
|
||||
font: 11px/1.6 var(--mono);
|
||||
}
|
||||
|
||||
/* Columns are given up in the order they are least missed: the duration first, since it is
|
||||
the only one of the six whose absence costs nothing to understanding what happened, and
|
||||
the timestamp after it. Level, service and the summary are never dropped — a log that
|
||||
cannot say how bad, where, or what is not a log. */
|
||||
@media (max-width: 1180px) {
|
||||
.loghead,
|
||||
.logrow {
|
||||
grid-template-columns: 84px 46px minmax(130px, 170px) minmax(200px, 1fr) minmax(88px, 130px);
|
||||
gap: 10px;
|
||||
}
|
||||
.loghead > :last-child,
|
||||
.logrow-duration {
|
||||
display: none;
|
||||
}
|
||||
.loghead,
|
||||
.logbody {
|
||||
min-width: 640px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.loghead,
|
||||
.logrow {
|
||||
grid-template-columns: 46px minmax(110px, 140px) minmax(180px, 1fr) minmax(72px, 110px);
|
||||
gap: 8px;
|
||||
}
|
||||
.loghead > :first-child,
|
||||
.logrow-time {
|
||||
display: none;
|
||||
}
|
||||
.loghead,
|
||||
.logbody {
|
||||
min-width: 520px;
|
||||
}
|
||||
}
|
||||
.logdetails {
|
||||
min-width: 0;
|
||||
}
|
||||
@@ -2243,7 +2648,11 @@ pre.code {
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
/* The presence dot: three-valued, and the tone is passed rather than derived. */
|
||||
/* The presence dot: four-valued, and the tone is passed rather than derived. The two
|
||||
greens are the point — one set is connected now and the other was an hour ago, and both
|
||||
are fine, so they read as the same answer at two strengths rather than as two answers.
|
||||
The dot is 7px and colour alone is never the whole signal here: every one of these
|
||||
carries the wording in its title. */
|
||||
.dot-state {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
@@ -2254,6 +2663,9 @@ pre.code {
|
||||
.dot-state[data-tone="ok"] {
|
||||
background: var(--accent);
|
||||
}
|
||||
.dot-state[data-tone="idle"] {
|
||||
background: var(--idle);
|
||||
}
|
||||
.dot-state[data-tone="warn"] {
|
||||
background: var(--warn);
|
||||
}
|
||||
@@ -2873,18 +3285,14 @@ details summary {
|
||||
min-height: 60px;
|
||||
padding: 13px 0;
|
||||
}
|
||||
.loghead,
|
||||
.logbody {
|
||||
min-width: 680px;
|
||||
}
|
||||
.loghead,
|
||||
.logline[data-virtual="true"] {
|
||||
grid-template-columns: 128px 44px minmax(160px, 1fr) minmax(220px, 1.4fr);
|
||||
gap: 10px;
|
||||
}
|
||||
/* The column collapse itself is width-driven and lives beside the table's own rules;
|
||||
what a touch device needs on top of it is room to scroll and controls it can reach. */
|
||||
.logview {
|
||||
height: min(66dvh, 720px);
|
||||
}
|
||||
.logbar-actions {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 820px) {
|
||||
|
||||
Reference in New Issue
Block a user