Files
physicalCombinatorics/src/physcom_web/static/style.css
Andrew Simonson d871635779 score-optimize actuator/storage/platform allocation, enforce structural feasibility
The saved composite score previously came from a requirement-solve that
only satisfied the platform's physical performance floor, not the
domain's actual weighted score -- a smaller/cheaper build could always
score higher by hand. _decide_masses now jointly searches platform,
actuator, and storage mass (coarse-to-fine grid, no external deps) to
maximize the domain's real weighted composite score, with the
requirement floor as a lower bound rather than the final answer.

Platform mass specifically was previously fixed at a geometric-mean
representative value, which could be too little structure to carry its
own required actuator+storage (reusing CARGO_KG_PER_STRUCTURAL_KG, the
existing structure-carries-N-times-its-mass ratio, applied to a
platform carrying its own powertrain instead of cargo). Growing
platform mass also raises that structural ceiling, so it has to be
searched jointly rather than fixed or bounded independently.

Because power_density/range_fuel/cost_efficiency are all per-kg
ratios, none of them naturally penalize a build whose absolute mass
exceeds its own platform's declared ceiling -- a Piston Engine sized
for a Hyperloop could still score well on a Light Personal Vehicle.
Pass 2 now detects genuine infeasibility (no platform mass within its
own declared ceiling can structurally carry the required floor) and
saves it as a per-domain block instead of a misleadingly good score.

Also adds an explore-panel warning (not a hard block, since exploration
is intentionally loose) when a manually-dragged slider build exceeds
the platform's mass ceiling or structural carrying capacity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 18:59:20 -05:00

707 lines
23 KiB
CSS

