mirror of
https://github.com/caiwx86/small-packages.git
synced 2026-11-04 18:13:56 +08:00
252 lines
14 KiB
CSS
252 lines
14 KiB
CSS
@layer page {
|
|
/* Every !important here fights an inline style= from luci-mod-status's 29_ports.js — page is
|
|
* the last layer, so a flag fighting only another footstrap rule is not kept. docs/css.md
|
|
* "Overview: the port-tile reskin". */
|
|
|
|
/* decoration only, glyph aria-hidden — docs/css.md "Overview: the disclosure pill, the grid,
|
|
* and the duplicate heading" */
|
|
.cbi-title .label[data-indicator="poll-status"] {
|
|
font-size: 0;
|
|
width: 16px;
|
|
height: 16px;
|
|
padding: 0;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: none;
|
|
border: 0;
|
|
color: var(--fs-faint);
|
|
}
|
|
|
|
/* two selectors: wrapper differs by release (25.12 .cbi-title>h3, 24.10 bare h3); matches 0 of
|
|
* 14 h3 on live 24.10.8 — not dead there, that release has no hide/show control */
|
|
:is(.cbi-title h3, .cbi-section > h3)[role="button"] {
|
|
cursor: pointer;
|
|
-webkit-user-select: none; /* every shipped Safari/iOS reads only the prefixed form */
|
|
user-select: none; /* rapid header clicks read as a double-click and select the card */
|
|
border-radius: var(--fs-radius-sm);
|
|
}
|
|
:is(.cbi-title h3, .cbi-section > h3)[role="button"]:focus-visible {
|
|
outline: none;
|
|
box-shadow: var(--fs-focus-ring);
|
|
}
|
|
|
|
/* every page-scoped selector below anchors on :where(#view)[data-page="…"], not bare #view —
|
|
* docs/css.md ":where(#view), not bare #view". */
|
|
|
|
/* drops what hideEmptyCard() marked (a stock include with nothing to show) and the stock <h2> duplicate of the chrome's title, the latter via .fs-content not #view */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section.fs-ovl-empty,
|
|
.fs-content[data-page="admin-status-overview"] h2[name="content"] { display: none; }
|
|
.fs-ovl {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: var(--fs-space-4);
|
|
margin-bottom: var(--fs-card-gap); /* match stock .cbi-section spacing below the grid */
|
|
}
|
|
/* min-width:0 so an item shrinks to its TRACK, not its content's min-width — docs/css.md above */
|
|
.fs-ovl > .fs-ovl-sys,
|
|
.fs-ovl > .fs-ovl-mem,
|
|
.fs-ovl > .fs-ovl-sto { margin: 0; min-width: 0; }
|
|
.fs-ovl > .fs-ovl-sys { grid-column: 1; grid-row: 1 / 3; }
|
|
.fs-ovl > .fs-ovl-mem { grid-column: 2; grid-row: 1; }
|
|
.fs-ovl > .fs-ovl-sto { grid-column: 2; grid-row: 2; }
|
|
@container fs-view (max-width: 800px) {
|
|
.fs-ovl { grid-template-columns: 1fr; }
|
|
.fs-ovl > .fs-ovl-sys,
|
|
.fs-ovl > .fs-ovl-mem,
|
|
.fs-ovl > .fs-ovl-sto { grid-column: 1; grid-row: auto; }
|
|
}
|
|
|
|
/* Port status reskin. Scoped to :has(img[src*="/port_"]) — do not unscope, Network/Wireless
|
|
* reuse the same .ifacebox classes. Child order: 1 name-head, 2 speed, 3 zone bar, 4 traffic. */
|
|
:where(#view)[data-page="admin-status-overview"] div:has(> .ifacebox img[src*="/port_"]) {
|
|
/* 8px not 10: an 11-port switch in a 1190px column fits 11 cards only at 8px gap */
|
|
gap: var(--fs-space-2);
|
|
grid-template-columns: repeat(auto-fit, minmax(calc(76px * var(--fs-density-type) + var(--fs-space-3) * 2), 1fr)) !important;
|
|
margin-bottom: 0 !important;
|
|
}
|
|
/* flex-wrap, not a grid+@container threshold (issue #7) — docs/css.md above */
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) {
|
|
margin: 0 !important;
|
|
min-width: 0 !important;
|
|
/* caps a 2-port device growing into two half-page cards; fights stock's inline max-width */
|
|
max-width: 200px !important;
|
|
/* ImmortalWrt 25.12 sets inline margin/width instead of stock's min/max pair */
|
|
width: auto !important;
|
|
/* same fork centres the grid CONTAINER; *-self wins over parent *-items, no flag needed */
|
|
justify-self: stretch;
|
|
align-self: stretch;
|
|
text-align: start;
|
|
background: var(--fs-panel2);
|
|
border: var(--fs-hairline);
|
|
border-radius: var(--fs-radius-lg);
|
|
padding: var(--fs-space-1-5) var(--fs-space-3);
|
|
/* no container-type: broke poll-replaced cards before containment resolved (bisected) */
|
|
display: flex;
|
|
/* NOT redundant: base/95-luci.css sets .ifacebox inline-flex column */
|
|
flex-direction: row;
|
|
flex-wrap: wrap;
|
|
/* row-gap 0: every row carries its own spacing already (zone bar margins, name line box) */
|
|
column-gap: var(--fs-space-2); row-gap: 0;
|
|
align-items: baseline;
|
|
}
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) img { display: none; }
|
|
/* two stock border-bottoms stack around the colour line; drop both */
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) .ifacebox-head { border-bottom: 0; border-radius: 0; }
|
|
/* zone-colour bar (WAN red/LAN green, issue #13); order places it between name and traffic.
|
|
* No overflow/border-radius: both clip the absolutely-positioned .cbi-tooltip */
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) > .ifacebox-head:nth-child(3) {
|
|
order: 1;
|
|
flex: 0 0 100%;
|
|
width: 100%;
|
|
margin: var(--fs-space-0-5) 0 var(--fs-space-1);
|
|
}
|
|
/* no status dot: speed + zone bar report carrier */
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) > .ifacebox-head:first-child {
|
|
flex: 0 0 auto;
|
|
width: 100%;
|
|
/* one line (nowrap from .ifacebox), ellipsised: without min-width: 0 a long name sets every tile's min width */
|
|
min-width: 0;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
line-height: var(--fs-leading);
|
|
font-size: var(--fs-type); color: var(--fs-text);
|
|
}
|
|
/* no link (*_down.svg): dim to match the dim speed and faded zone bar */
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]):has(img[src*="_down.svg"]) > .ifacebox-head:first-child { color: var(--fs-dim); }
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) > .ifacebox-body:nth-child(2) {
|
|
order: 2; /* below the zone-colour line (child 3, order 1) */
|
|
font-size: var(--fs-type); font-weight: var(--fs-weight); color: var(--fs-good); text-align: start;
|
|
/* margin-left:auto forces its own row in Chrome's line-break count; flex-grow instead */
|
|
flex: 1 1 auto; white-space: normal; overflow-wrap: break-word;
|
|
}
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) > .ifacebox-body:nth-child(2) br { display: none; }
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]):has(img[src*="_down.svg"]) > .ifacebox-body:nth-child(2) { color: var(--fs-dim); }
|
|
/* traffic: tx over rx, as stock's <br> leaves them — CSS cannot reorder br-separated text.
|
|
* Size flag fights the inline font-size:80%. */
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) > .ifacebox-body:nth-child(4) {
|
|
order: 2; /* shares the speed's row, below the zone line */
|
|
text-align: end;
|
|
/* grows to anchor text-align:end, never shrinks (nowrap figures) */
|
|
flex: 1 0 100%;
|
|
}
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) > .ifacebox-body:nth-child(4) > .cbi-tooltip-container {
|
|
font-family: var(--fs-font-mono);
|
|
/* widest thing a card must fit whole, sets the card's floor; fights inline font-size:80% */
|
|
font-size: var(--fs-type-2xs) !important;
|
|
color: var(--fs-dim);
|
|
line-height: var(--fs-leading-tight);
|
|
white-space: nowrap;
|
|
/* fights the element's own inline text-align:left */
|
|
text-align: end !important;
|
|
}
|
|
/* 25.12+ PoE line: inline color:#000 is 1.65:1 on the dark tile (#2d333b); beats it, needs the flag */
|
|
:where(#view)[data-page="admin-status-overview"] .ifacebox:has(img[src*="/port_"]) > .ifacebox-body:nth-child(4) > .cbi-tooltip-container > span[style*="color:#000"] { color: var(--fs-text) !important; }
|
|
|
|
/* meter rows — a key/value-shaped .table row with a .cbi-progressbar (same shape test as
|
|
* :218 below and 30-tables.css's key/value rule); a data table's own bar stays untouched.
|
|
* docs/css.md above. */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))):has(.cbi-progressbar) { display: block; }
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar) {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr);
|
|
gap: var(--fs-space-1) var(--fs-space-2-5);
|
|
/* halved from 8/10: the outer padding duplicated the gap. Bottom stays larger for the bar. */
|
|
padding: var(--fs-space-1) 0 var(--fs-space-1-5);
|
|
border: 0;
|
|
position: relative;
|
|
}
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar):last-child { padding-bottom: var(--fs-space-0-5); }
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar) .td {
|
|
display: block;
|
|
/* beats base's .td[width="33%"] with no flag: that sets a width ATTRIBUTE, a later layer wins */
|
|
width: auto;
|
|
padding: 0;
|
|
border: 0;
|
|
}
|
|
/* label — undoes key/value nowrap: a mount point is one unbreakable line past the card.
|
|
* padding-inline-end is the gutter for the out-of-flow value (::after over the bar's edge). */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar) .td:first-child {
|
|
grid-column: 1; grid-row: 1;
|
|
align-self: center;
|
|
min-width: 0;
|
|
white-space: normal;
|
|
padding-inline-end: min(230px, 50%);
|
|
font-size: var(--fs-type);
|
|
}
|
|
|
|
/* value rides the label's own line at desktop (::after floats over the row's top edge) —
|
|
* opt out of the bare-meter default reserve. <=560px below restores it (own line, no room). */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar) .cbi-progressbar {
|
|
margin-block-start: 0;
|
|
}
|
|
|
|
/* narrow card: the value takes its own line, the reserve above cannot fit it — docs/css.md
|
|
* above has the 218px/190px measurement. */
|
|
@container fs-view (max-width: 560px) {
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar) .td:first-child {
|
|
padding-inline-end: 0;
|
|
}
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar) .cbi-progressbar {
|
|
margin-block-start: calc(var(--fs-type-xs) * var(--fs-leading));
|
|
}
|
|
}
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr:has(.cbi-progressbar) .td:nth-child(2) {
|
|
grid-column: 1 / -1; grid-row: 2;
|
|
}
|
|
|
|
/* per-row dividers dropped, keyed on table SHAPE (no .th, no 3rd .td — same test as
|
|
* 30-tables.css's key/value rule, docs/css.md "Tables: the key/value discriminator") not on the
|
|
* three named cards. attendedsysupgrade's 11_upgrades.js (a stock header row) keeps its
|
|
* dividers under this test. */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .td,
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .th,
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .tr { border-bottom: 0; }
|
|
/* own rule, chosen instead of :is(): .cbi-value carries no :has(), and a selector list is not
|
|
* forgiving below the browser floor */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .cbi-value { border-bottom: 0; }
|
|
|
|
/* key/value name is the QUIET half: --fs-dim at normal weight, matching what the System table's
|
|
* first column already resolved to. Data tables excluded by the same shape test above. */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .td:first-child {
|
|
font-weight: var(--fs-weight-normal);
|
|
color: var(--fs-dim);
|
|
}
|
|
|
|
/* .active fill (theme/45-misc.css) makes three saturated bars at once here; "Up" said in
|
|
* colour+text on --fs-panel2 instead. Network -> Interfaces keeps the fill (tells boxes apart
|
|
* there), so this is scoped to Overview only. */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .ifacebox .ifacebox-head.active {
|
|
background: var(--fs-panel2);
|
|
color: var(--fs-good);
|
|
font-weight: var(--fs-weight);
|
|
}
|
|
|
|
/* L.itemlist wraps every caption in <strong> at 700 weight — the boldest text on the card,
|
|
* inverted like the key/value rule above; the value keeps --fs-text with no rule of its own */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .ifacebox-body strong {
|
|
font-weight: var(--fs-weight-normal);
|
|
color: var(--fs-dim);
|
|
}
|
|
|
|
/* progressbar's attr(title) was --fs-type-xs/--fs-dim beside a now-demoted label; give Memory's
|
|
* bars something at full strength. Overview only — on Software the value sits beside its own
|
|
* field label. */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:not(:has(.th)):not(:has(.td:nth-child(3))) .cbi-progressbar::after {
|
|
font-size: var(--fs-type);
|
|
color: var(--fs-text);
|
|
}
|
|
|
|
/* row height in DATA tables (DHCP leases, station list, attendedsysupgrade's 11_upgrades.js):
|
|
* theme/30-tables.css pads for a page that IS a table, here it's a card read at a glance — 8
|
|
* leases measured 740px against a 440px System card. Positive test is the complement of the
|
|
* key/value shape above (:has(.th) or a 3rd .td), not .tr.table-titles — a stock header .th
|
|
* emitted through initFromMarkup never carries that class. One step down the space ladder,
|
|
* only here. */
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:is(:has(.th), :has(.td:nth-child(3))) .td,
|
|
:where(#view)[data-page="admin-status-overview"] .cbi-section .table:is(:has(.th), :has(.td:nth-child(3))) .th {
|
|
padding-block: var(--fs-space-1-5);
|
|
}
|
|
|
|
}
|