Remove data-theme attribute when mode="auto" instead of setting it to "auto". Pico's OS-dark selector is :root:not([data-theme]), so any value (even "auto") prevents dark-mode Pico styles. Add Pico form element background vars and color-scheme: light to match active theme. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
1534 lines
40 KiB
CSS
1534 lines
40 KiB
CSS
/* ==========================================================================
|
|
ImpTune — application shell + component layer on top of Pico CSS.
|
|
|
|
Design direction: a workbench for a build pipeline (driver -> printer ->
|
|
package), not a dashboard. Prose is set in the system UI face; every value
|
|
the machine cares about (IPs, port names, INF driver names, PowerShell
|
|
commands) is set in monospace. That split is the visual identity.
|
|
|
|
Theme selectors mirror Pico's own so equal specificity + later source order
|
|
wins: light = :root:not([data-theme=dark]) ; dark = the two dark selectors.
|
|
The "system" state renders with **no** data-theme attribute (base.html
|
|
removes it) — Pico's OS-dark block is `:root:not([data-theme])`, so a literal
|
|
data-theme="auto" would keep Pico light while this file went dark.
|
|
========================================================================== */
|
|
|
|
/* --- Tokens: light (paper) ----------------------------------------------- */
|
|
:root:not([data-theme="dark"]) {
|
|
--im-bg: #f2f2ef;
|
|
--im-surface: #ffffff;
|
|
--im-surface-2: #f8f8f5;
|
|
--im-surface-3: #eeeeea;
|
|
--im-line: #e2e3de;
|
|
--im-line-strong: #cdcfc8;
|
|
--im-text: #191f26;
|
|
--im-text-dim: #59626c;
|
|
--im-text-faint: #868f99;
|
|
--im-accent: #0d6f79;
|
|
--im-accent-hover: #0a575f;
|
|
--im-accent-soft: #dff0f1;
|
|
--im-accent-line: #a9d5d9;
|
|
--im-ok: #2b7048;
|
|
--im-ok-soft: #e2f0e7;
|
|
--im-warn: #8c5a0c;
|
|
--im-warn-soft: #fbeed7;
|
|
--im-danger: #a32f2f;
|
|
--im-danger-soft: #f8e4e2;
|
|
--im-shadow: 0 1px 2px rgba(20, 26, 32, .05), 0 8px 24px -12px rgba(20, 26, 32, .18);
|
|
--im-ring: rgba(13, 111, 121, .35);
|
|
|
|
/* Pico remap */
|
|
--pico-background-color: var(--im-bg);
|
|
--pico-color: var(--im-text);
|
|
--pico-muted-color: var(--im-text-dim);
|
|
--pico-muted-border-color: var(--im-line);
|
|
--pico-border-color: var(--im-line);
|
|
--pico-h1-color: var(--im-text);
|
|
--pico-h2-color: var(--im-text);
|
|
--pico-h3-color: var(--im-text);
|
|
--pico-h4-color: var(--im-text);
|
|
--pico-h5-color: var(--im-text);
|
|
--pico-h6-color: var(--im-text-dim);
|
|
--pico-primary: var(--im-accent);
|
|
--pico-primary-background: var(--im-accent);
|
|
--pico-primary-border: var(--im-accent);
|
|
--pico-primary-hover: var(--im-accent-hover);
|
|
--pico-primary-hover-background: var(--im-accent-hover);
|
|
--pico-primary-hover-border: var(--im-accent-hover);
|
|
--pico-primary-underline: var(--im-accent-line);
|
|
--pico-primary-focus: var(--im-ring);
|
|
--pico-primary-inverse: #ffffff;
|
|
--pico-secondary: var(--im-text-dim);
|
|
--pico-secondary-background: var(--im-surface-3);
|
|
--pico-secondary-border: var(--im-line-strong);
|
|
--pico-secondary-hover: var(--im-text);
|
|
--pico-secondary-hover-background: var(--im-line);
|
|
--pico-secondary-hover-border: var(--im-line-strong);
|
|
--pico-secondary-inverse: var(--im-text);
|
|
--pico-card-background-color: var(--im-surface);
|
|
--pico-card-border-color: var(--im-line);
|
|
--pico-card-sectioning-background-color: var(--im-surface-2);
|
|
--pico-card-box-shadow: none;
|
|
--pico-form-element-background-color: var(--im-surface);
|
|
--pico-form-element-border-color: var(--im-line-strong);
|
|
--pico-form-element-color: var(--im-text);
|
|
--pico-form-element-placeholder-color: var(--im-text-faint);
|
|
--pico-form-element-active-border-color: var(--im-accent);
|
|
--pico-form-element-focus-color: var(--im-accent);
|
|
/* Pico swaps the *background* on :focus/:active. Remap it too, or a focused
|
|
field falls back to Pico's own palette instead of ours. */
|
|
--pico-form-element-active-background-color: var(--im-surface);
|
|
--pico-form-element-selected-background-color: var(--im-surface-3);
|
|
--pico-code-background-color: var(--im-surface-3);
|
|
--pico-code-color: var(--im-text);
|
|
--pico-modal-overlay-background-color: rgba(24, 30, 36, .42);
|
|
/* Native widgets: <select> popup, scrollbars, autofill. */
|
|
color-scheme: light;
|
|
}
|
|
|
|
/* --- Tokens: dark (ink) -------------------------------------------------- */
|
|
@media only screen and (prefers-color-scheme: dark) {
|
|
:root:not([data-theme="light"]) {
|
|
--im-bg: #0f151b;
|
|
--im-surface: #161d24;
|
|
--im-surface-2: #1b232b;
|
|
--im-surface-3: #222c35;
|
|
--im-line: #26313a;
|
|
--im-line-strong: #35434e;
|
|
--im-text: #e5eaee;
|
|
--im-text-dim: #98a5b0;
|
|
--im-text-faint: #6c7a86;
|
|
--im-accent: #33bec6;
|
|
--im-accent-hover: #5ad3d9;
|
|
--im-accent-soft: #10333a;
|
|
--im-accent-line: #1f5d66;
|
|
--im-ok: #58c185;
|
|
--im-ok-soft: #14301f;
|
|
--im-warn: #dfa757;
|
|
--im-warn-soft: #33260f;
|
|
--im-danger: #e8746c;
|
|
--im-danger-soft: #35191a;
|
|
--im-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 12px 32px -14px rgba(0, 0, 0, .7);
|
|
--im-ring: rgba(51, 190, 198, .4);
|
|
|
|
--pico-background-color: var(--im-bg);
|
|
--pico-color: var(--im-text);
|
|
--pico-muted-color: var(--im-text-dim);
|
|
--pico-muted-border-color: var(--im-line);
|
|
--pico-border-color: var(--im-line);
|
|
--pico-h1-color: var(--im-text);
|
|
--pico-h2-color: var(--im-text);
|
|
--pico-h3-color: var(--im-text);
|
|
--pico-h4-color: var(--im-text);
|
|
--pico-h5-color: var(--im-text);
|
|
--pico-h6-color: var(--im-text-dim);
|
|
--pico-primary: var(--im-accent);
|
|
--pico-primary-background: var(--im-accent);
|
|
--pico-primary-border: var(--im-accent);
|
|
--pico-primary-hover: var(--im-accent-hover);
|
|
--pico-primary-hover-background: var(--im-accent-hover);
|
|
--pico-primary-hover-border: var(--im-accent-hover);
|
|
--pico-primary-underline: var(--im-accent-line);
|
|
--pico-primary-focus: var(--im-ring);
|
|
--pico-primary-inverse: #06232a;
|
|
--pico-secondary: var(--im-text-dim);
|
|
--pico-secondary-background: var(--im-surface-3);
|
|
--pico-secondary-border: var(--im-line-strong);
|
|
--pico-secondary-hover: var(--im-text);
|
|
--pico-secondary-hover-background: var(--im-line-strong);
|
|
--pico-secondary-hover-border: var(--im-line-strong);
|
|
--pico-secondary-inverse: var(--im-text);
|
|
--pico-card-background-color: var(--im-surface);
|
|
--pico-card-border-color: var(--im-line);
|
|
--pico-card-sectioning-background-color: var(--im-surface-2);
|
|
--pico-card-box-shadow: none;
|
|
--pico-form-element-background-color: var(--im-surface-2);
|
|
--pico-form-element-border-color: var(--im-line-strong);
|
|
--pico-form-element-color: var(--im-text);
|
|
--pico-form-element-placeholder-color: var(--im-text-faint);
|
|
--pico-form-element-active-border-color: var(--im-accent);
|
|
--pico-form-element-focus-color: var(--im-accent);
|
|
--pico-form-element-active-background-color: var(--im-surface-3);
|
|
--pico-form-element-selected-background-color: var(--im-surface-3);
|
|
--pico-code-background-color: var(--im-surface-3);
|
|
--pico-code-color: var(--im-text);
|
|
--pico-modal-overlay-background-color: rgba(4, 8, 11, .62);
|
|
color-scheme: dark;
|
|
}
|
|
}
|
|
|
|
[data-theme="dark"] {
|
|
--im-bg: #0f151b;
|
|
--im-surface: #161d24;
|
|
--im-surface-2: #1b232b;
|
|
--im-surface-3: #222c35;
|
|
--im-line: #26313a;
|
|
--im-line-strong: #35434e;
|
|
--im-text: #e5eaee;
|
|
--im-text-dim: #98a5b0;
|
|
--im-text-faint: #6c7a86;
|
|
--im-accent: #33bec6;
|
|
--im-accent-hover: #5ad3d9;
|
|
--im-accent-soft: #10333a;
|
|
--im-accent-line: #1f5d66;
|
|
--im-ok: #58c185;
|
|
--im-ok-soft: #14301f;
|
|
--im-warn: #dfa757;
|
|
--im-warn-soft: #33260f;
|
|
--im-danger: #e8746c;
|
|
--im-danger-soft: #35191a;
|
|
--im-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 12px 32px -14px rgba(0, 0, 0, .7);
|
|
--im-ring: rgba(51, 190, 198, .4);
|
|
|
|
--pico-background-color: var(--im-bg);
|
|
--pico-color: var(--im-text);
|
|
--pico-muted-color: var(--im-text-dim);
|
|
--pico-muted-border-color: var(--im-line);
|
|
--pico-border-color: var(--im-line);
|
|
--pico-h1-color: var(--im-text);
|
|
--pico-h2-color: var(--im-text);
|
|
--pico-h3-color: var(--im-text);
|
|
--pico-h4-color: var(--im-text);
|
|
--pico-h5-color: var(--im-text);
|
|
--pico-h6-color: var(--im-text-dim);
|
|
--pico-primary: var(--im-accent);
|
|
--pico-primary-background: var(--im-accent);
|
|
--pico-primary-border: var(--im-accent);
|
|
--pico-primary-hover: var(--im-accent-hover);
|
|
--pico-primary-hover-background: var(--im-accent-hover);
|
|
--pico-primary-hover-border: var(--im-accent-hover);
|
|
--pico-primary-underline: var(--im-accent-line);
|
|
--pico-primary-focus: var(--im-ring);
|
|
--pico-primary-inverse: #06232a;
|
|
--pico-secondary: var(--im-text-dim);
|
|
--pico-secondary-background: var(--im-surface-3);
|
|
--pico-secondary-border: var(--im-line-strong);
|
|
--pico-secondary-hover: var(--im-text);
|
|
--pico-secondary-hover-background: var(--im-line-strong);
|
|
--pico-secondary-hover-border: var(--im-line-strong);
|
|
--pico-secondary-inverse: var(--im-text);
|
|
--pico-card-background-color: var(--im-surface);
|
|
--pico-card-border-color: var(--im-line);
|
|
--pico-card-sectioning-background-color: var(--im-surface-2);
|
|
--pico-card-box-shadow: none;
|
|
--pico-form-element-background-color: var(--im-surface-2);
|
|
--pico-form-element-border-color: var(--im-line-strong);
|
|
--pico-form-element-color: var(--im-text);
|
|
--pico-form-element-placeholder-color: var(--im-text-faint);
|
|
--pico-form-element-active-border-color: var(--im-accent);
|
|
--pico-form-element-focus-color: var(--im-accent);
|
|
--pico-form-element-active-background-color: var(--im-surface-3);
|
|
--pico-form-element-selected-background-color: var(--im-surface-3);
|
|
--pico-code-background-color: var(--im-surface-3);
|
|
--pico-code-color: var(--im-text);
|
|
--pico-modal-overlay-background-color: rgba(4, 8, 11, .62);
|
|
color-scheme: dark;
|
|
}
|
|
|
|
/* --- Typography + global rhythm ----------------------------------------- */
|
|
:root {
|
|
--im-mono: ui-monospace, "Cascadia Mono", "Cascadia Code", "SF Mono",
|
|
"JetBrains Mono", Consolas, "Liberation Mono", monospace;
|
|
--im-r: 8px;
|
|
--im-r-sm: 5px;
|
|
--im-sidebar-w: 236px;
|
|
--pico-font-family-sans-serif: system-ui, -apple-system, "Segoe UI Variable Text",
|
|
"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
--pico-font-family-monospace: var(--im-mono);
|
|
--pico-font-size: 93.75%; /* 15px base */
|
|
--pico-line-height: 1.55;
|
|
--pico-border-radius: var(--im-r-sm);
|
|
--pico-spacing: 1rem;
|
|
--pico-form-element-spacing-vertical: .55rem;
|
|
--pico-form-element-spacing-horizontal: .7rem;
|
|
--pico-typography-spacing-vertical: .9rem;
|
|
--pico-outline-width: 2px;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
body {
|
|
background: var(--im-bg);
|
|
color: var(--im-text);
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
h1, h2, h3, h4 { letter-spacing: -.011em; font-weight: 600; }
|
|
|
|
/* Utility label — the recurring "field label" voice of a control panel. */
|
|
.eyebrow {
|
|
font-size: .688rem;
|
|
font-weight: 600;
|
|
letter-spacing: .085em;
|
|
text-transform: uppercase;
|
|
color: var(--im-text-faint);
|
|
margin: 0;
|
|
}
|
|
|
|
.mono { font-family: var(--im-mono); font-size: .84em; }
|
|
.dim { color: var(--im-text-dim); }
|
|
.faint { color: var(--im-text-faint); }
|
|
.nowrap { white-space: nowrap; }
|
|
.ico { flex: 0 0 auto; vertical-align: -.18em; }
|
|
|
|
:where(a, button, [role="button"], summary, input, select, textarea):focus-visible {
|
|
outline: 2px solid var(--im-accent);
|
|
outline-offset: 2px;
|
|
box-shadow: none;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
App shell
|
|
========================================================================== */
|
|
|
|
.layout {
|
|
display: flex;
|
|
min-height: 100vh;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.layout > * { box-sizing: border-box; }
|
|
|
|
nav.sidebar {
|
|
width: var(--im-sidebar-w);
|
|
flex: 0 0 var(--im-sidebar-w);
|
|
background: var(--im-surface);
|
|
border-right: 1px solid var(--im-line);
|
|
padding: 0;
|
|
margin: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0;
|
|
position: sticky;
|
|
top: 0;
|
|
height: 100vh;
|
|
overflow-y: auto;
|
|
overscroll-behavior: contain;
|
|
}
|
|
|
|
nav.sidebar ul,
|
|
nav.sidebar li {
|
|
margin: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
|
|
/* Brand: wordmark + a printed-sheet mark built from the accent. */
|
|
.brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .6rem;
|
|
padding: 1.05rem 1rem .95rem;
|
|
text-decoration: none;
|
|
color: var(--im-text);
|
|
border-bottom: 1px solid var(--im-line);
|
|
}
|
|
|
|
.brand:hover { background: var(--im-surface-2); }
|
|
|
|
.brand-mark {
|
|
width: 26px;
|
|
height: 26px;
|
|
flex: 0 0 auto;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.brand-name {
|
|
font-weight: 650;
|
|
font-size: 1.02rem;
|
|
letter-spacing: -.02em;
|
|
line-height: 1.1;
|
|
}
|
|
|
|
.brand-sub {
|
|
display: block;
|
|
font-size: .656rem;
|
|
font-weight: 500;
|
|
letter-spacing: .07em;
|
|
text-transform: uppercase;
|
|
color: var(--im-text-faint);
|
|
}
|
|
|
|
.nav-group { padding: .85rem 0 .2rem; }
|
|
.nav-group + .nav-group { border-top: 1px solid var(--im-line); }
|
|
|
|
.nav-group-label {
|
|
padding: 0 1rem .45rem;
|
|
font-size: .656rem;
|
|
font-weight: 600;
|
|
letter-spacing: .09em;
|
|
text-transform: uppercase;
|
|
color: var(--im-text-faint);
|
|
}
|
|
|
|
.sidebar-nav a {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .6rem;
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
padding: .5rem 1rem;
|
|
margin: 0;
|
|
text-decoration: none;
|
|
color: var(--im-text-dim);
|
|
font-size: .906rem;
|
|
font-weight: 500;
|
|
line-height: 1.4;
|
|
border-left: 2px solid transparent;
|
|
transition: background-color .12s ease, color .12s ease;
|
|
}
|
|
|
|
.sidebar-nav a .ico { color: var(--im-text-faint); transition: color .12s ease; }
|
|
|
|
.sidebar-nav a:hover {
|
|
background: var(--im-surface-2);
|
|
color: var(--im-text);
|
|
}
|
|
|
|
.sidebar-nav a:hover .ico { color: var(--im-text-dim); }
|
|
|
|
.sidebar-nav a.active {
|
|
color: var(--im-text);
|
|
font-weight: 600;
|
|
background: var(--im-accent-soft);
|
|
border-left-color: var(--im-accent);
|
|
}
|
|
|
|
.sidebar-nav a.active .ico { color: var(--im-accent); }
|
|
|
|
.sidebar-foot {
|
|
margin-top: auto;
|
|
border-top: 1px solid var(--im-line);
|
|
padding: .7rem .75rem .85rem;
|
|
}
|
|
|
|
.sidebar-foot details { margin: 0; }
|
|
|
|
.sidebar-foot summary {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .5rem;
|
|
padding: .4rem .25rem;
|
|
font-size: .844rem;
|
|
font-weight: 500;
|
|
color: var(--im-text-dim);
|
|
cursor: pointer;
|
|
list-style: none;
|
|
}
|
|
|
|
.sidebar-foot summary::after { display: none; }
|
|
.sidebar-foot summary:hover { color: var(--im-text); }
|
|
.sidebar-foot summary .ico { color: var(--im-text-faint); }
|
|
|
|
.sidebar-foot .foot-links {
|
|
padding: .1rem 0 .2rem;
|
|
display: grid;
|
|
gap: .1rem;
|
|
}
|
|
|
|
.sidebar-foot .foot-links a {
|
|
display: block;
|
|
padding: .3rem .3rem .3rem 1.85rem;
|
|
font-size: .812rem;
|
|
color: var(--im-text-dim);
|
|
text-decoration: none;
|
|
border-radius: var(--im-r-sm);
|
|
}
|
|
|
|
.sidebar-foot .foot-links a:hover { background: var(--im-surface-2); color: var(--im-accent); }
|
|
.sidebar-foot .foot-note {
|
|
padding: .35rem .3rem 0 1.85rem;
|
|
font-size: .75rem;
|
|
color: var(--im-text-faint);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
/* --- Main column --------------------------------------------------------- */
|
|
|
|
.main-wrapper {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.topbar {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 20;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
min-height: 58px;
|
|
padding: .6rem 1.75rem;
|
|
background: color-mix(in srgb, var(--im-bg) 88%, transparent);
|
|
backdrop-filter: blur(8px);
|
|
border-bottom: 1px solid var(--im-line);
|
|
}
|
|
|
|
.topbar-title {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: .1rem;
|
|
min-width: 0;
|
|
}
|
|
|
|
.topbar-title h1 {
|
|
margin: 0;
|
|
font-size: 1.1rem;
|
|
font-weight: 620;
|
|
line-height: 1.2;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.topbar-title .crumb {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .3rem;
|
|
font-size: .75rem;
|
|
color: var(--im-text-faint);
|
|
}
|
|
|
|
.topbar-title .crumb a { color: var(--im-text-faint); text-decoration: none; }
|
|
.topbar-title .crumb a:hover { color: var(--im-accent); }
|
|
|
|
.topbar-actions {
|
|
margin-left: auto;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .5rem;
|
|
}
|
|
|
|
.topbar-sep {
|
|
width: 1px;
|
|
height: 22px;
|
|
background: var(--im-line);
|
|
margin: 0 .15rem;
|
|
}
|
|
|
|
.icon-btn {
|
|
--pico-background-color: transparent;
|
|
display: inline-grid;
|
|
place-items: center;
|
|
width: 2rem;
|
|
height: 2rem;
|
|
padding: 0;
|
|
margin: 0;
|
|
border: 1px solid transparent;
|
|
border-radius: var(--im-r-sm);
|
|
background: transparent;
|
|
color: var(--im-text-dim);
|
|
font-size: .75rem;
|
|
font-weight: 600;
|
|
line-height: 1;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.icon-btn:hover {
|
|
background: var(--im-surface-3);
|
|
border-color: var(--im-line);
|
|
color: var(--im-text);
|
|
}
|
|
|
|
.sidebar-toggle { display: none; }
|
|
|
|
.main-content {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
width: 100%;
|
|
max-width: 1180px;
|
|
padding: 1.6rem 1.75rem 4rem;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
Buttons
|
|
========================================================================== */
|
|
|
|
.btn,
|
|
a[role="button"].btn,
|
|
button.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .4rem;
|
|
padding: .48rem .8rem;
|
|
border-radius: var(--im-r-sm);
|
|
border: 1px solid var(--im-accent);
|
|
background: var(--im-accent);
|
|
color: var(--pico-primary-inverse);
|
|
font-size: .875rem;
|
|
font-weight: 570;
|
|
line-height: 1.3;
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
width: auto;
|
|
transition: background-color .12s ease, border-color .12s ease, color .12s ease;
|
|
}
|
|
|
|
.btn:hover { background: var(--im-accent-hover); border-color: var(--im-accent-hover); }
|
|
|
|
.btn.ghost {
|
|
background: var(--im-surface);
|
|
border-color: var(--im-line-strong);
|
|
color: var(--im-text);
|
|
}
|
|
|
|
.btn.ghost:hover { background: var(--im-surface-2); border-color: var(--im-text-faint); }
|
|
|
|
.btn.quiet {
|
|
background: transparent;
|
|
border-color: transparent;
|
|
color: var(--im-text-dim);
|
|
padding: .35rem .5rem;
|
|
}
|
|
|
|
.btn.quiet:hover { background: var(--im-surface-3); color: var(--im-text); }
|
|
|
|
.btn.danger { background: transparent; border-color: transparent; color: var(--im-danger); }
|
|
.btn.danger:hover { background: var(--im-danger-soft); border-color: var(--im-danger-soft); }
|
|
|
|
.btn.sm { padding: .3rem .55rem; font-size: .812rem; }
|
|
|
|
.btn[aria-disabled="true"],
|
|
.btn:disabled {
|
|
opacity: .45;
|
|
cursor: not-allowed;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.btn-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: .5rem;
|
|
align-items: center;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
Cards, sections, page furniture
|
|
========================================================================== */
|
|
|
|
.card {
|
|
background: var(--im-surface);
|
|
border: 1px solid var(--im-line);
|
|
border-radius: var(--im-r);
|
|
margin: 0 0 1.1rem;
|
|
overflow: clip;
|
|
}
|
|
|
|
.card-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .75rem;
|
|
padding: .8rem 1rem;
|
|
border-bottom: 1px solid var(--im-line);
|
|
background: var(--im-surface-2);
|
|
}
|
|
|
|
.card-head h2,
|
|
.card-head h3 {
|
|
margin: 0;
|
|
font-size: .938rem;
|
|
font-weight: 620;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.card-head .sub {
|
|
margin: .1rem 0 0;
|
|
font-size: .781rem;
|
|
color: var(--im-text-dim);
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.card-head .head-actions { margin-left: auto; display: flex; gap: .4rem; align-items: center; }
|
|
.card-body { padding: 1rem; }
|
|
.card-body > :last-child { margin-bottom: 0; }
|
|
.card-body p:first-child { margin-top: 0; }
|
|
.card-flush > .card-body { padding: 0; }
|
|
|
|
.card-grid {
|
|
display: grid;
|
|
gap: 1.1rem;
|
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
|
margin-bottom: 1.1rem;
|
|
}
|
|
|
|
.card-grid > .card { margin-bottom: 0; }
|
|
|
|
.split {
|
|
display: grid;
|
|
gap: 1.1rem;
|
|
grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
|
|
align-items: start;
|
|
}
|
|
|
|
@media (max-width: 900px) { .split { grid-template-columns: minmax(0, 1fr); } }
|
|
|
|
.page-intro {
|
|
margin: -.35rem 0 1.15rem;
|
|
max-width: 62ch;
|
|
color: var(--im-text-dim);
|
|
font-size: .906rem;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
Signature: the pipeline rail (driver -> printer -> package)
|
|
Order carries real information — each stage unlocks the next.
|
|
========================================================================== */
|
|
|
|
.rail {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 0;
|
|
border: 1px solid var(--im-line);
|
|
border-radius: var(--im-r);
|
|
background: var(--im-surface);
|
|
overflow: clip;
|
|
margin-bottom: 1.1rem;
|
|
}
|
|
|
|
.rail-step {
|
|
position: relative;
|
|
display: block;
|
|
padding: 1rem 1.1rem 1.05rem;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
border-left: 1px solid var(--im-line);
|
|
transition: background-color .12s ease;
|
|
}
|
|
|
|
.rail-step:first-child { border-left: 0; }
|
|
.rail-step:hover { background: var(--im-surface-2); }
|
|
|
|
/* Progress hairline across the top of each stage. */
|
|
.rail-step::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0 0 auto 0;
|
|
height: 2px;
|
|
background: var(--im-line-strong);
|
|
}
|
|
|
|
.rail-step.done::before { background: var(--im-ok); }
|
|
.rail-step.next::before { background: var(--im-accent); }
|
|
|
|
.rail-top {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .5rem;
|
|
margin-bottom: .55rem;
|
|
}
|
|
|
|
.rail-num {
|
|
width: 1.35rem;
|
|
height: 1.35rem;
|
|
flex: 0 0 auto;
|
|
display: grid;
|
|
place-items: center;
|
|
border-radius: 50%;
|
|
border: 1px solid var(--im-line-strong);
|
|
color: var(--im-text-faint);
|
|
font-family: var(--im-mono);
|
|
font-size: .688rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.rail-step.done .rail-num {
|
|
background: var(--im-ok-soft);
|
|
border-color: var(--im-ok);
|
|
color: var(--im-ok);
|
|
}
|
|
|
|
.rail-step.next .rail-num {
|
|
background: var(--im-accent);
|
|
border-color: var(--im-accent);
|
|
color: var(--pico-primary-inverse);
|
|
}
|
|
|
|
.rail-title { font-weight: 600; font-size: .938rem; }
|
|
|
|
.rail-count {
|
|
margin-left: auto;
|
|
font-family: var(--im-mono);
|
|
font-size: 1.05rem;
|
|
font-weight: 600;
|
|
color: var(--im-text);
|
|
}
|
|
|
|
.rail-desc {
|
|
margin: 0;
|
|
font-size: .812rem;
|
|
line-height: 1.45;
|
|
color: var(--im-text-dim);
|
|
}
|
|
|
|
.rail-cta {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .3rem;
|
|
margin-top: .55rem;
|
|
font-size: .812rem;
|
|
font-weight: 570;
|
|
color: var(--im-accent);
|
|
}
|
|
|
|
.rail-step.done .rail-cta { color: var(--im-text-faint); }
|
|
|
|
@media (max-width: 720px) {
|
|
.rail { grid-template-columns: minmax(0, 1fr); }
|
|
.rail-step { border-left: 0; border-top: 1px solid var(--im-line); }
|
|
.rail-step:first-child { border-top: 0; }
|
|
}
|
|
|
|
/* ==========================================================================
|
|
Badges, pills, status
|
|
========================================================================== */
|
|
|
|
.badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .28rem;
|
|
padding: .12rem .45rem;
|
|
border-radius: 999px;
|
|
border: 1px solid var(--im-line-strong);
|
|
background: var(--im-surface-3);
|
|
color: var(--im-text-dim);
|
|
font-size: .719rem;
|
|
font-weight: 600;
|
|
letter-spacing: .01em;
|
|
line-height: 1.5;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.badge .ico { width: 12px; height: 12px; }
|
|
.badge.ok { background: var(--im-ok-soft); border-color: transparent; color: var(--im-ok); }
|
|
.badge.warn { background: var(--im-warn-soft); border-color: transparent; color: var(--im-warn); }
|
|
.badge.info { background: var(--im-accent-soft); border-color: transparent; color: var(--im-accent); }
|
|
|
|
.pill {
|
|
display: inline-block;
|
|
padding: .1rem .4rem;
|
|
border-radius: var(--im-r-sm);
|
|
background: var(--im-surface-3);
|
|
color: var(--im-text-dim);
|
|
font-family: var(--im-mono);
|
|
font-size: .719rem;
|
|
line-height: 1.6;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.pill-row { display: flex; flex-wrap: wrap; gap: .25rem; align-items: center; }
|
|
|
|
/* A multi-model INF can name a dozen printers: show three, fold the rest. */
|
|
details.more-pills { display: inline-block; margin: 0; }
|
|
|
|
details.more-pills > summary {
|
|
cursor: pointer;
|
|
list-style: none;
|
|
color: var(--im-accent);
|
|
background: var(--im-accent-soft);
|
|
}
|
|
|
|
details.more-pills > summary::marker { content: ""; }
|
|
details.more-pills > summary::-webkit-details-marker { display: none; }
|
|
details.more-pills > summary::after { display: none; }
|
|
details.more-pills[open] > .pill-row { margin-top: .25rem; }
|
|
|
|
/* ==========================================================================
|
|
Tables
|
|
========================================================================== */
|
|
|
|
.table-scroll {
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.table-scroll table,
|
|
.data-table {
|
|
margin: 0;
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: .875rem;
|
|
}
|
|
|
|
.data-table thead th {
|
|
padding: .5rem .75rem;
|
|
background: var(--im-surface-2);
|
|
border-bottom: 1px solid var(--im-line);
|
|
font-size: .688rem;
|
|
font-weight: 600;
|
|
letter-spacing: .075em;
|
|
text-transform: uppercase;
|
|
color: var(--im-text-faint);
|
|
text-align: left;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.data-table tbody td {
|
|
padding: .6rem .75rem;
|
|
border-bottom: 1px solid var(--im-line);
|
|
vertical-align: middle;
|
|
background: transparent;
|
|
}
|
|
|
|
.data-table tbody tr:last-child td { border-bottom: 0; }
|
|
.data-table tbody tr:hover td { background: var(--im-surface-2); }
|
|
|
|
.data-table .cell-name {
|
|
font-weight: 570;
|
|
color: var(--im-text);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.data-table .cell-name:hover { color: var(--im-accent); text-decoration: underline; }
|
|
.data-table .cell-sub {
|
|
display: block;
|
|
margin-top: .1rem;
|
|
font-family: var(--im-mono);
|
|
font-size: .719rem;
|
|
color: var(--im-text-faint);
|
|
}
|
|
|
|
.data-table td.num { font-family: var(--im-mono); font-size: .812rem; }
|
|
.data-table td.actions { width: 1%; white-space: nowrap; text-align: right; }
|
|
.data-table td.actions .btn-row {
|
|
justify-content: flex-end;
|
|
flex-wrap: nowrap; /* keep the action cluster on one line */
|
|
gap: .25rem;
|
|
}
|
|
|
|
/* Group heading above each client's table */
|
|
.group-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .5rem;
|
|
padding: .7rem 1rem;
|
|
border-bottom: 1px solid var(--im-line);
|
|
background: var(--im-surface-2);
|
|
}
|
|
|
|
.group-head h3 {
|
|
margin: 0;
|
|
font-size: .875rem;
|
|
font-weight: 620;
|
|
}
|
|
|
|
.group-head h3 a { color: inherit; text-decoration: none; }
|
|
.group-head h3 a:hover { color: var(--im-accent); text-decoration: underline; }
|
|
.group-head .count {
|
|
font-family: var(--im-mono);
|
|
font-size: .75rem;
|
|
color: var(--im-text-faint);
|
|
}
|
|
.group-head .head-actions { margin-left: auto; }
|
|
|
|
/* ==========================================================================
|
|
Toolbar (search + filters + primary action)
|
|
========================================================================== */
|
|
|
|
.toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .6rem;
|
|
flex-wrap: wrap;
|
|
margin-bottom: 1.1rem;
|
|
}
|
|
|
|
.search {
|
|
position: relative;
|
|
flex: 1 1 240px;
|
|
max-width: 340px;
|
|
}
|
|
|
|
.search .ico {
|
|
position: absolute;
|
|
left: .6rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: var(--im-text-faint);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.search input[type="search"],
|
|
.search input[type="text"] {
|
|
margin: 0;
|
|
padding-left: 2rem;
|
|
height: 2.25rem;
|
|
font-size: .875rem;
|
|
background-image: none;
|
|
}
|
|
|
|
.filter-count {
|
|
font-size: .812rem;
|
|
color: var(--im-text-faint);
|
|
font-family: var(--im-mono);
|
|
}
|
|
|
|
.toolbar .spacer { margin-left: auto; }
|
|
|
|
/* ==========================================================================
|
|
Empty states — an invitation to act, not a mood
|
|
========================================================================== */
|
|
|
|
.empty,
|
|
p.empty-state {
|
|
color: var(--im-text-dim);
|
|
font-style: normal;
|
|
}
|
|
|
|
.empty {
|
|
display: grid;
|
|
justify-items: start;
|
|
gap: .3rem;
|
|
padding: 1.75rem 1rem 1.9rem;
|
|
text-align: left;
|
|
}
|
|
|
|
.empty .empty-ico {
|
|
display: grid;
|
|
place-items: center;
|
|
width: 2.25rem;
|
|
height: 2.25rem;
|
|
border-radius: var(--im-r-sm);
|
|
background: var(--im-surface-3);
|
|
color: var(--im-text-faint);
|
|
margin-bottom: .3rem;
|
|
}
|
|
|
|
.empty strong { font-size: .938rem; font-weight: 620; color: var(--im-text); }
|
|
.empty p { margin: 0; font-size: .875rem; max-width: 52ch; }
|
|
.empty .btn { margin-top: .6rem; }
|
|
|
|
/* ==========================================================================
|
|
Key/value description grid
|
|
========================================================================== */
|
|
|
|
.kv {
|
|
display: grid;
|
|
grid-template-columns: minmax(9rem, auto) minmax(0, 1fr);
|
|
margin: 0;
|
|
}
|
|
|
|
.kv dt,
|
|
.kv dd {
|
|
margin: 0;
|
|
padding: .5rem .1rem;
|
|
border-top: 1px solid var(--im-line);
|
|
font-size: .875rem;
|
|
}
|
|
|
|
.kv dt:first-of-type,
|
|
.kv dt:first-of-type + dd { border-top: 0; }
|
|
|
|
.kv dt {
|
|
color: var(--im-text-faint);
|
|
font-size: .781rem;
|
|
font-weight: 500;
|
|
padding-right: 1rem;
|
|
}
|
|
|
|
.kv dd { color: var(--im-text); }
|
|
.kv dd.mono-val { font-family: var(--im-mono); font-size: .812rem; }
|
|
|
|
/* ==========================================================================
|
|
Command rows + copy
|
|
========================================================================== */
|
|
|
|
.cmd {
|
|
display: flex;
|
|
align-items: stretch;
|
|
gap: 0;
|
|
border: 1px solid var(--im-line);
|
|
border-radius: var(--im-r-sm);
|
|
background: var(--im-surface-2);
|
|
overflow: clip;
|
|
}
|
|
|
|
.cmd code {
|
|
flex: 1 1 auto;
|
|
min-width: 0;
|
|
padding: .5rem .65rem;
|
|
background: transparent;
|
|
color: var(--im-text);
|
|
font-family: var(--im-mono);
|
|
font-size: .781rem;
|
|
line-height: 1.5;
|
|
overflow-x: auto;
|
|
white-space: pre;
|
|
}
|
|
|
|
.cmd button {
|
|
flex: 0 0 auto;
|
|
width: auto;
|
|
margin: 0;
|
|
padding: 0 .65rem;
|
|
border: 0;
|
|
border-left: 1px solid var(--im-line);
|
|
border-radius: 0;
|
|
background: var(--im-surface-3);
|
|
color: var(--im-text-dim);
|
|
font-size: .75rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cmd button:hover { background: var(--im-accent-soft); color: var(--im-accent); }
|
|
|
|
.field-stack { display: grid; gap: .85rem; }
|
|
.field-stack > label { margin: 0; }
|
|
|
|
/* ==========================================================================
|
|
Forms — grouped fieldsets so a long form reads as a few short ones
|
|
========================================================================== */
|
|
|
|
.form-section {
|
|
border: 0;
|
|
border-top: 1px solid var(--im-line);
|
|
margin: 0;
|
|
padding: 1.35rem 0 .2rem;
|
|
display: grid;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.form-section:first-of-type { border-top: 0; padding-top: 0; }
|
|
|
|
/* A <legend> renders inside the fieldset's top border, so the section rule
|
|
would strike through it. Lean into that: the label knocks a gap in the
|
|
hairline and the rule continues to its right. */
|
|
.form-section legend {
|
|
padding: 0 .55rem 0 0;
|
|
margin: 0 0 -.35rem;
|
|
background: var(--im-surface);
|
|
font-size: .688rem;
|
|
font-weight: 600;
|
|
letter-spacing: .085em;
|
|
text-transform: uppercase;
|
|
color: var(--im-text-faint);
|
|
}
|
|
|
|
.form-row {
|
|
display: grid;
|
|
gap: .85rem;
|
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
}
|
|
|
|
.form-row > label { margin: 0; }
|
|
|
|
.label-text {
|
|
display: block;
|
|
margin-bottom: .25rem;
|
|
font-size: .812rem;
|
|
font-weight: 550;
|
|
color: var(--im-text);
|
|
}
|
|
|
|
.hint {
|
|
display: block;
|
|
margin-top: .25rem;
|
|
font-size: .75rem;
|
|
color: var(--im-text-faint);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.check-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 1.1rem;
|
|
align-items: center;
|
|
}
|
|
|
|
.check-row label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .45rem;
|
|
margin: 0;
|
|
font-size: .875rem;
|
|
}
|
|
|
|
.check-row input[type="checkbox"] { margin: 0; }
|
|
|
|
.form-foot {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .6rem;
|
|
flex-wrap: wrap;
|
|
border-top: 1px solid var(--im-line);
|
|
margin-top: 1.1rem;
|
|
padding-top: 1rem;
|
|
}
|
|
|
|
.form-foot .btn { margin: 0; }
|
|
|
|
input[type="file"] { font-size: .844rem; }
|
|
|
|
/* File upload panel */
|
|
.uploader {
|
|
display: grid;
|
|
gap: .7rem;
|
|
padding: .9rem;
|
|
border: 1px dashed var(--im-line-strong);
|
|
border-radius: var(--im-r);
|
|
background: var(--im-surface-2);
|
|
}
|
|
|
|
.uploader p { margin: 0; font-size: .812rem; color: var(--im-text-dim); }
|
|
.uploader input[type="file"] { margin: 0; }
|
|
.uploader .btn-row { margin: 0; }
|
|
|
|
/* ==========================================================================
|
|
Alerts / inline feedback
|
|
========================================================================== */
|
|
|
|
.notice,
|
|
.error,
|
|
div.error > p {
|
|
font-size: .875rem;
|
|
}
|
|
|
|
.notice,
|
|
.error {
|
|
display: block;
|
|
padding: .65rem .8rem;
|
|
border-radius: var(--im-r-sm);
|
|
border: 1px solid transparent;
|
|
margin: 0 0 .9rem;
|
|
}
|
|
|
|
.notice {
|
|
background: var(--im-warn-soft);
|
|
border-color: color-mix(in srgb, var(--im-warn) 30%, transparent);
|
|
color: var(--im-warn);
|
|
}
|
|
|
|
.error {
|
|
background: var(--im-danger-soft);
|
|
border-color: color-mix(in srgb, var(--im-danger) 30%, transparent);
|
|
color: var(--im-danger);
|
|
}
|
|
|
|
.error p, .notice p { margin: 0; }
|
|
|
|
/* Session-mode banners — memory-only (COOKIE_SECURE=false) and single-user
|
|
(COOKIE_SECURE=single_user): icon, message, and the escape hatch on one
|
|
line, stacking on narrow screens. */
|
|
.notice.session-ephemeral,
|
|
.notice.session-single-user {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .6rem;
|
|
}
|
|
|
|
.notice.session-ephemeral p,
|
|
.notice.session-single-user p { flex: 1; min-width: 12rem; }
|
|
.notice.session-ephemeral .ico,
|
|
.notice.session-single-user .ico { flex: none; }
|
|
|
|
.notice.session-ephemeral .btn {
|
|
flex: none;
|
|
border-color: color-mix(in srgb, var(--im-warn) 40%, transparent);
|
|
color: var(--im-warn);
|
|
}
|
|
|
|
.notice.session-ephemeral .btn:hover {
|
|
background: color-mix(in srgb, var(--im-warn) 14%, transparent);
|
|
border-color: var(--im-warn);
|
|
}
|
|
|
|
@media (max-width: 640px) {
|
|
.notice.session-ephemeral,
|
|
.notice.session-single-user { flex-wrap: wrap; }
|
|
}
|
|
|
|
.notice details { margin: .4rem 0 0; }
|
|
.notice summary { font-size: .812rem; cursor: pointer; }
|
|
.notice ul { margin: .4rem 0 0; font-size: .812rem; font-family: var(--im-mono); }
|
|
|
|
.ok-note {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .35rem;
|
|
font-size: .844rem;
|
|
color: var(--im-ok);
|
|
}
|
|
|
|
/* ==========================================================================
|
|
Icon preview
|
|
========================================================================== */
|
|
|
|
.icon-preview {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .75rem;
|
|
padding: .6rem;
|
|
border: 1px solid var(--im-line);
|
|
border-radius: var(--im-r-sm);
|
|
background: var(--im-surface-2);
|
|
margin-bottom: .8rem;
|
|
}
|
|
|
|
.icon-preview img {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: var(--im-r-sm);
|
|
background: var(--im-surface-3);
|
|
image-rendering: auto;
|
|
}
|
|
|
|
.icon-preview .meta { font-size: .812rem; color: var(--im-text-dim); }
|
|
|
|
.error-note {
|
|
margin: 0 0 .8rem;
|
|
font-size: .875rem;
|
|
color: var(--im-danger);
|
|
}
|
|
|
|
/* Driver-library thumbnail: fixed box whether or not an icon exists, so the
|
|
name column does not shift when one is added out of band. */
|
|
.cell-with-thumb {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: .6rem;
|
|
}
|
|
|
|
.driver-thumb {
|
|
flex: none;
|
|
width: 24px;
|
|
height: 24px;
|
|
margin-top: .1rem;
|
|
border-radius: var(--im-r-sm);
|
|
background: var(--im-surface-3);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.driver-thumb img { width: 24px; height: 24px; display: block; }
|
|
|
|
/* ==========================================================================
|
|
Web lookups — image picker and driver-page results
|
|
========================================================================== */
|
|
|
|
.web-picker {
|
|
margin-top: .9rem;
|
|
padding-top: .9rem;
|
|
border-top: 1px dashed var(--im-line);
|
|
}
|
|
|
|
.web-picker label { margin: 0 0 .5rem; }
|
|
.web-picker .btn-row { margin: 0; }
|
|
|
|
.image-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
|
|
gap: .5rem;
|
|
margin: .6rem 0;
|
|
}
|
|
|
|
/* Each result is a button, not an <img> with a click handler — keyboard
|
|
selection and focus rings come for free. */
|
|
.image-option {
|
|
position: relative;
|
|
display: block;
|
|
width: 100%;
|
|
aspect-ratio: 1;
|
|
padding: 0;
|
|
border: 1px solid var(--im-line);
|
|
border-radius: var(--im-r-sm);
|
|
background: var(--im-surface-3);
|
|
overflow: hidden;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.image-option:hover,
|
|
.image-option:focus-visible { border-color: var(--im-accent); }
|
|
|
|
.image-option img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: contain;
|
|
display: block;
|
|
}
|
|
|
|
.image-option .image-meta {
|
|
position: absolute;
|
|
inset: auto 0 0 0;
|
|
padding: .1rem .25rem;
|
|
font-size: .625rem;
|
|
line-height: 1.4;
|
|
color: #fff;
|
|
background: rgba(0, 0, 0, .55);
|
|
}
|
|
|
|
.link-list {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: .7rem;
|
|
}
|
|
|
|
.link-list li {
|
|
padding-bottom: .7rem;
|
|
border-bottom: 1px solid var(--im-line);
|
|
}
|
|
|
|
.link-list li:last-child { border-bottom: 0; padding-bottom: 0; }
|
|
.link-list a { font-size: .906rem; font-weight: 560; }
|
|
.link-list p { margin: .2rem 0 0; font-size: .812rem; }
|
|
.link-list .cell-sub { display: block; }
|
|
|
|
/* ==========================================================================
|
|
Dialogs
|
|
========================================================================== */
|
|
|
|
/* The edit dialog is rendered inside its row's Actions cell, so it inherits
|
|
that cell's right-aligned, no-wrap text. Reset at the dialog boundary. */
|
|
dialog {
|
|
text-align: start;
|
|
white-space: normal;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
dialog > article {
|
|
border: 1px solid var(--im-line);
|
|
border-radius: var(--im-r);
|
|
box-shadow: var(--im-shadow);
|
|
padding: 0;
|
|
max-width: 34rem;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Pico bleeds article header/footer past the article padding with negative
|
|
horizontal margins. These panels are padded themselves, so drop that. */
|
|
dialog article > header,
|
|
dialog article > footer,
|
|
dialog .dialog-head,
|
|
dialog .dialog-foot { margin: 0; }
|
|
|
|
/* Class-based, not element-based: the edit dialog wraps head/body/foot in a
|
|
<form>, so `dialog > article > header` would never match. */
|
|
dialog .dialog-head,
|
|
dialog .dialog-foot {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: .55rem;
|
|
padding: .85rem 1.1rem;
|
|
margin: 0;
|
|
background: var(--im-surface-2);
|
|
}
|
|
|
|
dialog .dialog-head { border-bottom: 1px solid var(--im-line); }
|
|
|
|
dialog .dialog-head h3 {
|
|
margin: 0;
|
|
font-size: 1rem;
|
|
font-weight: 620;
|
|
}
|
|
|
|
/* Pico draws its own X into any [aria-label=Close] button — we supply the glyph. */
|
|
dialog .dialog-head .close {
|
|
margin-left: auto;
|
|
background-image: none;
|
|
font-size: 1.15rem;
|
|
line-height: 1;
|
|
}
|
|
|
|
dialog .dialog-foot {
|
|
border-top: 1px solid var(--im-line);
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
/* Head and foot stay put; only the fields scroll on a short viewport. */
|
|
dialog .dialog-body {
|
|
padding: 1.1rem;
|
|
max-height: min(68vh, 36rem);
|
|
overflow-y: auto;
|
|
}
|
|
dialog .dialog-body > :last-child { margin-bottom: 0; }
|
|
dialog .dialog-body .form-section:first-of-type { padding-top: 0; }
|
|
|
|
[x-cloak] { display: none !important; }
|
|
|
|
/* ==========================================================================
|
|
HTMX feedback
|
|
========================================================================== */
|
|
|
|
.htmx-indicator { display: none; }
|
|
.htmx-request .htmx-indicator,
|
|
.htmx-request.htmx-indicator { display: inline-flex; align-items: center; gap: .4rem; font-size: .812rem; color: var(--im-text-dim); }
|
|
|
|
form.htmx-request button[type="submit"] { opacity: .6; pointer-events: none; }
|
|
|
|
/* ==========================================================================
|
|
Responsive: sidebar becomes an off-canvas drawer
|
|
========================================================================== */
|
|
|
|
@media (max-width: 860px) {
|
|
.sidebar-toggle { display: inline-grid; }
|
|
|
|
nav.sidebar {
|
|
position: fixed;
|
|
z-index: 40;
|
|
inset: 0 auto 0 0;
|
|
transform: translateX(-100%);
|
|
transition: transform .18s ease;
|
|
box-shadow: var(--im-shadow);
|
|
}
|
|
|
|
body.nav-open nav.sidebar { transform: translateX(0); }
|
|
|
|
body.nav-open .nav-scrim {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 30;
|
|
background: var(--pico-modal-overlay-background-color);
|
|
}
|
|
|
|
.topbar { padding: .6rem 1rem; }
|
|
.main-content { padding: 1.1rem 1rem 3rem; }
|
|
}
|
|
|
|
@media (max-width: 620px) {
|
|
/* Page actions shrink to their icons; the h1 keeps the context. */
|
|
.topbar-actions .btn > span { display: none; }
|
|
.topbar-actions .btn { padding: .45rem .55rem; }
|
|
.topbar-sep { display: none; }
|
|
|
|
/* Print defaults are the least urgent column — the detail page has them. */
|
|
.data-table .col-defaults { display: none; }
|
|
}
|
|
|
|
/* ==========================================================================
|
|
Small corrections to Pico defaults that the components rely on
|
|
========================================================================== */
|
|
|
|
.kv dd a,
|
|
.hint a,
|
|
.data-table a:not(.btn):not(.cell-name) { color: var(--im-accent); }
|
|
|
|
.data-table img { display: inline-block; max-width: 100%; }
|
|
|
|
/* Headings borrowed as section eyebrows keep the eyebrow scale, not h2's. */
|
|
h2.eyebrow, h3.eyebrow { font-size: .688rem; line-height: 1.4; }
|
|
|
|
/* Pico marks any <details><summary> as an accordion; the session menu and the
|
|
folded pill list are not accordions. */
|
|
.sidebar-foot summary::marker,
|
|
details.more-pills > summary::marker { content: ""; }
|
|
|
|
/* The upload confirmation reuses the full driver table; in the add-printer
|
|
sidebar there is only room for the file and its parsed names. */
|
|
.form-aside .data-table .col-arch,
|
|
.form-aside .data-table .col-used,
|
|
.form-aside .data-table .col-added,
|
|
.form-aside .data-table .col-actions { display: none; }
|
|
|
|
.uploader label { margin: 0; }
|
|
.uploader .hint { margin-top: 0; }
|
|
|
|
figure { margin: 0; }
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
* { transition-duration: .01ms !important; animation-duration: .01ms !important; }
|
|
}
|