/* ══════════════════════════════════════════════════════════
PhysCom — Dark Mathematical Serenity Theme
══════════════════════════════════════════════════════════ */
/* ── Custom Properties ──────────────────────────────────── */
:root {
--bg-deep: #0d1117;
--bg-surface: #161b22;
--bg-card: #1c2128;
--bg-elevated: #252c35;
--border: #2a3140;
--border-subtle: #222833;
--text-primary: #d4dae3;
--text-secondary:#8b95a5;
--text-muted: #5c6575;
--text-faint: #3d4555;
--accent-gold: #c9a84c;
--accent-blue: #6b9fbd;
--accent-teal: #6ba3a0;
--accent-green: #7aab8a;
--accent-red: #b85c5c;
--accent-amber: #b8935c;
--accent-violet: #9b8ec4;
--font-body: 'Inter', system-ui, -apple-system, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
--font-display: 'Cormorant Garamond', 'Garamond', 'Georgia', serif;
--radius: 6px;
--radius-lg: 10px;
}
/* ── Reset & Base ───────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: var(--font-body);
line-height: 1.6;
color: var(--text-primary);
background: var(--bg-deep);
min-height: 100vh;
}
/* Subtle grid texture on body */
body::before {
content: '';
position: fixed;
inset: 0;
background-image:
linear-gradient(var(--border-subtle) 1px, transparent 1px),
linear-gradient(90deg, var(--border-subtle) 1px, transparent 1px);
background-size: 60px 60px;
opacity: 0.25;
pointer-events: none;
z-index: 0;
}
body > * { position: relative; z-index: 1; }
a { color: var(--accent-blue); text-decoration: none; transition: color 0.2s; }
a:hover { color: #8dbdd6; text-decoration: none; }
::selection {
background: rgba(107, 159, 189, 0.3);
color: var(--text-primary);
}
/* ── Nav ─────────────────────────────────────────────────── */
nav {
background: var(--bg-surface);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
padding: 0 1.5rem;
gap: 2rem;
height: 52px;
}
.nav-brand {
display: flex;
align-items: center;
gap: 0.6rem;
color: var(--text-primary) !important;
font-family: var(--font-display);
font-weight: 600;
font-size: 1.2rem;
letter-spacing: 0.04em;
text-decoration: none !important;
}
.nav-brand img {
width: 28px;
height: 28px;
opacity: 0.9;
}
.nav-brand:hover { color: var(--accent-gold) !important; }
.nav-brand:hover img { opacity: 1; }
nav ul { list-style: none; display: flex; gap: 0.25rem; }
nav a {
color: var(--text-secondary);
padding: 0.4rem 0.75rem;
border-radius: var(--radius);
font-size: 0.88rem;
font-weight: 500;
transition: color 0.2s, background 0.2s;
}
nav a:hover {
color: var(--text-primary);
background: var(--bg-elevated);
text-decoration: none;
}
/* ── Main ────────────────────────────────────────────────── */
main {
max-width: 1100px;
margin: 1.5rem auto;
padding: 0 1.25rem;
}
/* ── Page header ─────────────────────────────────────────── */
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
h1 {
font-size: 1.5rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.75rem;
}
h2 {
font-size: 1.15rem;
font-weight: 600;
color: var(--text-primary);
margin: 1.25rem 0 0.5rem;
}
h3 {
font-size: 1rem;
font-weight: 600;
margin-bottom: 0.25rem;
color: var(--text-primary);
}
.subtitle { font-weight: 400; color: var(--text-secondary); font-size: 0.9rem; }
/* ── Cards ───────────────────────────────────────────────── */
.card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 1rem 1.25rem;
margin-bottom: 1rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 1rem;
}
.card-grid > * { min-width: 0; overflow-x: auto; }
/* ── Tables ──────────────────────────────────────────────── */
table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
th, td {
padding: 0.5rem 0.6rem;
text-align: left;
border-bottom: 1px solid var(--border-subtle);
}
th {
font-weight: 600;
color: var(--text-muted);
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.06em;
}
tr:hover td { background: rgba(107, 159, 189, 0.04); }
table.compact th, table.compact td { padding: 0.25rem 0.4rem; font-size: 0.83rem; }
/* ── Score cells ─────────────────────────────────────────── */
.score-cell {
font-family: var(--font-mono);
font-weight: 500;
font-size: 0.85rem;
color: var(--accent-gold);
}
/* ── Badges ──────────────────────────────────────────────── */
.badge {
display: inline-block;
padding: 0.15rem 0.55rem;
border-radius: 4px;
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.03em;
background: var(--bg-elevated);
color: var(--text-secondary);
border: 1px solid var(--border);
}
.badge-requires { background: rgba(107,159,189,0.12); color: var(--accent-blue); border-color: rgba(107,159,189,0.25); }
.badge-provides { background: rgba(122,171,138,0.12); color: var(--accent-green); border-color: rgba(122,171,138,0.25); }
.badge-range_min,
.badge-range_max { background: rgba(184,147,92,0.12); color: var(--accent-amber); border-color: rgba(184,147,92,0.25); }
.badge-excludes { background: rgba(184,92,92,0.12); color: var(--accent-red); border-color: rgba(184,92,92,0.25); }
.badge-valid { background: rgba(122,171,138,0.12); color: var(--accent-green); border-color: rgba(122,171,138,0.25); }
.badge-p1_fail,
.badge-p2_fail,
.badge-p3_fail,
.badge-p4_fail { background: rgba(184,92,92,0.12); color: var(--accent-red); border-color: rgba(184,92,92,0.25); }
.badge-scored { background: rgba(107,159,189,0.12); color: var(--accent-blue); border-color: rgba(107,159,189,0.25); }
.badge-llm_reviewed { background: rgba(107,163,160,0.12); color: var(--accent-teal); border-color: rgba(107,163,160,0.25); }
.badge-reviewed { background: rgba(155,142,196,0.12); color: var(--accent-violet); border-color: rgba(155,142,196,0.25); }
.badge-pending { background: rgba(184,147,92,0.12); color: var(--accent-amber); border-color: rgba(184,147,92,0.25); }
.badge-rating-low { background: rgba(184,92,92,0.12); color: var(--accent-red); border-color: rgba(184,92,92,0.25); }
.badge-rating-medium { background: rgba(184,147,92,0.12); color: var(--accent-amber); border-color: rgba(184,147,92,0.25); }
.badge-rating-high { background: rgba(122,171,138,0.12); color: var(--accent-green); border-color: rgba(122,171,138,0.25); }
/* ── Buttons ─────────────────────────────────────────────── */
.btn {
display: inline-block;
padding: 0.4rem 0.85rem;
border: 1px solid var(--border);
border-radius: var(--radius);
background: var(--bg-elevated);
color: var(--text-primary);
font-size: 0.85rem;
cursor: pointer;
text-decoration: none;
transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.btn:hover {
background: var(--bg-card);
border-color: var(--text-muted);
text-decoration: none;
}
.btn-primary {
background: rgba(107,159,189,0.15);
color: var(--accent-blue);
border-color: rgba(107,159,189,0.35);
}
.btn-primary:hover {
background: rgba(107,159,189,0.25);
border-color: rgba(107,159,189,0.5);
}
.btn-danger {
background: rgba(184,92,92,0.12);
color: var(--accent-red);
border-color: rgba(184,92,92,0.3);
}
.btn-danger:hover {
background: rgba(184,92,92,0.22);
border-color: rgba(184,92,92,0.5);
}
.btn-sm { padding: 0.2rem 0.55rem; font-size: 0.8rem; }
/* ── Forms ───────────────────────────────────────────────── */
.form-group { margin-bottom: 0.75rem; }
.form-group label {
display: block;
font-weight: 600;
font-size: 0.85rem;
margin-bottom: 0.25rem;
color: var(--text-primary);
}
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 0.45rem 0.65rem;
border: 1px solid var(--border);
border-radius: var(--radius);
font-size: 0.9rem;
background: var(--bg-surface);
color: var(--text-primary);
transition: border-color 0.2s;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--accent-blue);
box-shadow: 0 0 0 2px rgba(107,159,189,0.15);
}
.form-actions { margin-top: 1rem; display: flex; gap: 0.5rem; }
.form-row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
.form-row input, .form-row select { width: auto; flex: 1; min-width: 80px; }
fieldset {
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0.75rem;
margin-bottom: 0.75rem;
}
legend {
font-weight: 600;
font-size: 0.85rem;
padding: 0 0.3rem;
color: var(--text-primary);
}
.checkbox-row { display: flex; gap: 1rem; flex-wrap: wrap; }
.checkbox-row label {
display: flex;
align-items: center;
gap: 0.3rem;
font-size: 0.9rem;
color: var(--text-primary);
}
/* Custom checkbox styling */
input[type="checkbox"] {
appearance: none;
width: 16px;
height: 16px;
border: 1px solid var(--text-muted);
border-radius: 3px;
background: var(--bg-surface);
cursor: pointer;
flex-shrink: 0;
position: relative;
transition: background 0.15s, border-color 0.15s;
}
input[type="checkbox"]:checked {
background: var(--accent-blue);
border-color: var(--accent-blue);
}
input[type="checkbox"]:checked::after {
content: '';
position: absolute;
left: 4px;
top: 1px;
width: 5px;
height: 9px;
border: solid var(--bg-deep);
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
input[type="checkbox"]:focus {
outline: none;
box-shadow: 0 0 0 2px rgba(107,159,189,0.2);
}
/* ── Inline form (for delete buttons) ────────────────────── */
.inline-form { display: inline; }
/* ── Flash messages ──────────────────────────────────────── */
.flash-container { margin-bottom: 1rem; }
.flash {
padding: 0.6rem 1rem;
border-radius: var(--radius);
margin-bottom: 0.5rem;
font-size: 0.9rem;
border: 1px solid;
}
.flash-success { background: rgba(122,171,138,0.1); color: var(--accent-green); border-color: rgba(122,171,138,0.25); }
.flash-error { background: rgba(184,92,92,0.1); color: var(--accent-red); border-color: rgba(184,92,92,0.25); }
.flash-info { background: rgba(107,159,189,0.1); color: var(--accent-blue); border-color: rgba(107,159,189,0.25); }
/* ── Filter row ──────────────────────────────────────────── */
.filter-row { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 1rem; }
.filter-row span { font-weight: 600; font-size: 0.85rem; color: var(--text-muted); }
/* ── DL styling ──────────────────────────────────────────── */
dl { display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 1rem; }
dt { font-weight: 600; font-size: 0.83rem; color: var(--text-muted); }
dd { font-size: 0.9rem; color: var(--text-primary); }
/* ── Empty state ─────────────────────────────────────────── */
.empty {
color: var(--text-muted);
padding: 2.5rem 0;
text-align: center;
font-style: italic;
}
/* ── Actions column ──────────────────────────────────────── */
.actions { white-space: nowrap; display: flex; gap: 0.25rem; }
/* ── Dep add form ────────────────────────────────────────── */
.dep-add-form { margin-top: 0.75rem; }
/* ── Form hints ──────────────────────────────────────────── */
.form-hint { color: var(--text-muted); font-size: 0.8rem; margin-bottom: 0.25rem; font-weight: 400; }
/* ── Vertical checkbox list ──────────────────────────────── */
.checkbox-col { display: flex; flex-direction: column; gap: 0.6rem; }
.checkbox-col label {
display: flex;
align-items: baseline;
gap: 0.4rem;
font-size: 0.9rem;
color: var(--text-primary);
}
.checkbox-col label .form-hint { display: block; margin-left: 1.3rem; }
/* ── Summary DL (pipeline) ───────────────────────────────── */
.summary-dl { display: grid; grid-template-columns: auto 1fr; gap: 0.15rem 1rem; }
/* ── Pipeline run status ──────────────────────────────────── */
.badge-running { background: rgba(107,159,189,0.12); color: var(--accent-blue); border-color: rgba(107,159,189,0.25); }
.badge-completed { background: rgba(122,171,138,0.12); color: var(--accent-green); border-color: rgba(122,171,138,0.25); }
.badge-failed { background: rgba(184,92,92,0.12); color: var(--accent-red); border-color: rgba(184,92,92,0.25); }
.badge-cancelled { background: rgba(184,147,92,0.12); color: var(--accent-amber); border-color: rgba(184,147,92,0.25); }
.badge-rate_limited { background: rgba(184,147,92,0.12); color: var(--accent-amber); border-color: rgba(184,147,92,0.25); }
.run-status { padding: 0.25rem 0; }
.run-status-header { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; }
.run-status-label { font-weight: 600; font-size: 0.9rem; color: var(--text-primary); }
.progress-bar-container {
background: var(--bg-elevated);
border-radius: 4px;
height: 8px;
overflow: hidden;
margin-bottom: 0.35rem;
border: 1px solid var(--border-subtle);
}
.progress-bar {
background: linear-gradient(90deg, var(--accent-blue), var(--accent-teal));
height: 100%;
border-radius: 3px;
transition: width 0.3s ease;
}
.run-status-counters {
display: flex;
gap: 1rem;
font-size: 0.8rem;
color: var(--text-muted);
margin-bottom: 0.35rem;
}
.run-status-actions { margin-top: 0.35rem; }
/* ── Block reason ───────────────────────────────────────── */
.block-reason-cell {
font-size: 0.8rem;
color: var(--text-muted);
max-width: 350px;
word-break: break-word;
}
/* ── Metric position bar ────────────────────────────────── */
.metric-bar-container {
display: inline-block;
width: 60px;
height: 6px;
background: var(--bg-elevated);
border-radius: 3px;
overflow: hidden;
vertical-align: middle;
border: 1px solid var(--border-subtle);
}
.metric-bar {
height: 100%;
background: linear-gradient(90deg, var(--accent-blue), var(--accent-gold));
border-radius: 2px;
}
.metric-bar-label {
font-size: 0.75rem;
color: var(--text-muted);
margin-left: 0.3rem;
}
/* ── Mass allocation bar (optimizer) ───────────────────────── */
.mass-bar-container {
display: flex;
width: 100%;
height: 18px;
border-radius: 4px;
overflow: hidden;
border: 1px solid var(--border-subtle);
margin-top: 0.5rem;
}
.mass-bar-seg { height: 100%; }
.mass-bar-platform { background: var(--accent-blue); }
.mass-bar-actuator { background: var(--accent-gold); }
.mass-bar-storage { background: var(--accent-teal); }
.mass-bar-legend {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 1rem;
font-size: 0.8rem;
color: var(--text-muted);
margin-top: 0.4rem;
align-items: center;
}
.mass-swatch {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 2px;
margin-right: 0.35rem;
vertical-align: middle;
}
.optimize-summary { margin-bottom: 0.25rem; }
.optimize-score { display: flex; flex-direction: column; gap: 0.1rem; }
/* ── Importance sliders (optimizer) ────────────────────────── */
.weight-slider-row {
display: grid;
grid-template-columns: 140px 1fr 48px;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.5rem;
}
.weight-slider-row label { font-size: 0.85rem; color: var(--text-muted); }
.weight-slider-row output { font-size: 0.85rem; text-align: right; font-variant-numeric: tabular-nums; }
.weight-slider-row input[type="range"] { width: 100%; }
/* ── Select dropdown dark styling ────────────────────────── */
select option {
background: var(--bg-surface);
color: var(--text-primary);
}
/* ── Scrollbar (WebKit) ──────────────────────────────────── */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg-deep); }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
/* ══════════════════════════════════════════════════════════
Homepage
══════════════════════════════════════════════════════════ */
/* ── Hero ────────────────────────────────────────────────── */
.hero {
text-align: center;
padding: 3rem 1rem 2.5rem;
}
.hero-logo img {
width: 72px;
height: 72px;
margin-bottom: 1rem;
opacity: 0.85;
}
.hero-title {
font-family: var(--font-display);
font-size: 2rem;
font-weight: 500;
letter-spacing: 0.03em;
color: var(--text-primary);
margin-bottom: 0.6rem;
}
.hero-subtitle {
max-width: 600px;
margin: 0 auto 1.5rem;
font-size: 0.95rem;
line-height: 1.7;
color: var(--text-secondary);
}
.hero-actions {
display: flex;
justify-content: center;
gap: 0.75rem;
}
/* ── Section headings ────────────────────────────────────── */
.section-heading {
font-size: 1.15rem;
font-weight: 600;
margin: 2rem 0 0.35rem;
color: var(--text-primary);
padding-bottom: 0.35rem;
border-bottom: 1px solid var(--border);
}
.section-desc {
font-size: 0.9rem;
color: var(--text-secondary);
margin-bottom: 1.25rem;
max-width: 700px;
}
/* ── Pipeline steps ──────────────────────────────────────── */
.pipeline-steps {
display: flex;
flex-direction: column;
gap: 0;
margin-bottom: 1.5rem;
}
.step-card {
display: flex;
gap: 1rem;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 1rem 1.25rem;
}
.step-number {
flex-shrink: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
font-family: var(--font-mono);
font-size: 0.8rem;
font-weight: 600;
background: rgba(107,159,189,0.12);
color: var(--accent-blue);
border: 1px solid rgba(107,159,189,0.25);
}
.step-body h3 {
font-size: 0.95rem;
margin-bottom: 0.3rem;
}
.step-body p {
font-size: 0.87rem;
color: var(--text-secondary);
line-height: 1.6;
}
.step-example {
margin-top: 0.5rem;
font-size: 0.8rem;
color: var(--text-muted);
padding: 0.4rem 0.65rem;
background: var(--bg-surface);
border-radius: var(--radius);
border-left: 2px solid var(--border);
}
.step-example code {
font-family: var(--font-mono);
font-size: 0.78rem;
color: var(--accent-gold);
}
.step-connector {
width: 1px;
height: 16px;
background: var(--border);
margin-left: 39px;
}
/* ── Concepts grid ───────────────────────────────────────── */
.concepts-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.concept-card p {
font-size: 0.87rem;
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: 0.6rem;
}
.concept-card em { color: var(--text-primary); font-style: normal; font-weight: 500; }
.concept-card code {
font-family: var(--font-mono);
font-size: 0.8rem;
color: var(--accent-gold);
background: var(--bg-surface);
padding: 0.1rem 0.35rem;
border-radius: 3px;
}
.concept-examples {
display: flex;
flex-wrap: wrap;
gap: 0.35rem;
margin-bottom: 0.6rem;
}
.concept-link {
font-size: 0.83rem;
color: var(--accent-blue);
}
/* ── Stats row ───────────────────────────────────────────── */
.stats-row {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.stat-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: 1rem;
text-align: center;
}
.stat-value {
font-family: var(--font-mono);
font-size: 1.6rem;
font-weight: 500;
color: var(--accent-gold);
line-height: 1.2;
}
.stat-label {
font-size: 0.78rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-top: 0.25rem;
}
/* ── Admin warning box ──────────────────────────────────── */
.warning-box {
border-color: rgba(184,147,92,0.4);
background: rgba(184,147,92,0.06);
}
/* ── Google Fonts import ─────────────────────────────────── */
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap');