Refactor web UI: CSS classes only, no inline styles; fix footer; add full lab1.zip

- Replace all inline style= with reusable CSS classes
- Add layout classes: page, page-header, page-main, page-footer
- Fix footer at bottom via flex column + flex:1 on main
- Remove jsessionid from static resource URLs
- Create lab1-full.zip with 30 variants from PDF metodichka
- All templates use CSS var classes for light/dark theme
This commit is contained in:
2026-09-10 21:29:10 +03:00
parent 9b7748571e
commit b4c801853a
10 changed files with 230 additions and 275 deletions

View File

@@ -1,6 +1,15 @@
*, *::before, *::after { box-sizing: border-box; }
html { height: 100%; }
html, body { height: 100%; margin: 0; }
body {
display: flex;
flex-direction: column;
background: var(--c-bg);
color: var(--c-text);
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
line-height: 1.5;
}
:root {
--c-bg: #f8fafc;
@@ -32,31 +41,40 @@ html { height: 100%; }
--c-badge-warn-text: #fcd34d;
}
body {
margin: 0;
background: var(--c-bg);
color: var(--c-text);
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
line-height: 1.5;
}
a { color: var(--c-text-link); }
a:hover { color: var(--c-text-link-hover); }
/* Layout */
.page { display: flex; flex-direction: column; min-height: 100vh; }
.page-header { position: sticky; top: 0; z-index: 10; border-bottom: 1px solid var(--c-border); background: var(--c-surface); }
.page-header-inner { max-width: 1152px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1.5rem; }
.page-main { flex: 1; width: 100%; max-width: 1152px; margin: 0 auto; padding: 2rem 1.5rem; }
.page-footer { border-top: 1px solid var(--c-border); padding: 1rem; text-align: center; font-size: 0.75rem; color: var(--c-text-muted); }
/* Nav */
.nav { display: flex; align-items: center; gap: 1rem; font-size: 0.875rem; }
.nav-link { color: var(--c-text-link); text-decoration: none; }
.nav-link:hover { color: var(--c-text-link-hover); }
.nav-sep { color: var(--c-text-muted); }
.logo { font-size: 1.125rem; font-weight: 600; color: var(--c-text); text-decoration: none; }
/* Buttons */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
border-radius: 0.5rem; padding: 0.5rem 1rem; font-size: 0.875rem; font-weight: 500;
border: none; cursor: pointer; transition: opacity 0.15s;
}
.btn:active { opacity: 0.8; }
.btn-primary { background: var(--c-accent); color: white; }
.btn-sm { padding: 0.25rem 0.5rem; font-size: 0.75rem; }
.btn-primary { background: var(--c-accent); color: white; text-decoration: none; }
.btn-primary:hover { opacity: 0.9; }
.btn-secondary {
background: var(--c-surface); color: var(--c-text);
background: var(--c-surface); color: var(--c-text); text-decoration: none;
box-shadow: inset 0 0 0 1px var(--c-border);
}
.btn-secondary:hover { background: var(--c-border); }
/* Forms */
.input {
width: 100%; border-radius: 0.5rem; background: var(--c-bg); color: var(--c-text);
padding: 0.5rem 0.75rem; font-size: 0.875rem; border: 1px solid var(--c-border);
@@ -64,18 +82,92 @@ a:hover { color: var(--c-text-link-hover); }
}
.input:focus { border-color: var(--c-accent); box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2); }
.input::placeholder { color: var(--c-text-muted); }
.label { display: block; margin-bottom: 0.25rem; font-size: 0.875rem; font-weight: 500; }
.hint { margin-top: 0.25rem; font-size: 0.75rem; color: var(--c-text-muted); }
.card {
border-radius: 0.75rem; background: var(--c-surface); border: 1px solid var(--c-border);
}
/* Cards */
.card { border-radius: 0.75rem; background: var(--c-surface); border: 1px solid var(--c-border); }
.card-flush { border-radius: 0.75rem; background: var(--c-surface); border: 1px solid var(--c-border); padding: 0; }
.card-body { padding: 1.5rem; }
/* Grid */
.grid { display: grid; gap: 1rem; }
.grid-2 { grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr)); }
.grid-stats { grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); }
/* Typography */
.page-title { margin: 0 0 1.5rem; font-size: 1.5rem; font-weight: 600; }
.section-title { margin: 0 0 0.75rem; font-size: 1.125rem; font-weight: 500; }
.stat-value { margin: 0.5rem 0 0; font-size: 1.875rem; font-weight: 600; }
.stat-title { font-size: 0.875rem; color: var(--c-text-muted); margin: 0; }
.text-muted { color: var(--c-text-muted); }
.opacity-30 { opacity: 0.3; }
.text-center { text-align: center; }
.text-sm { font-size: 0.875rem; }
.font-mono { font-family: monospace; }
/* Spacing */
.mt-1 { margin-top: 0.25rem; }
.mt-2 { margin-top: 0.5rem; }
.mt-4 { margin-top: 1rem; }
.mt-6 { margin-top: 1.5rem; }
.mt-8 { margin-top: 2rem; }
.mb-2 { margin-bottom: 0.5rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-6 { margin-bottom: 1.5rem; }
.ml-2 { margin-left: 0.5rem; }
.p-0 { padding: 0; }
.p-4 { padding: 1rem; }
.p-6 { padding: 1.5rem; }
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
.gap-2 { gap: 0.5rem; }
.gap-4 { gap: 1rem; }
/* Flex */
.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.w-full { width: 100%; }
.overflow-x-auto { overflow-x: auto; }
/* Badges */
.badge { display: inline-flex; align-items: center; border-radius: 9999px; padding: 0.125rem 0.625rem; font-size: 0.75rem; font-weight: 500; }
.badge-ok { background: var(--c-badge-ok-bg); color: var(--c-badge-ok-text); }
.badge-warn { background: var(--c-badge-warn-bg); color: var(--c-badge-warn-text); }
/* Tables */
table { width: 100%; font-size: 0.875rem; border-collapse: collapse; }
th { text-align: left; font-weight: 500; color: var(--c-text-muted); padding: 0.75rem 1.5rem; border-bottom: 1px solid var(--c-border); }
td { padding: 0.75rem 1.5rem; border-bottom: 1px solid var(--c-border); }
tr:last-child td { border-bottom: none; }
tr:last-child td { border-bottom: none; }
/* Alerts */
.alert { padding: 0.75rem 1rem; border-radius: 0.5rem; font-size: 0.875rem; margin-bottom: 1rem; }
.alert-error { background: #fef2f2; color: #991b1b; }
.alert-success { background: #dcfce7; color: #166534; }
.alert-warning { background: #fef3c7; color: #92400e; }
.ml-2 { margin-left: 0.5rem; }
.list-pad { padding-left: 1.25rem; }
.import-card { border-color: rgba(16,185,129,0.4); }
.mini-alert { padding: 0.5rem 0.75rem; border-radius: 0.25rem; margin-bottom: 0.5rem; }
.font-semibold { font-weight: 600; }
/* Theme toggle */
.theme-btn { padding: 0.25rem 0.5rem; font-size: 0.75rem; }
/* Empty state */
.empty { text-align: center; color: var(--c-text-muted); padding: 1.5rem; }
/* Mono inline code */
code.code { padding: 0.125rem 0.5rem; border-radius: 0.25rem; font-family: monospace; background: var(--c-bg); }
/* Containers */
.container-sm { max-width: 28rem; margin: 0 auto; }
.form-stack { display: flex; flex-direction: column; gap: 1rem; }
.form-card { padding: 1.5rem; }
/* Header logo */
.link-inherit { font-size: 0.875rem; }