Each tool row's Run button gains a small play-triangle SVG to the left of the label, matching the iconography pattern the Services tab uses for its Restart and Open buttons. Same green colour (currentColor), so the icon inherits the success/destructive variants without extra CSS. Button becomes a flex container with a 6px gap so icon + label stay nicely centred regardless of label width. Signed-off-by: librelad <librelad@digitalangels.vip>
649 lines
17 KiB
CSS
649 lines
17 KiB
CSS
/*
|
|
Tools tab — mirrors the Services tab visual structure (.task-item,
|
|
.task-header, .task-info, .task-actions) plus a generic input modal
|
|
for tools that need user inputs.
|
|
*/
|
|
|
|
.tools-section { padding: 0; }
|
|
|
|
.tools-title {
|
|
padding: 20px;
|
|
background: transparent;
|
|
border-bottom: 1px solid var(--border-color);
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.tools-title h3 {
|
|
margin: 0 0 8px 0;
|
|
color: var(--text-primary, #fff);
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.tools-title p {
|
|
margin: 0;
|
|
color: var(--text-secondary, #ccc);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.tools-list { display: flex; flex-direction: column; }
|
|
|
|
/* Recessed dark pocket wrapping the tool rows — same idiom as
|
|
.services-rows on the Services tab and .tasks-container on the Tasks
|
|
tab so the three app-page tabs share one visual language. */
|
|
.tools-rows {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.6rem;
|
|
padding: 16px;
|
|
margin: 16px;
|
|
background: rgba(var(--bg-rgb), 0.2);
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.tools-cat-pane { display: none; }
|
|
.tools-cat-pane.active { display: flex; }
|
|
/* When the multi-category tab bar is present, the pane recedes directly
|
|
below it — drop the top margin so the pocket sits flush with the tabs. */
|
|
.tools-tab-bar + .tools-cat-pane,
|
|
.tools-tab-bar ~ .tools-cat-pane { margin-top: 0; }
|
|
|
|
.tools-tab-bar {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.4rem;
|
|
padding: 0.75rem 1.25rem 0;
|
|
border-bottom: 1px solid var(--border-color, rgba(255, 255, 255, 0.08));
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.tools-tab {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.4rem;
|
|
background: transparent;
|
|
border: 1px solid transparent;
|
|
border-bottom: none;
|
|
color: var(--text-secondary, #a0a0a0);
|
|
padding: 0.45rem 0.85rem;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
border-radius: 6px 6px 0 0;
|
|
cursor: pointer;
|
|
transition: color 120ms ease, background 120ms ease, border-color 120ms ease;
|
|
position: relative;
|
|
bottom: -1px;
|
|
}
|
|
|
|
.tools-tab:hover {
|
|
color: var(--text-primary, #fff);
|
|
background: rgba(255, 255, 255, 0.04);
|
|
}
|
|
|
|
.tools-tab.active {
|
|
color: var(--text-primary, #fff);
|
|
background: var(--surface-color, rgba(255, 255, 255, 0.06));
|
|
border-color: var(--border-color, rgba(255, 255, 255, 0.08));
|
|
border-bottom-color: var(--surface-color, rgba(255, 255, 255, 0.06));
|
|
}
|
|
|
|
.tools-tab-count {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-width: 1.4em;
|
|
padding: 0 0.4em;
|
|
border-radius: 999px;
|
|
background: rgba(255, 255, 255, 0.08);
|
|
color: var(--text-secondary, #ccc);
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.tools-tab.active .tools-tab-count {
|
|
background: var(--accent-color, #6c63ff);
|
|
color: #fff;
|
|
}
|
|
|
|
.tools-loading {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 0.6rem;
|
|
padding: 2rem;
|
|
color: var(--text-secondary, var(--text-muted));
|
|
}
|
|
|
|
.tools-spinner {
|
|
width: 16px;
|
|
height: 16px;
|
|
border: 2px solid rgba(var(--text-rgb), 0.15);
|
|
border-top-color: var(--accent-color, var(--accent));
|
|
border-radius: 50%;
|
|
animation: tools-spin 0.7s linear infinite;
|
|
}
|
|
|
|
@keyframes tools-spin { to { transform: rotate(360deg); } }
|
|
|
|
.tools-empty {
|
|
text-align: center;
|
|
padding: 2.5rem 1rem;
|
|
color: var(--text-secondary, var(--text-muted));
|
|
}
|
|
|
|
.tools-empty-icon {
|
|
font-size: 2rem;
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
/* Tool row -------------------------------------------------------- */
|
|
|
|
/* Mirror .task-item shell from style.css so tool rows visually match
|
|
task rows, but use a horizontal flex layout so the action button
|
|
stays vertically centered across the whole row regardless of
|
|
description length. */
|
|
.tool-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
padding: 14px 18px;
|
|
background: rgba(var(--text-rgb), 0.03);
|
|
border: 1px solid rgba(var(--text-rgb), 0.08);
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.tool-text { flex: 1 1 auto; min-width: 0; }
|
|
|
|
.tool-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.tool-icon { font-size: 18px; line-height: 1; }
|
|
|
|
.tool-title {
|
|
color: var(--text-primary, #fff);
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.tool-desc {
|
|
margin: 4px 0 0 0;
|
|
color: var(--text-secondary, var(--text-muted));
|
|
font-size: 12px;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.tool-action { flex: 0 0 auto; display: flex; align-items: center; }
|
|
|
|
/* Matches the .task-btn.delete look (translucent fill + colored border)
|
|
but bigger and green. The delete button uses bootstrap red var(--status-danger);
|
|
we use bootstrap green var(--status-success) for parity. */
|
|
.tool-run-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 6px;
|
|
background: rgba(var(--status-success-rgb), 0.12);
|
|
border: 1px solid rgba(var(--status-success-rgb), 0.3);
|
|
color: var(--status-success);
|
|
padding: 10px 22px;
|
|
border-radius: 6px;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
letter-spacing: 0.2px;
|
|
min-width: 96px;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
}
|
|
.tool-run-btn-icon { flex-shrink: 0; }
|
|
.tool-run-btn-label { display: inline-block; }
|
|
|
|
.tool-run-btn:hover {
|
|
background: rgba(var(--status-success-rgb), 0.22);
|
|
border-color: rgba(var(--status-success-rgb), 0.45);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.tool-run-btn:active { transform: translateY(0); }
|
|
|
|
.tool-run-btn.destructive {
|
|
background: rgba(var(--status-danger-rgb), 0.1);
|
|
border-color: rgba(var(--status-danger-rgb), 0.3);
|
|
color: var(--status-danger);
|
|
}
|
|
|
|
.tool-run-btn.destructive:hover {
|
|
background: rgba(var(--status-danger-rgb), 0.22);
|
|
border-color: rgba(var(--status-danger-rgb), 0.45);
|
|
}
|
|
|
|
/* Tool modal ------------------------------------------------------ */
|
|
|
|
/* Center the modal vertically + horizontally. Mirrors the gluetun-modal
|
|
trick: the inline `style="display: block"` set in JS triggers this
|
|
selector, which overrides to flexbox so the content sits in the
|
|
middle of the viewport regardless of its height. */
|
|
.tool-modal {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 1100;
|
|
}
|
|
.tool-modal[style*="display: block"] {
|
|
display: flex !important;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
/* Global .modal-body sets padding: 0 (it's used for full-bleed
|
|
content like the readme iframe). The tool modal's form needs
|
|
real breathing room around it — match the gluetun modal's
|
|
padding so the picker cards don't sit flush against the edges.
|
|
overflow:hidden so any inner scrollable region (e.g. the URL
|
|
list in app_urls_multi) is the *only* thing that scrolls,
|
|
not the whole modal body. */
|
|
.tool-modal .modal-body {
|
|
padding: 20px;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
.tool-modal .tool-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
flex: 1;
|
|
}
|
|
.tool-modal .tool-form .form-group-app-urls,
|
|
.tool-modal .tool-form .form-group:has(.app-urls-multi) {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
flex: 1;
|
|
margin-bottom: 0;
|
|
gap: 0;
|
|
}
|
|
.tool-modal .app-urls-multi {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
flex: 1;
|
|
gap: 0;
|
|
}
|
|
|
|
/* Single bordered shell that holds the search row + URL list as one
|
|
visual unit, mirroring the framing the rest of the WebUI uses. */
|
|
.app-urls-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
flex: 1;
|
|
background: rgba(var(--text-rgb), 0.02);
|
|
border: 1px solid rgba(var(--text-rgb), 0.08);
|
|
border-radius: 10px;
|
|
overflow: hidden;
|
|
}
|
|
/* Title bar at the top of the picker container — replaces the old
|
|
floating .form-label so the field reads as one cohesive unit. */
|
|
.app-urls-title {
|
|
padding: 10px 14px;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
background: rgba(var(--accent-rgb), 0.08);
|
|
border-bottom: 1px solid rgba(var(--accent-rgb), 0.20);
|
|
letter-spacing: 0.2px;
|
|
flex-shrink: 0;
|
|
}
|
|
.app-urls-title .required-mark { color: var(--status-danger); margin-left: 2px; }
|
|
|
|
.app-urls-header {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
padding: 10px 12px;
|
|
border-bottom: 1px solid rgba(var(--text-rgb), 0.06);
|
|
background: rgba(var(--bg-rgb), 0.12);
|
|
flex-shrink: 0;
|
|
}
|
|
.tool-modal .modal-footer {
|
|
padding: 16px 20px;
|
|
border-top: 1px solid var(--border-color);
|
|
display: flex;
|
|
justify-content: stretch;
|
|
gap: 12px;
|
|
}
|
|
.tool-modal .modal-footer .btn {
|
|
flex: 1 1 0;
|
|
}
|
|
|
|
.tool-modal-confirm {
|
|
background: rgba(var(--status-warning-rgb), 0.12);
|
|
border: 1px solid rgba(var(--status-warning-rgb), 0.4);
|
|
color: var(--status-warning);
|
|
padding: 10px 12px;
|
|
border-radius: 6px;
|
|
font-size: 13px;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.tool-form .form-group { margin-bottom: 14px; }
|
|
.tool-form .form-group:last-child { margin-bottom: 0; }
|
|
|
|
.tool-form .form-label {
|
|
display: block;
|
|
margin-bottom: 6px;
|
|
color: var(--text-primary, #fff);
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.tool-form .required-mark { color: var(--status-danger); }
|
|
|
|
/* installed_apps_multi — visually mirrors gluetun country picker. */
|
|
.installed-apps-multi {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
/* Framed card holding the search input + bulk-action buttons, same
|
|
treatment as .gluetun-search-card. */
|
|
.installed-apps-search-card {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
padding: 10px 12px;
|
|
background: rgba(var(--text-rgb), 0.03);
|
|
border: 1px solid rgba(var(--text-rgb), 0.08);
|
|
border-radius: 10px;
|
|
}
|
|
.installed-apps-search-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 10px;
|
|
background: rgba(var(--text-rgb), 0.04);
|
|
border: 1px solid rgba(var(--text-rgb), 0.10);
|
|
border-radius: 8px;
|
|
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
}
|
|
.installed-apps-search-row:focus-within {
|
|
border-color: rgba(var(--accent-rgb), 0.55);
|
|
box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.12);
|
|
}
|
|
.installed-apps-search-icon {
|
|
color: rgba(var(--text-rgb), 0.55);
|
|
flex-shrink: 0;
|
|
}
|
|
.installed-apps-search {
|
|
flex: 1;
|
|
background: transparent;
|
|
border: none;
|
|
outline: none;
|
|
color: var(--text-primary);
|
|
font-size: 14px;
|
|
padding: 2px 0;
|
|
}
|
|
.installed-apps-actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
.installed-apps-actions .btn { flex: 1 1 0; }
|
|
|
|
/* Grid of selectable apps, matching .gluetun-country-list. */
|
|
.installed-apps-list {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
gap: 6px 14px;
|
|
max-height: 45vh;
|
|
overflow-y: auto;
|
|
padding: 4px 2px;
|
|
background: transparent;
|
|
border: none;
|
|
}
|
|
.installed-apps-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 8px 10px;
|
|
background: rgba(var(--text-rgb), 0.03);
|
|
border: 1px solid rgba(var(--text-rgb), 0.08);
|
|
border-radius: 10px;
|
|
cursor: pointer;
|
|
transition: background 0.15s ease, border-color 0.15s ease;
|
|
}
|
|
.installed-apps-item:hover {
|
|
background: rgba(var(--text-rgb), 0.06);
|
|
border-color: rgba(var(--accent-rgb), 0.25);
|
|
}
|
|
.installed-apps-item:has(input:checked) {
|
|
background: rgba(var(--accent-rgb), 0.10);
|
|
border-color: rgba(var(--accent-rgb), 0.45);
|
|
}
|
|
|
|
.installed-apps-item input[type="checkbox"] {
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
width: 18px;
|
|
height: 18px;
|
|
flex-shrink: 0;
|
|
cursor: pointer;
|
|
border-radius: 5px;
|
|
background: rgba(var(--text-rgb), 0.04);
|
|
border: 1.5px solid rgba(var(--text-rgb), 0.18);
|
|
box-shadow: inset 0 0 0 1px rgba(var(--text-rgb), 0.02);
|
|
position: relative;
|
|
transition: background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease, transform 0.12s ease;
|
|
margin: 0;
|
|
}
|
|
.installed-apps-item:hover input[type="checkbox"] {
|
|
border-color: rgba(var(--accent-rgb), 0.55);
|
|
box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.08);
|
|
}
|
|
.installed-apps-item input[type="checkbox"]:focus-visible {
|
|
outline: none;
|
|
border-color: rgba(var(--accent-rgb), 0.85);
|
|
box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.20);
|
|
}
|
|
.installed-apps-item input[type="checkbox"]:checked {
|
|
background: linear-gradient(135deg, var(--accent), var(--accent));
|
|
border-color: rgba(var(--accent-rgb), 0.9);
|
|
box-shadow: 0 0 0 1px rgba(var(--accent-rgb), 0.35);
|
|
}
|
|
.installed-apps-item input[type="checkbox"]:checked::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
background-size: 13px 13px;
|
|
animation: installedAppsCheckPop 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
}
|
|
@keyframes installedAppsCheckPop {
|
|
0% { transform: scale(0.4); opacity: 0; }
|
|
100% { transform: scale(1); opacity: 1; }
|
|
}
|
|
|
|
.installed-apps-icon {
|
|
width: 22px;
|
|
height: 22px;
|
|
border-radius: 5px;
|
|
object-fit: contain;
|
|
flex-shrink: 0;
|
|
}
|
|
.installed-apps-name {
|
|
font-size: 14px;
|
|
color: var(--text-primary);
|
|
font-weight: 500;
|
|
}
|
|
.installed-apps-multi-empty {
|
|
padding: 24px;
|
|
text-align: center;
|
|
color: rgba(var(--text-rgb), 0.6);
|
|
font-size: 13px;
|
|
}
|
|
|
|
/* app_urls_multi — flat task-style list. One URL per row, no per-app
|
|
grouping. Each row is slim (icon + label + URL inline + checkbox)
|
|
and visually echoes the .task-item shell from style.css. */
|
|
.app-urls-list {
|
|
display: flex !important;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
grid-template-columns: none !important;
|
|
padding: 8px 10px;
|
|
background: transparent;
|
|
border: none;
|
|
/* Fill available space inside the container and scroll only this
|
|
region — overrides the inherited .installed-apps-list max-height
|
|
which was sized for the wide-grid layout. */
|
|
flex: 1;
|
|
min-height: 0;
|
|
max-height: none;
|
|
overflow-y: auto;
|
|
}
|
|
.app-urls-loading {
|
|
padding: 18px;
|
|
text-align: center;
|
|
color: rgba(var(--text-rgb), 0.55);
|
|
font-size: 13px;
|
|
font-style: italic;
|
|
}
|
|
|
|
.app-url-row.installed-apps-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 6px 12px;
|
|
min-height: 34px;
|
|
background: rgba(var(--text-rgb), 0.03);
|
|
border: 1px solid rgba(var(--text-rgb), 0.06);
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
transition: background 0.12s ease, border-color 0.12s ease;
|
|
line-height: 1;
|
|
}
|
|
.app-url-row:hover {
|
|
background: rgba(var(--text-rgb), 0.06);
|
|
border-color: rgba(var(--accent-rgb), 0.25);
|
|
}
|
|
.app-url-row:has(input:checked) {
|
|
background: rgba(var(--accent-rgb), 0.10);
|
|
border-color: rgba(var(--accent-rgb), 0.40);
|
|
}
|
|
|
|
/* Slim flat row checkbox — ~⅓ smaller than the wide-grid gluetun
|
|
style, no glow. */
|
|
.app-url-row input[type="checkbox"] {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 2px;
|
|
flex-shrink: 0;
|
|
align-self: center;
|
|
}
|
|
.app-url-row input[type="checkbox"]:checked {
|
|
box-shadow: none;
|
|
}
|
|
.app-url-row input[type="checkbox"]:checked::after {
|
|
background-size: 8px 8px;
|
|
}
|
|
|
|
.app-url-icon {
|
|
width: 28px;
|
|
height: 28px;
|
|
border-radius: 6px;
|
|
object-fit: contain;
|
|
flex-shrink: 0;
|
|
align-self: center;
|
|
}
|
|
|
|
.app-url-label {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
font-size: 13px;
|
|
color: var(--text-primary);
|
|
font-weight: 500;
|
|
white-space: nowrap;
|
|
line-height: 1;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
min-width: 0;
|
|
flex: 1;
|
|
}
|
|
.app-url-sep {
|
|
color: rgba(var(--text-rgb), 0.35);
|
|
font-weight: 400;
|
|
margin: 0 2px;
|
|
}
|
|
|
|
/* User list modal — opens after a list_users tool task completes. */
|
|
.user-list { display: flex; flex-direction: column; gap: 6px; }
|
|
.user-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 10px 12px;
|
|
background: rgba(var(--text-rgb), 0.03);
|
|
border: 1px solid rgba(var(--text-rgb), 0.08);
|
|
border-radius: 8px;
|
|
}
|
|
.user-row:hover { background: rgba(var(--text-rgb), 0.05); }
|
|
.user-row-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
|
|
.user-row-primary { font-size: 14px; font-weight: 500; color: var(--text-primary); }
|
|
.user-row-secondary { font-size: 12px; color: rgba(var(--text-rgb), 0.55); font-family: ui-monospace, "SF Mono", Menlo, monospace; }
|
|
.user-row-roles {
|
|
display: inline-flex;
|
|
align-self: flex-start;
|
|
margin-top: 2px;
|
|
font-size: 10px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.4px;
|
|
padding: 2px 6px;
|
|
border-radius: 3px;
|
|
background: rgba(var(--accent-rgb), 0.10);
|
|
border: 1px solid rgba(var(--accent-rgb), 0.25);
|
|
color: var(--accent);
|
|
}
|
|
|
|
.user-row-actions { display: flex; gap: 4px; flex-shrink: 0; }
|
|
.user-row-btn {
|
|
width: 30px;
|
|
height: 30px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 14px;
|
|
background: transparent;
|
|
border: 1px solid rgba(var(--text-rgb), 0.12);
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
transition: background 0.12s, border-color 0.12s, color 0.12s;
|
|
color: rgba(var(--text-rgb), 0.85);
|
|
}
|
|
.user-row-btn:hover {
|
|
background: rgba(var(--accent-rgb), 0.10);
|
|
border-color: rgba(var(--accent-rgb), 0.40);
|
|
}
|
|
.user-row-btn.danger:hover {
|
|
background: rgba(var(--status-danger-rgb), 0.12);
|
|
border-color: rgba(var(--status-danger-rgb), 0.45);
|
|
}
|
|
.user-row-roles.is-admin {
|
|
background: rgba(var(--status-warning-rgb), 0.12);
|
|
border-color: rgba(var(--status-warning-rgb), 0.30);
|
|
color: var(--status-warning);
|
|
}
|
|
|
|
/* Toggle inside a tool form — match form-group spacing so it sits flush
|
|
with siblings. .form-group:last-child rule already handles the bottom. */
|
|
.tool-form > .tool-form-toggle { margin-bottom: 14px; }
|
|
.tool-form > .tool-form-toggle:last-child { margin-bottom: 0; }
|