Add missing files, update style

This commit is contained in:
2026-10-05 20:48:08 +02:00
parent e70549337e
commit 9d092ed9df
20 changed files with 1161 additions and 202 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

+429 -103
View File
@@ -1,127 +1,453 @@
/*
* Shared stylesheet for all pcap tools pages.
*
* Follows the utel-frontend design: dark theme, utel color tokens, Inter /
* Dazzed / Roboto Mono fonts, top bar with a sidebar, "widget" cards and
* pill shaped buttons and inputs.
*/
/* ---------- Fonts ---------- */
@font-face { font-family: "Inter"; font-weight: 400; font-display: swap; src: url("/static/fonts/inter-v12-latin-regular.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-weight: 500; font-display: swap; src: url("/static/fonts/inter-v12-latin-500.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-weight: 600; font-display: swap; src: url("/static/fonts/inter-v12-latin-600.woff2") format("woff2"); }
@font-face { font-family: "Inter"; font-weight: 700; font-display: swap; src: url("/static/fonts/inter-v12-latin-700.woff2") format("woff2"); }
@font-face { font-family: "Dazzed-Medium"; font-display: swap; src: url("/static/fonts/Dazzed-Medium.otf") format("opentype"); }
@font-face { font-family: "Roboto-mono"; font-display: swap; src: url("/static/fonts/RobotoMono-Regular.ttf") format("truetype"); }
/* ---------- Tokens (from utel-frontend variables.scss) ---------- */
:root {
--bg: #f7f7f5;
--fg: #1d1d1f;
--muted: #6b6b70;
--card: #ffffff;
--border: #d9d9de;
--accent: #2463eb;
--accent-fg: #ffffff;
--error-bg: #fdecec;
--error-fg: #9b1c1c;
--l2: #b45309;
--l3: #1d4ed8;
--l7: #047857;
--mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
color-scheme: dark;
--utel-body-background: #191c1c;
--utel-navigation-background: #1f2f2e;
--utel-navigation-background-darken: #15201f;
--utel-text-color: #fff;
--utel-scrollbar-color: #696969;
--utel-icon-label-text-color: #a7a7a7;
--utel-icon-color: #d2d2d2;
--utel-p-text-color: #d3d3d3;
--utel-title-text-color: #d8d8d8;
--utel-title-link-color: #a7a7a7;
--utel-navigation-darker-text-color: #e6e6e6;
--utel-content-background: #242828;
--utel-content-darker-background: #1c1f1f;
--utel-content-text-color: #d8d8d8;
--utel-highlight-text-color: #9ed7aa;
--utel-content-border-color: #707070ac;
--utel-modal-border-color: #303434;
--utel-solid-button-color: #6da478;
--utel-solid-button-color-darker: #5d9568;
--utel-widget-button-color: #3c4343;
--utel-widget-button-color-darker: #434b4b;
--utel-widget-title-border: #1c1f1f;
--utel-widget-border: #323737;
--utel-content-hover-color: #393d3d;
--utel-fraud-color-yellow: #e4b266;
--utel-fraud-color-red: #ea6f80;
--utel-table-color: #2d3232;
--utel-table-split-color: #242828;
--utel-table-header-text-color: #9a9a9a;
--utel-severity-color-low: #6daa9c;
--utel-input-border-color: #3b4040;
--top-bar-height: 55px;
--sidebar-width: 220px;
--font-body: "Inter", system-ui, sans-serif;
--font-heading: "Dazzed-Medium", "Inter", sans-serif;
--font-mono: "Roboto-mono", ui-monospace, Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #161618;
--fg: #e8e8ea;
--muted: #9a9aa2;
--card: #1f1f22;
--border: #36363c;
--accent: #5b8cff;
--accent-fg: #0b0b0c;
--error-bg: #3a1717;
--error-fg: #ffb4b4;
--l2: #f5a65b;
--l3: #8fb0ff;
--l7: #5fd3a6;
}
}
/* ---------- Base ---------- */
* { box-sizing: border-box; }
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; }
body {
margin: 0;
background: var(--bg);
color: var(--fg);
font: 15px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
background: var(--utel-body-background);
color: var(--utel-text-color);
font: 400 15px/1.5 var(--font-body);
scrollbar-color: var(--utel-scrollbar-color) transparent;
scrollbar-width: thin;
}
header { border-bottom: 1px solid var(--border); background: var(--card); }
nav { max-width: 960px; margin: 0 auto; padding: 0.75rem 1rem; display: flex; gap: 1.25rem; flex-wrap: wrap; }
nav a { color: var(--muted); text-decoration: none; }
nav a:hover, nav a.active { color: var(--fg); }
nav a.brand { color: var(--fg); font-weight: 600; }
::-webkit-scrollbar { width: 7px; height: 7px; }
::-webkit-scrollbar-track { background: transparent; border-radius: 80px; }
::-webkit-scrollbar-thumb { background-color: var(--utel-scrollbar-color); border-radius: 80px; }
main { max-width: 960px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }
h1 { margin: 0 0 0.5rem; font-size: 1.6rem; }
h2 { font-size: 1.25rem; margin: 0 0 0.75rem; }
h3 { font-size: 1rem; margin: 1.25rem 0 0.5rem; }
.lead { color: var(--muted); margin-top: 0; }
a { color: var(--accent); }
code { font-family: var(--mono); font-size: 0.9em; }
.hint { color: var(--muted); font-weight: normal; font-size: 0.85em; }
h1, h2, h3 { font-family: var(--font-heading); font-weight: normal; margin: 0; }
h1 { font-size: 20px; }
h2 { font-size: 16px; }
h3 { font-size: 15px; color: var(--utel-title-text-color); margin: 16px 0 8px; }
.tools { list-style: none; padding: 0; display: grid; gap: 0.75rem; }
.tools li { background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 1rem; }
.tools a { font-weight: 600; font-size: 1.05rem; }
.tools p { margin: 0.25rem 0 0; color: var(--muted); }
p { color: var(--utel-p-text-color); }
a { color: var(--utel-highlight-text-color); }
code, pre { font-family: var(--font-mono); font-size: 13px; }
form label { display: block; font-weight: 600; margin: 1rem 0 0.3rem; }
textarea, input, select {
width: 100%;
font: inherit;
color: var(--fg);
background: var(--card);
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.5rem 0.6rem;
.hint { color: var(--utel-icon-label-text-color); font-weight: 400; font-size: 13px; }
.note { color: var(--utel-icon-label-text-color); font-size: 14px; margin: 6px 0; }
.visually-hidden {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
textarea { font-family: var(--mono); font-size: 0.9rem; resize: vertical; }
textarea:focus, input:focus, select:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
fieldset { border: 0; padding: 0; margin: 0; }
label.check { display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; font-weight: 600; }
label.check input { width: auto; }
.row { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 1rem; }
@media (max-width: 720px) { .row { grid-template-columns: 1fr; gap: 0; } }
/* ---------- Top bar ---------- */
.actions { margin-top: 1.25rem; display: flex; gap: 0.75rem; }
button {
font: inherit;
padding: 0.5rem 1.1rem;
border-radius: 6px;
border: 1px solid var(--border);
background: var(--card);
color: var(--fg);
.topbar {
position: sticky;
top: 0;
z-index: 20;
display: flex;
align-items: center;
height: var(--top-bar-height);
background: var(--utel-navigation-background);
border-bottom: 1px solid var(--utel-body-background);
}
.burger {
display: grid;
place-items: center;
width: var(--top-bar-height);
height: var(--top-bar-height);
flex: none;
background: var(--utel-navigation-background-darken);
cursor: pointer;
}
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
.burger svg { width: 19px; fill: var(--utel-text-color); }
.nav-toggle:focus-visible + .topbar .burger { outline: 2px solid var(--utel-solid-button-color); outline-offset: -2px; }
.error { background: var(--error-bg); color: var(--error-fg); padding: 0.75rem 1rem; border-radius: 6px; margin: 1rem 0; }
.note { color: var(--muted); margin: 0.35rem 0; }
.app-title {
margin-left: 15px;
font: 16px/var(--top-bar-height) var(--font-heading);
color: var(--utel-text-color);
text-decoration: none;
}
.result { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
.summary { display: grid; grid-template-columns: max-content 1fr; gap: 0.25rem 1rem; margin: 0; }
.summary dt { color: var(--muted); }
.logo-symbol {
position: absolute;
left: 50%;
transform: translateX(-50%);
display: flex;
}
.logo-symbol svg { width: 40px; height: 40px; fill: var(--utel-text-color); }
/* ---------- Sidebar ---------- */
.sidebar {
position: fixed;
top: var(--top-bar-height);
left: 0;
z-index: 10;
width: var(--sidebar-width);
height: calc(100% - var(--top-bar-height));
overflow-y: auto;
background: var(--utel-navigation-background-darken);
transition: transform 0.15s ease;
}
.nav-section {
display: flex;
align-items: center;
gap: 8px;
margin-top: 10px;
padding: 8px 15px;
color: var(--utel-icon-label-text-color);
font-size: 11px;
letter-spacing: 0.8px;
text-transform: uppercase;
}
.nav-item {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 15px;
color: var(--utel-text-color);
font-weight: 500;
font-size: 15px;
text-decoration: none;
}
.nav-item:hover, .nav-item.active { background: var(--utel-navigation-background); }
.nav-item.active { color: var(--utel-highlight-text-color); }
.nav-item::before {
content: "";
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--utel-solid-button-color);
flex: none;
}
/*
* The burger toggles the sidebar using a checkbox, so no JavaScript is needed.
* Wide screens show the sidebar by default and the burger hides it; narrow
* screens hide it by default and the burger shows it over the content.
*/
.content { margin-left: var(--sidebar-width); padding: 10px; transition: margin-left 0.15s ease; }
.nav-toggle:checked ~ .sidebar { transform: translateX(-100%); }
.nav-toggle:checked ~ .content { margin-left: 0; }
@media (max-width: 64rem) {
.sidebar { transform: translateX(-100%); box-shadow: 4px 0 12px rgb(0 0 0 / 0.35); }
.nav-toggle:checked ~ .sidebar { transform: none; }
.content { margin-left: 0; }
.logo-symbol { display: none; }
}
/* ---------- Page toolbar ---------- */
.toolbar {
display: flex;
align-items: baseline;
flex-wrap: wrap;
gap: 0 20px;
margin: 0 5px 10px;
font-size: 16px;
}
.breadcrumb { color: var(--utel-navigation-darker-text-color); }
.toolbar-link { color: var(--utel-title-link-color); text-decoration: none; }
.toolbar-link:hover { color: var(--utel-title-text-color); border-bottom: 1px solid var(--utel-title-text-color); }
.title-separator { margin: 0 5px 0 7px; color: var(--utel-title-link-color); }
.toolbar-title { color: var(--utel-title-text-color); }
.toolbar-info { color: var(--utel-icon-label-text-color); font-size: 14px; }
/* ---------- Widgets ---------- */
.widget {
margin: 5px 5px 10px;
background: var(--utel-content-background);
border-radius: 5px;
}
.widget-title {
display: flex;
align-items: center;
gap: 10px;
min-height: 38px;
border-bottom: 1px solid var(--utel-widget-title-border);
}
.widget-title h2 { padding: 8px 0 8px 10px; color: var(--utel-title-text-color); }
.widget-title .hint { margin-left: auto; padding-right: 10px; }
.widget-content { padding: 10px; border-top: 1px solid var(--utel-widget-border); }
.widget-content > :first-child { margin-top: 0; }
.widget-content > :last-child { margin-bottom: 0; }
.widget-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.tool-card { display: flex; flex-direction: column; text-decoration: none; color: inherit; transition: background 0.1s; }
.tool-card:hover { background: var(--utel-content-hover-color); }
.tool-card .widget-content { flex: 1; color: var(--utel-p-text-color); font-size: 14px; }
/* ---------- Buttons ---------- */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 35px;
padding: 6px 16px;
border: 0;
border-radius: 80px;
font: 700 15px var(--font-body);
color: var(--utel-text-color);
background: var(--utel-widget-button-color);
cursor: pointer;
text-decoration: none;
white-space: nowrap;
}
.btn:hover { background: var(--utel-widget-button-color-darker); }
.btn:focus-visible { outline: 2px solid var(--utel-highlight-text-color); outline-offset: 2px; }
.btn.primary { background: var(--utel-solid-button-color); }
.btn.primary:hover { background: var(--utel-solid-button-color-darker); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 15px; }
/* ---------- Forms ---------- */
label, .label {
display: block;
margin: 12px 0 4px;
color: var(--utel-content-text-color);
font-size: 14px;
font-weight: 500;
}
input, select, textarea {
font: 400 14px var(--font-body);
color: var(--utel-content-text-color);
}
/* Single line inputs and selects: utel pill style */
input:not([type=checkbox], [type=radio], [type=file]), select {
width: 100%;
height: 32px;
padding: 0 15px;
background: var(--utel-content-background);
border: 1px solid var(--utel-input-border-color);
border-radius: 64px;
}
select {
appearance: none;
padding-right: 36px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%23a7a7a7' stroke-width='1.6'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 14px center;
background-size: 12px 8px;
text-overflow: ellipsis;
}
select option { background: var(--utel-content-background); }
/* Multi-line hex input: same border, darker field, rounded rectangle */
textarea {
display: block;
width: 100%;
padding: 8px 12px;
background: var(--utel-content-darker-background);
border: 1px solid var(--utel-input-border-color);
border-radius: 5px;
font-family: var(--font-mono);
font-size: 13px;
resize: vertical;
}
::placeholder { color: var(--utel-icon-label-text-color); opacity: 1; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--utel-solid-button-color); }
/* Checkbox and radio: 18px box with the utel green when checked */
input[type=checkbox], input[type=radio] {
appearance: none;
flex: none;
width: 18px;
height: 18px;
margin: 0;
border: 1px solid var(--utel-content-border-color);
border-radius: 3px;
background: transparent;
display: grid;
place-items: center;
cursor: pointer;
}
input[type=radio] { border-radius: 50%; }
input[type=checkbox]:checked, input[type=radio]:checked {
background: var(--utel-solid-button-color);
border-color: var(--utel-solid-button-color);
}
input[type=checkbox]:checked::after {
content: "";
width: 10px;
height: 6px;
margin-top: -3px;
border: solid var(--utel-text-color);
border-width: 0 0 2px 2px;
transform: rotate(-45deg);
}
input[type=radio]:checked::after {
content: "";
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--utel-text-color);
}
input[type=checkbox]:focus-visible, input[type=radio]:focus-visible { outline: 2px solid var(--utel-highlight-text-color); outline-offset: 2px; }
label.check {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
font-weight: 400;
font-size: 15px;
}
/* File input: the button looks like a secondary utel button */
input[type=file] {
width: 100%;
padding: 4px;
border: 1px dashed var(--utel-input-border-color);
border-radius: 5px;
color: var(--utel-icon-label-text-color);
}
input[type=file]::file-selector-button {
height: 30px;
margin-right: 12px;
padding: 0 14px;
border: 0;
border-radius: 80px;
font: 700 14px var(--font-body);
color: var(--utel-text-color);
background: var(--utel-widget-button-color);
cursor: pointer;
}
input[type=file]::file-selector-button:hover { background: var(--utel-widget-button-color-darker); }
fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
legend { padding: 0; margin: 12px 0 4px; font-size: 14px; font-weight: 500; color: var(--utel-content-text-color); }
/* Three controls on one line: link type, custom link type, file name */
.row { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 0 12px; align-items: start; }
.row label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.field-hint { display: block; margin: 4px 0 0 15px; }
@media (max-width: 720px) { .row { grid-template-columns: 1fr; } }
/* Split modes: radio with inline number input and unit */
.modes label.check { margin: 8px 0; }
.modes input.num { width: 8rem; }
.modes select.unit { width: 5.5rem; }
/* ---------- Messages ---------- */
.error {
margin: 0 5px 10px;
padding: 10px 15px;
border: 1px solid var(--utel-fraud-color-red);
border-left-width: 4px;
border-radius: 5px;
background: rgb(234 111 128 / 0.1);
color: var(--utel-text-color);
}
/* ---------- Tables (utel table-theme) ---------- */
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th {
padding: 0 10px 5px 5px;
text-align: left;
font-weight: 400;
white-space: nowrap;
color: var(--utel-table-header-text-color);
}
td {
padding: 5px 10px 5px 5px;
font-weight: 500;
background: var(--utel-table-color);
border-top: 1px solid var(--utel-table-split-color);
}
tr.changed td:last-child { color: var(--utel-highlight-text-color); }
/* ---------- hex2pcap result ---------- */
.summary { display: grid; grid-template-columns: max-content 1fr; gap: 4px 16px; margin: 0; font-size: 14px; }
.summary dt { color: var(--utel-icon-label-text-color); }
.summary dd { margin: 0; }
table { border-collapse: collapse; width: 100%; background: var(--card); border: 1px solid var(--border); }
th, td { text-align: left; padding: 0.4rem 0.75rem; border-bottom: 1px solid var(--border); }
th { color: var(--muted); font-weight: 600; font-size: 0.85rem; }
tr.changed td:last-child { font-weight: 600; }
.dump {
font-family: var(--mono);
font-size: 0.85rem;
background: var(--card);
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.75rem 1rem;
margin: 0;
padding: 10px 12px;
overflow-x: auto;
background: var(--utel-content-darker-background);
border-radius: 5px;
color: var(--utel-p-text-color);
line-height: 1.6;
}
.dump .off { color: var(--muted); }
.l2 { color: var(--l2); }
.l3 { color: var(--l3); }
.l7 { color: var(--l7); }
.chg { text-decoration: underline; text-underline-offset: 3px; font-weight: 700; }
.dump .off { color: var(--utel-table-header-text-color); }
.l2 { color: var(--utel-fraud-color-yellow); }
.l3 { color: var(--utel-severity-color-low); }
.l7 { color: var(--utel-p-text-color); }
.chg { text-decoration: underline; text-underline-offset: 3px; color: var(--utel-highlight-text-color); font-weight: 700; }
input[type=file] { padding: 0.4rem; }
.modes { margin-top: 1rem; }
.modes legend { font-weight: 600; margin-bottom: 0.3rem; }
.modes label.check { font-weight: normal; margin: 0.5rem 0; align-items: center; }
.modes input.num { width: 8rem; }
.modes select.unit { width: auto; }
/* A hint under a checkbox lines up with the checkbox's text */
label.check + .field-hint { margin: 2px 0 0 26px; }