6.3 KB
raw
@use "../../base/styles/variables" as *;
@use "../../base/styles/mixins" as *;
/* ---------- page intro ---------- */
.health-lede {
max-width: 64ch;
margin: 10px 0 2px;
color: var(--ink-dim);
font-size: 0.9rem;
}
.health-asof {
@include eyebrow;
font-size: 0.6rem;
}
/* ---------- systems verdict (Phase 7) ----------
The distilled top read: a coloured dot + headline + one-line clause. Tones
reuse the semantic good/ok/bad tokens; filled live by the page script. */
.health-verdict {
display: flex;
align-items: center;
gap: 14px;
margin: 18px 0 6px;
padding: 14px 16px;
border: 1px solid var(--rule);
border-radius: var(--radius);
background: var(--surface);
}
.health-verdict[hidden] {
display: none;
}
.health-verdict__dot {
flex: none;
width: 11px;
height: 11px;
border-radius: 50%;
background: var(--ink-faint);
}
.health-verdict__head {
margin: 0;
font-size: 1.05rem;
font-weight: 600;
letter-spacing: -0.01em;
}
.health-verdict__detail {
margin: 2px 0 0;
color: var(--ink-dim);
font-size: 0.85rem;
}
.health-verdict[data-tone="ok"] {
border-color: var(--up-soft);
.health-verdict__dot { background: var(--up); }
}
.health-verdict[data-tone="warn"] {
border-color: var(--warn);
background: var(--warn-soft);
.health-verdict__dot { background: var(--warn); animation: pulse 1.2s ease-in-out infinite; }
}
.health-verdict[data-tone="bad"] {
border-color: var(--down);
background: var(--down-soft);
.health-verdict__dot { background: var(--down); }
}
/* ---------- "fetching now" banner ---------- */
.health-banner {
display: flex;
align-items: center;
gap: 10px;
margin: 16px 0 2px;
padding: 11px 14px;
border: 1px solid var(--warn);
border-radius: var(--radius);
background: var(--warn-soft);
font-weight: 500;
font-size: 0.9rem;
}
/* `.health-banner` sets display:flex, which would override the [hidden]
attribute's display:none — so re-assert it explicitly. */
.health-banner[hidden] {
display: none;
}
.health-banner__dot {
flex: none;
width: 9px;
height: 9px;
border-radius: 50%;
background: var(--warn);
animation: pulse 1.2s ease-in-out infinite;
}
/* ---------- status badge ---------- */
.badge {
@include eyebrow;
flex: none;
padding: 3px 8px;
border-radius: 999px;
font-size: 0.56rem;
}
.badge--ok {
color: var(--up);
background: var(--up-soft);
}
.badge--bad {
color: var(--down);
background: var(--down-soft);
}
.badge--warn {
color: var(--warn);
background: var(--warn-soft);
}
.badge--idle {
color: var(--ink-faint);
background: var(--well);
}
/* ---------- endpoints ----------
Phase 31: an explicit 3-up at desktop, 2-up at tablet, 1-up at phone,
so the SEC / Stooq / Yahoo cards always read in a tidy grid rather
than the previous auto-fit which dropped to 1-up at narrow desktops. */
.endpoint-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--sp-3);
}
@media (min-width: $bp-sm) {
.endpoint-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (min-width: $bp-md) {
.endpoint-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
.endpoint {
@include card;
padding: var(--sp-4);
}
.endpoint__head,
.job__head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
}
.endpoint__head h3,
.job__id h3 {
font-size: 1rem;
}
/* request-budget meter */
.meter {
margin: 16px 0 2px;
}
.meter__row {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 10px;
margin-bottom: 7px;
}
.meter__count {
font-size: 0.82rem;
font-weight: 600;
}
.meter__track {
height: 8px;
}
/* budget fill warms then reddens as the hourly ceiling nears */
.track__fill--warn {
background: var(--warn);
}
.track__fill--bad {
background: var(--down);
}
.meter__note {
margin-top: 7px;
color: var(--ink-faint);
font-size: 0.74rem;
}
/* ---------- key-value rows (shared by endpoints and jobs) ---------- */
.kvs {
margin-top: 12px;
}
.kv {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
padding: 7px 0;
border-top: 1px solid var(--rule);
font-size: 0.85rem;
}
.kv dt {
color: var(--ink-dim);
}
.kv dd {
font-weight: 600;
text-align: right;
}
.kv--err {
flex-direction: column;
align-items: stretch;
}
.kv--err dd {
font-weight: 400;
text-align: left;
color: var(--down);
word-break: break-word;
}
.kv--err .muted {
color: var(--ink-faint);
white-space: nowrap;
}
/* ---------- background jobs ---------- */
.job-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.job {
@include card;
padding: 14px 16px;
}
/* a job mid-fetch is rimmed in the working amber, echoing the banner */
.job--active {
border-color: var(--warn);
}
.job__id p {
margin-top: 3px;
color: var(--ink-dim);
font-size: 0.8rem;
}
/* ---------- activity log ---------- */
.log {
@include card;
padding: 2px 14px;
}
.logrows {
margin: 0;
padding: 0;
list-style: none;
}
.logrow {
display: flex;
align-items: baseline;
flex-wrap: wrap;
gap: var(--sp-1) var(--sp-3);
padding: 8px 0;
border-top: 1px solid var(--rule);
font-size: var(--fs-sm);
/* routine `ok` rows mute their entire body; the time, job, detail and
meta all drop a tier so the eye glides past them and lands on
anything coloured. */
color: var(--ink-faint);
}
.logrow:first-child {
border-top: none;
}
.logrow__time {
@include mono;
color: var(--ink-faint);
font-size: var(--fs-xs);
}
.logrow__job {
@include mono;
min-width: 6ch;
font-weight: 600;
color: var(--ink-dim);
font-size: var(--fs-xs);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.logrow__detail {
flex: 1 1 14ch;
min-width: 0;
color: var(--ink-dim);
}
/* a failed fetch should catch the eye down the tail; the row's job pill
and detail both pop, the time/meta stay quiet. */
.logrow--bad .logrow__job {
color: var(--down);
}
.logrow--bad .logrow__detail {
color: var(--down);
font-weight: 500;
}
.logrow__meta {
color: var(--ink-faint);
font-size: var(--fs-2xs);
}
/* ---------- empty states ---------- */
.health-empty {
@include card;
padding: 22px;
color: var(--ink-dim);
font-size: 0.9rem;
text-align: center;
}
/* ---------- desktop ---------- */
@media (min-width: $bp-md) {
.logrow__job {
min-width: 9ch;
}
}