Files
action a97651184f
marry-jell / merge (push) Waiting to run
update 2026-11-01 11:53:54
2026-11-01 11:53:54 +08:00

129 lines
7.4 KiB
CSS

@layer theme {
/* alert panel: a left accent stripe on a panel card; variants recolour the frame */
.alert-message {
padding: var(--fs-space-3-5) var(--fs-space-4);
border-radius: var(--fs-radius-lg);
border: var(--fs-hairline);
/* logical: the stripe marks the READING start, swapping sides in RTL (LuCI ships ar/fa/he) */
border-inline-start: 3px solid var(--fs-accent);
/* --fs-panel stays the background-COLOUR; the tint is a background-IMAGE layer over it,
* not a replacement — a `-fill` background alone is transparent to the wallpaper. */
background-color: var(--fs-panel);
background-image: linear-gradient(var(--fs-alert-tint, transparent), var(--fs-alert-tint, transparent));
color: var(--fs-text);
gap: var(--fs-space-3);
}
/* status lives in stripe+surface, ring stays neutral. :not(.btn) is load-bearing: a confirm
* control is a `<label class="btn alert-message danger">`, and without the guard the tint
* out-ranked `.btn.danger`, fading its fill. */
.alert-message.warning:not(.btn) {
border-color: var(--fs-border); border-inline-start-color: var(--fs-warn);
--fs-alert-tint: var(--fs-warn-fill);
}
.alert-message.error:not(.btn), .alert-message.danger:not(.btn) {
border-color: var(--fs-border); border-inline-start-color: var(--fs-danger);
--fs-alert-tint: var(--fs-danger-fill);
}
.alert-message.success:not(.btn) {
border-inline-start-color: var(--fs-good);
--fs-alert-tint: var(--fs-good-fill);
}
/* .notice groups HERE, not with .label.notice's accent: ui.js emits `notice spinning` for an
* IN-PROGRESS banner, so it reads as informational rather than success. */
.alert-message.info:not(.btn), .alert-message.notice:not(.btn) {
border-inline-start-color: var(--fs-accent);
--fs-alert-tint: var(--fs-accent-fill);
}
/* spinner ::before is inline-block for its usual inline hosts, but displayStatus() builds a
* BLOCK host, opening its own line. GRID, not flex: the caller decides child count. */
.alert-message.spinning {
display: grid;
grid-template-columns: auto 1fr;
align-items: center; /* centres the glyph against the FIRST row, not pinned to its top */
/* the column gap is the glyph's own spacing, stated rather than inherited from the row `gap` */
column-gap: var(--fs-space-2);
}
/* grid item now, so its inline margin would double the column gap; row 1 keeps it beside the
* FIRST child however many follow */
.alert-message.spinning::before { grid-row: 1; margin-inline-end: 0; }
.alert-message.spinning > * { grid-column: 2; }
/* h2 is what the theme's own notices emit; h4 covers a third-party alert, h5/h6 joined so an
* alert heading does not fall back to base's look past h4. */
.alert-message :is(h2, h3, h4, h5, h6) { margin: 0 0 var(--fs-space-1); font-size: var(--fs-type-lg); font-weight: var(--fs-weight-bold); color: var(--fs-text); }
/* moved from base with the heading ramp: line-height:inherit beat the ramp's leading
* in-layer, left behind it loses by layer (21 -> 16.8px) */
.alert-message h4,
.alert-message h5,
.alert-message pre,
.alert-message ul,
.alert-message li,
.alert-message p {
border: none;
line-height: inherit;
background: transparent;
padding: 0;
}
/* --fs-text, not --fs-dim: the paragraph IS the message — dim measured 4.06:1 on the tint */
.alert-message p { margin: var(--fs-space-1) 0; color: var(--fs-text); font-size: var(--fs-type); }
/* the body elements an alert may carry, absorbed from base/90-widgets.css (same values) */
.alert-message :is(ul, ol, li, pre) { color: var(--fs-text); margin: .25em 0; }
/* inner table (firmware Current/Available) flattened — no nested-card look, row dividers only */
.alert-message .table { margin: var(--fs-space-2-5) 0; background: transparent; border: 0; box-shadow: none; border-radius: 0; }
/* --fs-text, not --fs-eyebrow-color: the muted ink does not survive the status tint
* (3.35-3.36:1 against AA's 4.5). */
.alert-message .table .th,
/* title-row arms (0,5,0) outrank 30-tables.css's `.table .tr.table-titles .th` (0,4,0) */
.alert-message .table .tr.table-titles .th,
.alert-message .table .tr.cbi-section-table-titles .th { color: var(--fs-text); font-weight: var(--fs-eyebrow-weight); font-size: var(--fs-type-xs); letter-spacing: var(--fs-eyebrow-tracking); }
/* column gap --fs-space-3 like every other cell; row density --fs-space-2, a dense readout */
.alert-message .table .th, .alert-message .table .td { padding-block: var(--fs-space-2); padding-inline: 0 var(--fs-space-3); background: transparent; border-color: color-mix(in srgb, var(--fs-border) 60%, transparent); }
.alert-message .table .td { color: var(--fs-text); }
/* validation tooltip: fill stays SOLID, unlike .label below — floats over arbitrary content,
* so a border alone cannot carry the status. Shadow replaces base's raw 2px halo (1.08-1.86:1). */
.cbi-tooltip { box-shadow: var(--fs-shadow-pop); }
/* base reveals it on :hover alone; no tabindex in anything LuCI ships today, but a third
* party's own container may add one */
.cbi-tooltip-container:focus-within .cbi-tooltip:not(:empty) { inset-inline-start: auto; opacity: 1; }
.cbi-tooltip.info { background: var(--fs-accent); border-color: var(--fs-accent); color: var(--fs-on-accent); }
.cbi-tooltip.success { background: var(--fs-good); border-color: var(--fs-good); color: var(--fs-on-good); }
.cbi-tooltip.error { background: var(--fs-danger); border-color: var(--fs-danger); color: var(--fs-on-danger); }
.cbi-tooltip.notice { background: var(--fs-panel2); border-color: var(--fs-border); color: var(--fs-text); }
/* .label: core barely uses it, any luci-app-* may. .important is bootstrap's accent name. */
.label {
display: inline-block; padding: var(--fs-space-1) var(--fs-space-2); border-radius: var(--fs-radius-pill);
font-size: var(--fs-type-xs); font-weight: var(--fs-weight); line-height: 1.4;
background: var(--fs-panel2); border: var(--fs-hairline);
color: var(--fs-dim); text-shadow: none; text-transform: none;
white-space: nowrap; margin-block: .125em; margin-inline: .4em 0; /* carried over from the absorbed base rule */
}
/* no background: a translucent tint under same-colour text eats contrast (3.4-4.4:1);
* inherited opaque --fs-panel2 guarantees >=4.5. */
.label.important, .label.notice { border-color: var(--fs-accent); color: var(--fs-accent); }
.label.warning { border-color: var(--fs-warn); color: var(--fs-warn); }
.label.success { border-color: var(--fs-good); color: var(--fs-good); }
.label.danger, .label.error { border-color: var(--fs-danger); color: var(--fs-danger); }
a.label:link, a.label:visited { color: var(--fs-dim); }
a.label:hover { text-decoration: none; color: var(--fs-text); }
/* section-title toggles are .label pills, clickable — SINGLE owner */
.cbi-title .label {
padding: var(--fs-space-1) var(--fs-space-3);
border: var(--fs-hairline);
color: var(--fs-dim); cursor: pointer;
letter-spacing: 0;
margin: 0; min-width: 0; box-shadow: none;
}
.cbi-title .label:hover { color: var(--fs-text); border-color: var(--fs-dim); opacity: 1; }
/* toggles section visibility — interactive, so keyboard focus must show */
.cbi-title .label:focus-visible {
outline: none; border-color: var(--fs-accent); box-shadow: var(--fs-focus-ring);
}
/* opaque surface (--fs-panel2 inherited): accent text on --fs-accent-soft measured 4.21:1
* (theme/65-dropdown.css) — the border carries the accent instead */
.cbi-title .label.notice { opacity: 1; color: var(--fs-accent); border-color: var(--fs-accent); }
}