25592fa6c2
ci / test (push) Successful in 6m14s
History-free snapshot of the private development repository at 77a82eb. Code, docs and the public catalogue only: no plant or job knowledge layers, no client, job or producer names (tools/scrub.py clean against the widened term list; a second word-level grep clean). The intro deck is left out because its slide images cannot be checked for job drawings.
476 lines
11 KiB
CSS
476 lines
11 KiB
CSS
/* WillTools shared front-end look -- Panel Analysis's new 前端 today, the
|
|
shell every future tool (Beam Analysis, Connection Analysis) and every
|
|
results page adopts next. Reference: Eriksson Wall's own input dialogs --
|
|
plain engineering software, dense but tidy. Light theme, one accent
|
|
colour, system font stack, no build step, no framework. */
|
|
|
|
:root {
|
|
--bg: #f3f4f6;
|
|
--panel-bg: #ffffff;
|
|
--border: #d7dae0;
|
|
--border-strong: #b7bcc6;
|
|
--text: #1b1e23;
|
|
--text-muted: #6b7280;
|
|
--text-faint: #9aa1ac;
|
|
--accent: #2f6fed;
|
|
--accent-dark: #1f56c9;
|
|
--accent-contrast: #ffffff;
|
|
--error: #d33333;
|
|
--error-bg: #fdecec;
|
|
--warn: #b45309;
|
|
--warn-bg: #fff7ed;
|
|
--row-stripe: #fafbfc;
|
|
--row-hover: #eef2ff;
|
|
--radius: 4px;
|
|
--focus-ring: 0 0 0 3px rgba(47, 111, 237, 0.28);
|
|
color-scheme: light;
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
html, body {
|
|
height: 100%;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
|
|
font-size: 13px;
|
|
line-height: 1.45;
|
|
}
|
|
|
|
button, input, select, textarea {
|
|
font: inherit;
|
|
color: inherit;
|
|
}
|
|
|
|
/* --------------------------------------------------------------- layout */
|
|
|
|
.app-shell {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100vh;
|
|
}
|
|
|
|
.toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 8px 14px;
|
|
background: var(--panel-bg);
|
|
border-bottom: 1px solid var(--border);
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.toolbar-title {
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.pa-mark {
|
|
font-weight: 400;
|
|
color: var(--text-muted);
|
|
margin-left: 6px;
|
|
}
|
|
|
|
.toolbar-spacer { flex: 1 1 auto; }
|
|
|
|
.btn {
|
|
appearance: none;
|
|
border: 1px solid var(--border-strong);
|
|
background: #fff;
|
|
color: var(--text);
|
|
border-radius: var(--radius);
|
|
padding: 6px 14px;
|
|
font-size: 13px;
|
|
cursor: pointer;
|
|
}
|
|
.btn:hover { background: #f4f5f7; }
|
|
.btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
|
|
.btn-primary {
|
|
background: var(--accent);
|
|
border-color: var(--accent-dark);
|
|
color: var(--accent-contrast);
|
|
font-weight: 600;
|
|
}
|
|
.btn-primary:hover { background: var(--accent-dark); }
|
|
|
|
.banner {
|
|
flex: 0 0 auto;
|
|
background: var(--error-bg);
|
|
color: var(--error);
|
|
border-bottom: 1px solid #f3c2c2;
|
|
padding: 8px 14px;
|
|
font-size: 12.5px;
|
|
}
|
|
.banner[hidden] { display: none; }
|
|
/* Two faces, never alike: amber = input still needed (the user's to fill),
|
|
red = something broke (a bug). The bare `.banner` is red so an
|
|
unlabelled failure is loud, never calm. */
|
|
.banner.banner--input {
|
|
background: var(--warn-bg);
|
|
color: var(--warn);
|
|
border-bottom-color: #f2d9b6;
|
|
}
|
|
.banner.banner--crash {
|
|
background: var(--error-bg);
|
|
color: var(--error);
|
|
border-bottom-color: #f3c2c2;
|
|
}
|
|
|
|
.spec-problems {
|
|
flex: 0 0 auto;
|
|
background: var(--warn-bg);
|
|
color: var(--warn);
|
|
border-bottom: 1px solid #f2d9b6;
|
|
padding: 6px 14px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.tabs {
|
|
display: flex;
|
|
gap: 2px;
|
|
background: var(--panel-bg);
|
|
border-bottom: 1px solid var(--border);
|
|
padding: 0 10px;
|
|
flex: 0 0 auto;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.tab {
|
|
appearance: none;
|
|
border: none;
|
|
background: transparent;
|
|
padding: 10px 14px;
|
|
font-size: 13px;
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
border-bottom: 3px solid transparent;
|
|
white-space: nowrap;
|
|
}
|
|
.tab:hover { color: var(--text); }
|
|
.tab.active {
|
|
color: var(--text);
|
|
font-weight: 600;
|
|
border-bottom-color: var(--accent);
|
|
}
|
|
|
|
.pages {
|
|
flex: 1 1 auto;
|
|
overflow-y: auto;
|
|
background: var(--bg);
|
|
}
|
|
|
|
.page-panel {
|
|
display: none;
|
|
padding: 18px 20px 60px;
|
|
max-width: 1180px;
|
|
margin: 0 auto;
|
|
}
|
|
.page-panel.active { display: block; }
|
|
|
|
/* -------------------------------------------------------------- headings */
|
|
|
|
h1.pa-h, h2.pa-h, h3.pa-h {
|
|
margin: 18px 0 8px;
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
}
|
|
h1.pa-h { font-size: 17px; border-bottom: 1px solid var(--border); padding-bottom: 6px; }
|
|
h2.pa-h { font-size: 14.5px; margin-top: 20px; }
|
|
h3.pa-h { font-size: 13.5px; color: var(--text-muted); }
|
|
|
|
hr.pa-rule {
|
|
border: none;
|
|
border-top: 1px solid var(--border);
|
|
margin: 14px 0;
|
|
}
|
|
|
|
.pa-space { display: block; }
|
|
|
|
/* -------------------------------------------------------------- columns */
|
|
|
|
.pa-columns {
|
|
display: flex;
|
|
gap: 22px;
|
|
align-items: flex-start;
|
|
}
|
|
.pa-col {
|
|
flex: 1 1 0;
|
|
min-width: 0;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------- field */
|
|
|
|
.field {
|
|
margin-bottom: 10px;
|
|
max-width: 420px;
|
|
}
|
|
.field.full-width { max-width: none; }
|
|
.field-label-row {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 5px;
|
|
margin-bottom: 3px;
|
|
}
|
|
.field-label {
|
|
font-size: 12.5px;
|
|
color: var(--text-muted);
|
|
}
|
|
.field.required .field-label::after {
|
|
content: " *";
|
|
color: var(--error);
|
|
}
|
|
.field-symbol {
|
|
font-size: 11px;
|
|
color: var(--text-faint);
|
|
}
|
|
.field-input {
|
|
width: 100%;
|
|
padding: 5px 7px;
|
|
border: 1px solid var(--border-strong);
|
|
border-radius: var(--radius);
|
|
background: #fff;
|
|
}
|
|
.field-input:focus {
|
|
outline: none;
|
|
border-color: var(--accent);
|
|
box-shadow: var(--focus-ring);
|
|
}
|
|
textarea.field-input { resize: vertical; min-height: 44px; }
|
|
.field-input.has-error {
|
|
border-color: var(--error);
|
|
background: var(--error-bg);
|
|
}
|
|
.field-error-msg {
|
|
color: var(--error);
|
|
font-size: 11px;
|
|
margin-top: 2px;
|
|
}
|
|
.field-check-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.field-check-row .field-label { margin: 0; }
|
|
|
|
/* "not used by the solve" (docs/pa-web-spec.md, unused_by_solve) --
|
|
collected only; muted so it can never pass for a live input */
|
|
.unused-by-solve .field-input,
|
|
tr.unused-by-solve .field-input { opacity: 0.55; }
|
|
.unused-by-solve .field-label,
|
|
tr.unused-by-solve td:first-child { color: var(--text-muted); }
|
|
.unused-tag {
|
|
display: inline-block;
|
|
margin-left: 6px;
|
|
padding: 0 5px;
|
|
border: 1px dashed var(--text-faint);
|
|
border-radius: 3px;
|
|
color: var(--text-muted);
|
|
font-size: 10px;
|
|
line-height: 15px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
/* row-table empty state + table-level error (issue #22) */
|
|
.table-empty-state {
|
|
color: var(--text-muted);
|
|
font-size: 12px;
|
|
font-style: italic;
|
|
margin: 4px 0;
|
|
}
|
|
.editable-table-wrap.has-error table.pa-editable {
|
|
outline: 2px solid var(--error);
|
|
background: var(--error-bg);
|
|
}
|
|
.table-error-msg {
|
|
color: var(--error);
|
|
font-size: 11px;
|
|
margin: 2px 0;
|
|
}
|
|
|
|
/* provenance */
|
|
.prov-icon {
|
|
display: inline-block;
|
|
width: 13px;
|
|
height: 13px;
|
|
line-height: 13px;
|
|
text-align: center;
|
|
border-radius: 50%;
|
|
font-size: 10px;
|
|
color: var(--accent);
|
|
cursor: help;
|
|
border: 1px solid var(--accent);
|
|
}
|
|
|
|
/* ------------------------------------------------------------ sentence */
|
|
|
|
.sentence { margin: 6px 0; color: var(--text); }
|
|
.sentence.emph { font-weight: 600; }
|
|
|
|
/* ------------------------------------------------------------------ kv */
|
|
|
|
table.kv-table { border-collapse: collapse; margin: 6px 0 12px; }
|
|
table.kv-table td { padding: 3px 10px 3px 0; vertical-align: top; font-size: 12.5px; }
|
|
table.kv-table td:first-child { color: var(--text-muted); white-space: nowrap; }
|
|
|
|
/* --------------------------------------------------------------- tables */
|
|
|
|
table.pa-table, table.pa-editable, table.pa-matrix, table.pa-lc {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
margin: 6px 0 14px;
|
|
font-size: 12.5px;
|
|
}
|
|
table.pa-table th, table.pa-table td,
|
|
table.pa-editable th, table.pa-editable td,
|
|
table.pa-matrix th, table.pa-matrix td,
|
|
table.pa-lc th, table.pa-lc td {
|
|
border: 1px solid var(--border);
|
|
padding: 4px 6px;
|
|
text-align: left;
|
|
vertical-align: middle;
|
|
}
|
|
table.pa-table th, table.pa-editable th, table.pa-matrix th, table.pa-lc th {
|
|
background: #eef1f5;
|
|
font-weight: 600;
|
|
color: var(--text-muted);
|
|
white-space: nowrap;
|
|
}
|
|
table.pa-table tbody tr:nth-child(even),
|
|
table.pa-editable tbody tr:nth-child(even) {
|
|
background: var(--row-stripe);
|
|
}
|
|
table.pa-table td input.field-input,
|
|
table.pa-editable td input.field-input,
|
|
table.pa-editable td select.field-input,
|
|
table.pa-matrix td input.field-input,
|
|
table.pa-matrix td select.field-input,
|
|
table.pa-lc td input.field-input {
|
|
padding: 3px 5px;
|
|
min-width: 44px;
|
|
}
|
|
table.pa-matrix td.na-cell {
|
|
text-align: center;
|
|
color: var(--text-faint);
|
|
}
|
|
table.pa-matrix th, table.pa-matrix td:first-child {
|
|
white-space: normal;
|
|
}
|
|
td.row-remove { text-align: center; width: 28px; }
|
|
.row-remove-btn, .row-check {
|
|
cursor: pointer;
|
|
color: var(--text-muted);
|
|
border: none;
|
|
background: none;
|
|
font-size: 14px;
|
|
}
|
|
.row-remove-btn:hover { color: var(--error); }
|
|
.add-row-btn {
|
|
margin: 2px 0 14px;
|
|
}
|
|
|
|
/* -------------------------------------------------------------- legend */
|
|
|
|
.legend {
|
|
display: flex;
|
|
gap: 18px;
|
|
flex-wrap: wrap;
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
margin: 4px 0 10px;
|
|
}
|
|
.legend-group-title { font-weight: 600; margin-right: 6px; }
|
|
.legend-item { display: inline-flex; align-items: center; gap: 4px; }
|
|
.legend-glyph { font-size: 13px; }
|
|
|
|
/* ------------------------------------------------------------- drawing */
|
|
|
|
.drawing-block {
|
|
margin: 10px 0 16px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
background: var(--panel-bg);
|
|
padding: 8px 10px;
|
|
}
|
|
.drawing-caption {
|
|
font-size: 12px;
|
|
color: var(--text-muted);
|
|
margin-bottom: 6px;
|
|
}
|
|
.drawing-host { width: 100%; }
|
|
.drawing-problems {
|
|
font-size: 11px;
|
|
color: var(--warn);
|
|
margin-top: 4px;
|
|
}
|
|
.drawing-problems:empty { display: none; }
|
|
|
|
/* -------------------------------------------------------------- details */
|
|
|
|
details.pa-section {
|
|
margin: 10px 0;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius);
|
|
background: var(--panel-bg);
|
|
}
|
|
details.pa-section > summary {
|
|
cursor: pointer;
|
|
padding: 8px 10px;
|
|
font-weight: 600;
|
|
font-size: 13px;
|
|
list-style: none;
|
|
}
|
|
details.pa-section > summary::-webkit-details-marker { display: none; }
|
|
details.pa-section > summary::before {
|
|
content: "▸ ";
|
|
color: var(--text-muted);
|
|
}
|
|
details.pa-section[open] > summary::before { content: "▾ "; }
|
|
details.pa-section > .pa-section-body { padding: 4px 12px 12px; }
|
|
|
|
details.pa-notes {
|
|
margin: 20px 0 4px;
|
|
border: 1px dashed var(--border-strong);
|
|
border-radius: var(--radius);
|
|
background: #fbfbfc;
|
|
}
|
|
details.pa-notes > summary {
|
|
cursor: pointer;
|
|
padding: 7px 10px;
|
|
color: var(--text-muted);
|
|
font-size: 12.5px;
|
|
list-style: none;
|
|
}
|
|
details.pa-notes > summary::-webkit-details-marker { display: none; }
|
|
.pa-notes-body { padding: 2px 14px 12px; font-size: 12px; color: var(--text-muted); }
|
|
.pa-notes-body h4 { margin: 8px 0 4px; font-size: 11.5px; text-transform: uppercase; letter-spacing: .03em; color: var(--text-faint); }
|
|
.pa-notes-body ul { margin: 0 0 6px; padding-left: 18px; }
|
|
.pa-notes-body li { margin-bottom: 3px; }
|
|
|
|
.unknown-block {
|
|
background: #fff3cd;
|
|
border: 1px solid #ffe08a;
|
|
border-radius: var(--radius);
|
|
padding: 6px 10px;
|
|
font-size: 12px;
|
|
margin: 6px 0;
|
|
}
|
|
|
|
#errors {
|
|
position: fixed;
|
|
left: 0; right: 0; bottom: 0;
|
|
max-height: 30vh;
|
|
overflow: auto;
|
|
margin: 0;
|
|
background: #2b0000;
|
|
color: #ffd9d9;
|
|
font-size: 11px;
|
|
padding: 8px 10px;
|
|
z-index: 999;
|
|
white-space: pre-wrap;
|
|
}
|
|
#errors[hidden] { display: none; }
|