/** * styles/podman.css * * Design tokens and component styles for the Podman plugin page. Ported * directly from the approved mockup (webui/mockups/prototype.html) so the * real implementation is visually identical to what was reviewed — the * masthead/main-nav chrome from that mockup is NOT included here, since * Podman.page renders inside Unraid's own real chrome, not a recreation * of it. * * Token strategy: custom properties on :root, redefined under * prefers-color-scheme (OS default) and under [data-theme] (explicit * override, e.g. from Unraid's own theme setting) — component rules below * only ever reference the tokens, never hardcode a color, so both themes * stay in sync automatically. See docs/ARCHITECTURE.md section 18. */ .podman-plugin { --bg: #eef0f2; --surface: #ffffff; --surface-2: #f4f5f7; --surface-3: #e9ebee; --border: #dde1e6; --text: #1c2024; --text-dim: #5b6572; --text-faint: #8a94a1; --accent: #d8541a; --accent-strong: #b8420f; --accent-contrast: #fff8f3; --good: #1a8f4c; --good-bg: #e4f6ea; --warn: #9a6b00; --warn-bg: #fdf1d6; --bad: #c22b3a; --bad-bg: #fbe6e8; --neutral: #5b6572; --neutral-bg: #e9ebee; --shadow: 0 1px 2px rgba(20, 22, 26, .06), 0 4px 12px rgba(20, 22, 26, .05); --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-mono: ui-monospace, "SF Mono", "Cascadia Code", "Roboto Mono", Consolas, "Liberation Mono", monospace; font-family: var(--font-ui); color: var(--text); font-size: 14px; line-height: 1.5; } @media (prefers-color-scheme: dark) { .podman-plugin { --bg: #15171b; --surface: #1c1f24; --surface-2: #23262c; --surface-3: #2b2f36; --border: #34383f; --text: #e7e9ec; --text-dim: #9aa1ab; --text-faint: #6b7280; --accent: #ef7f3f; --accent-strong: #f6975f; --accent-contrast: #1a1002; --good: #4cc785; --good-bg: #123322; --warn: #e0b23d; --warn-bg: #3a2e0d; --bad: #ef6470; --bad-bg: #3a1519; --neutral: #9aa1ab; --neutral-bg: #2b2f36; --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35); } } :root[data-theme="dark"] .podman-plugin { --bg: #15171b; --surface: #1c1f24; --surface-2: #23262c; --surface-3: #2b2f36; --border: #34383f; --text: #e7e9ec; --text-dim: #9aa1ab; --text-faint: #6b7280; --accent: #ef7f3f; --accent-strong: #f6975f; --accent-contrast: #1a1002; --good: #4cc785; --good-bg: #123322; --warn: #e0b23d; --warn-bg: #3a2e0d; --bad: #ef6470; --bad-bg: #3a1519; --neutral: #9aa1ab; --neutral-bg: #2b2f36; --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35); } :root[data-theme="light"] .podman-plugin { --bg: #eef0f2; --surface: #ffffff; --surface-2: #f4f5f7; --surface-3: #e9ebee; --border: #dde1e6; --text: #1c2024; --text-dim: #5b6572; --text-faint: #8a94a1; --accent: #d8541a; --accent-strong: #b8420f; --accent-contrast: #fff8f3; --good: #1a8f4c; --good-bg: #e4f6ea; --warn: #9a6b00; --warn-bg: #fdf1d6; --bad: #c22b3a; --bad-bg: #fbe6e8; --neutral: #5b6572; --neutral-bg: #e9ebee; --shadow: 0 1px 2px rgba(20,22,26,.06), 0 4px 12px rgba(20,22,26,.05); } .podman-plugin * { box-sizing: border-box; } .podman-plugin h1, .podman-plugin h2, .podman-plugin h3 { text-wrap: balance; margin: 0; font-weight: 600; } .podman-plugin .tnum { font-variant-numeric: tabular-nums; } .podman-plugin .mono { font-family: var(--font-mono); } .podman-plugin :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; } .podman-pagehead { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 4px 0 0; } .podman-pagehead .titlewrap { display: flex; align-items: center; gap: 12px; } .podman-pagehead .icon { width: 38px; height: 38px; border-radius: 9px; background: var(--surface-3); display: grid; place-items: center; color: var(--accent); border: 1px solid var(--border); } .podman-pagehead h1 { font-size: 21px; } .podman-pagehead .meta { font-size: 12.5px; color: var(--text-dim); margin-top: 2px; } .podman-pagehead .meta .dot-good { color: var(--good); } .podman-pagehead .meta .dot-bad { color: var(--bad); } .podman-btn { appearance: none; border: 1px solid var(--border); background: var(--surface); color: var(--text); padding: 8px 14px; border-radius: 7px; font-size: 13px; font-weight: 600; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: border-color .12s, background .12s; font-family: var(--font-ui); } .podman-btn:hover { border-color: var(--text-faint); } .podman-btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); } .podman-btn-primary:hover { background: var(--accent-strong); border-color: var(--accent-strong); } .podman-btn-danger { color: var(--bad); } .podman-btn-danger:hover { border-color: var(--bad); } .podman-btn-icon { padding: 6px 8px; } .podman-btn[disabled] { opacity: .4; cursor: not-allowed; } .podman-subnav { margin: 14px 0 0; padding: 0; display: flex; gap: 4px; border-bottom: 1px solid var(--border); overflow-x: auto; list-style: none; } .podman-subnav button { appearance: none; background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-dim); padding: 10px 12px; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; display: flex; align-items: center; gap: 6px; font-family: var(--font-ui); } .podman-subnav button:hover { color: var(--text); } .podman-subnav button.active { color: var(--accent-strong); border-bottom-color: var(--accent); } .podman-subnav button .n { font-size: 10.5px; padding: 1px 5px; border-radius: 8px; background: var(--surface-3); color: var(--text-dim); } .podman-main { padding: 20px 0 48px; } .podman-panel { display: none; } .podman-panel.active { display: block; } .podman-card { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow); } .podman-card-pad { padding: 16px 18px; } .podman-card-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; border-bottom: 1px solid var(--border); } .podman-card-head h2 { font-size: 14.5px; } .podman-card-head .sub { font-size: 12px; color: var(--text-faint); font-weight: 500; } .podman-grid { display: grid; gap: 14px; } .podman-stat-grid { grid-template-columns: repeat(6, 1fr); } @media (max-width: 1080px) { .podman-stat-grid { grid-template-columns: repeat(3, 1fr); } } @media (max-width: 620px) { .podman-stat-grid { grid-template-columns: repeat(2, 1fr); } } .podman-stat { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px 16px; box-shadow: var(--shadow); } .podman-stat .label { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-faint); font-weight: 700; } .podman-stat .value { font-size: 24px; font-weight: 700; margin-top: 6px; } .podman-stat .value small { font-size: 13px; color: var(--text-dim); font-weight: 600; } .podman-stat .bar { height: 5px; border-radius: 3px; background: var(--surface-3); margin-top: 10px; overflow: hidden; } .podman-stat .bar > span { display: block; height: 100%; background: var(--accent); border-radius: 3px; } .podman-chip { display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: 100px; font-size: 11.5px; font-weight: 700; letter-spacing: .01em; white-space: nowrap; } .podman-chip .d { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; } .podman-chip-good { background: var(--good-bg); color: var(--good); } .podman-chip-warn { background: var(--warn-bg); color: var(--warn); } .podman-chip-bad { background: var(--bad-bg); color: var(--bad); } .podman-chip-neutral { background: var(--neutral-bg); color: var(--neutral); } .podman-plugin table { width: 100%; border-collapse: collapse; font-size: 13px; } .podman-plugin thead th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-faint); font-weight: 700; padding: 10px 18px; border-bottom: 1px solid var(--border); } .podman-plugin tbody td { padding: 11px 18px; border-bottom: 1px solid var(--border); vertical-align: middle; } .podman-plugin tbody tr:last-child td { border-bottom: none; } .podman-plugin tbody tr:hover { background: var(--surface-2); } .podman-table-wrap { overflow-x: auto; } .podman-row-name { display: flex; align-items: center; gap: 10px; font-weight: 600; } .podman-row-name-btn { appearance: none; border: none; background: none; padding: 0; cursor: pointer; color: var(--text); font-family: var(--font-ui); font-size: 13px; text-align: left; } .podman-row-name-btn:hover { color: var(--accent-strong); } .podman-row-name-btn:hover .ico { border-color: var(--accent); } .podman-row-name .ico { width: 26px; height: 26px; border-radius: 6px; flex: none; background: var(--surface-3); display: grid; place-items: center; font-size: 12px; border: 1px solid var(--border); color: var(--text-dim); } .podman-row-sub { font-size: 11.5px; color: var(--text-faint); font-weight: 500; margin-top: 1px; } .podman-actions { display: flex; gap: 4px; justify-content: flex-end; } .podman-usage-mini { display: flex; align-items: center; gap: 8px; min-width: 110px; } .podman-usage-mini .track { flex: 1; height: 5px; border-radius: 3px; background: var(--surface-3); overflow: hidden; } .podman-usage-mini .track > span { display: block; height: 100%; background: var(--accent); } .podman-usage-mini .num { font-size: 11.5px; color: var(--text-dim); width: 34px; text-align: right; } .podman-toolbar { display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid var(--border); flex-wrap: wrap; } .podman-search { flex: 1; min-width: 180px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; padding: 7px 11px; font-size: 13px; color: var(--text); font-family: var(--font-ui); } .podman-search::placeholder { color: var(--text-faint); } .podman-two-col { display: grid; grid-template-columns: 1.3fr 1fr; gap: 14px; align-items: start; } @media (max-width: 920px) { .podman-two-col { grid-template-columns: 1fr; } } .podman-activity-list { list-style: none; margin: 0; padding: 6px 0; } .podman-activity-list li { display: flex; gap: 10px; padding: 9px 18px; border-bottom: 1px solid var(--border); font-size: 12.5px; } .podman-activity-list li:last-child { border-bottom: none; } .podman-activity-list .dot { width: 7px; height: 7px; border-radius: 50%; margin-top: 5px; flex: none; } .podman-activity-list .when { color: var(--text-faint); font-size: 11px; margin-top: 1px; } .podman-empty-note { padding: 28px 18px; text-align: center; color: var(--text-faint); font-size: 13px; } .podman-pod-card { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; margin-bottom: 14px; background: var(--surface); box-shadow: var(--shadow); } .podman-pod-head { display: flex; align-items: center; gap: 10px; padding: 13px 16px; background: var(--surface-2); border-bottom: 1px solid var(--border); } .podman-pod-head .name { font-weight: 700; font-size: 13.5px; } .podman-pod-head .infra { font-size: 11.5px; color: var(--text-faint); } .podman-logs-layout { display: grid; grid-template-columns: 200px 1fr; min-height: 460px; } @media (max-width: 760px) { .podman-logs-layout { grid-template-columns: 1fr; } } .podman-logs-side { border-right: 1px solid var(--border); } .podman-logs-side .item { padding: 10px 14px; font-size: 12.5px; border-bottom: 1px solid var(--border); cursor: pointer; display: flex; align-items: center; gap: 8px; } .podman-logs-side .item.active { background: var(--surface-2); font-weight: 700; box-shadow: inset 2px 0 0 var(--accent); } .podman-log-pane { background: #0f1114; color: #c7ccd4; font-family: var(--font-mono); font-size: 12.3px; padding: 14px 16px; height: 400px; overflow-y: auto; line-height: 1.65; } .podman-log-pane .l { white-space: pre-wrap; word-break: break-word; } .podman-log-pane .ts { color: #6b7280; } .podman-log-pane .lvl-warn { color: #e0b23d; } .podman-log-pane .lvl-error { color: #ef6470; } .podman-term { background: #0f1114; color: #d7dbe0; font-family: var(--font-mono); font-size: 12.6px; border-radius: 8px; padding: 14px 16px; height: 380px; overflow-y: auto; line-height: 1.7; } .podman-term .prompt { color: #4cc785; } .podman-term .path { color: #6fb2f5; } .podman-term-input { width: 100%; margin-top: 10px; background: #0f1114; color: #d7dbe0; border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; font-family: var(--font-mono); font-size: 12.6px; } .podman-compose-layout { display: grid; grid-template-columns: 230px 1fr; min-height: 480px; } @media (max-width: 800px) { .podman-compose-layout { grid-template-columns: 1fr; } } .podman-compose-side { border-right: 1px solid var(--border); } .podman-compose-proj { padding: 12px 14px; border-bottom: 1px solid var(--border); cursor: pointer; } .podman-compose-proj.active { background: var(--surface-2); box-shadow: inset 2px 0 0 var(--accent); } .podman-compose-proj .path { font-size: 11px; color: var(--text-faint); margin-top: 2px; font-family: var(--font-mono); } .podman-yaml { background: #0f1114; color: #c7ccd4; font-family: var(--font-mono); font-size: 12.4px; padding: 16px 18px; height: 420px; overflow: auto; line-height: 1.7; white-space: pre-wrap; } .podman-field-row { display: grid; grid-template-columns: 220px 1fr; gap: 16px; padding: 14px 18px; border-bottom: 1px solid var(--border); align-items: start; } .podman-field-row:last-child { border-bottom: none; } .podman-field-row label { font-weight: 600; font-size: 13px; } .podman-field-row .hint { font-size: 11.5px; color: var(--text-faint); margin-top: 4px; max-width: 46ch; } .podman-field-row input[type="text"], .podman-field-row input[type="number"], .podman-field-row select { background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; padding: 8px 10px; font-size: 13px; color: var(--text); width: 100%; max-width: 340px; font-family: var(--font-ui); } .podman-danger-card { border-color: color-mix(in srgb, var(--bad) 40%, var(--border)); } .podman-danger-card .podman-card-head { border-bottom-color: color-mix(in srgb, var(--bad) 30%, var(--border)); } .podman-danger-card .podman-card-head h2 { color: var(--bad); } .podman-badge-update { font-size: 10px; font-weight: 700; color: var(--accent-strong); background: color-mix(in srgb, var(--accent) 16%, transparent); padding: 2px 7px; border-radius: 100px; margin-left: 8px; } .podman-loading, .podman-error { padding: 32px 18px; text-align: center; color: var(--text-faint); font-size: 13px; } /** * Modal form dialog — replaces browser-native prompt()/confirm() for any * action that needs more than a single yes/no (e.g. "New Volume" needs a * name AND an optional host path together, which prompt() can't express * as one coherent form). See app.js's openFormModal(). */ .podman-modal-backdrop { position: fixed; inset: 0; background: rgba(15, 17, 20, .55); z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 20px; } .podman-modal { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow); width: 100%; max-width: 420px; max-height: calc(100vh - 40px); overflow-y: auto; color: var(--text); font-family: var(--font-ui); } .podman-modal-head { padding: 16px 20px; border-bottom: 1px solid var(--border); } .podman-modal-head h3 { font-size: 15px; } .podman-modal-body { padding: 16px 20px; display: grid; gap: 14px; } .podman-modal-field label { display: block; font-weight: 600; font-size: 12.5px; margin-bottom: 6px; } .podman-modal-field input[type="text"] { background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; padding: 8px 10px; font-size: 13px; color: var(--text); width: 100%; font-family: var(--font-ui); } .podman-modal-field .hint { font-size: 11.5px; color: var(--text-faint); margin-top: 4px; } .podman-modal-field select { background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; padding: 8px 10px; font-size: 13px; color: var(--text); font-family: var(--font-ui); } .podman-modal-checkbox label { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 12.5px; margin-bottom: 0; } .podman-modal-error { font-size: 12.5px; color: var(--bad); background: var(--bad-bg); border-radius: 7px; padding: 8px 10px; } .podman-modal-actions { padding: 14px 20px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 8px; } .podman-error { color: var(--bad); } /* Wider variant + repeatable row groups, for forms with more than 1-2 fields (e.g. Create Container). */ .podman-modal-wide { max-width: 640px; } .podman-row-group { display: grid; gap: 8px; margin-bottom: 8px; } .podman-row-group-item { display: flex; align-items: center; gap: 8px; } .podman-row-group-item input[type="text"] { background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; padding: 7px 9px; font-size: 12.5px; color: var(--text); font-family: var(--font-mono); flex: 1; min-width: 0; } .podman-row-group-item select { background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; padding: 7px 9px; font-size: 12.5px; color: var(--text); font-family: var(--font-ui); flex: none; } .podman-row-group-item span { color: var(--text-faint); font-size: 12px; flex: none; } /* Anchored dropdown context menu — see app.js openContextMenu(). */ .podman-context-menu { position: absolute; width: 180px; background: var(--surface); border: 1px solid var(--border); border-radius: 9px; box-shadow: var(--shadow); z-index: 1001; padding: 4px; display: grid; gap: 1px; } .podman-context-menu button { appearance: none; border: none; background: none; text-align: left; padding: 8px 10px; font-size: 12.5px; font-weight: 600; color: var(--text); border-radius: 6px; cursor: pointer; font-family: var(--font-ui); width: 100%; } .podman-context-menu button:hover { background: var(--surface-2); } .podman-context-menu button.danger { color: var(--bad); } .podman-context-menu button[disabled] { opacity: .4; cursor: not-allowed; } .podman-context-menu-sep { height: 1px; background: var(--border); margin: 4px 2px; } /* Container detail modal — see containers.js openDetailModal(). */ .podman-modal-xwide { max-width: 760px; } .podman-detail-tabs { display: flex; gap: 2px; padding: 0 20px; border-bottom: 1px solid var(--border); overflow-x: auto; } .podman-detail-tabs button { appearance: none; background: none; border: none; border-bottom: 2px solid transparent; color: var(--text-dim); padding: 10px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer; white-space: nowrap; font-family: var(--font-ui); } .podman-detail-tabs button:hover { color: var(--text); } .podman-detail-tabs button.active { color: var(--accent-strong); border-bottom-color: var(--accent); } .podman-detail-body { padding: 16px 20px; max-height: 50vh; overflow-y: auto; } .podman-detail-table { width: 100%; border-collapse: collapse; font-size: 12.5px; } .podman-detail-table td { padding: 6px 0; border-bottom: 1px solid var(--border); vertical-align: top; } .podman-detail-table td:first-child { color: var(--text-faint); font-weight: 600; width: 160px; padding-right: 12px; } .podman-detail-table td.mono { font-family: var(--font-mono); word-break: break-all; } .podman-detail-json { background: #0f1114; color: #c7ccd4; font-family: var(--font-mono); font-size: 11.8px; padding: 14px 16px; border-radius: 8px; white-space: pre-wrap; word-break: break-all; line-height: 1.6; } .podman-detail-empty { color: var(--text-faint); font-size: 12.5px; padding: 8px 0; }