Files

794 lines
13 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
:root {
--bg: #0f172a;
--surface: #1e293b;
--surface-2: #273449;
--border: #334155;
--text: #e2e8f0;
--muted: #94a3b8;
--primary: #6366f1;
--danger: #ef4444;
--link: #a5b4fc;
--danger-fg: #fca5a5;
--shadow-lg: rgba(0, 0, 0, 0.5);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
background: var(--bg);
color: var(--text);
line-height: 1.5;
}
a {
color: var(--link);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.muted {
color: var(--muted);
}
.container {
max-width: 95%;
margin: 0 auto;
padding: 1.5rem;
}
/* Top bar */
.topbar {
display: flex;
align-items: center;
gap: 1.5rem;
padding: 0.75rem 1.5rem;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.topbar .brand a {
font-weight: 700;
color: var(--text);
}
.topbar nav {
display: flex;
align-items: center;
gap: 1rem;
}
.topbar .logout {
margin-left: auto;
display: flex;
align-items: center;
gap: 0.75rem;
}
/* Nav icons */
.nav-icon {
width: 14px;
height: 14px;
stroke: currentColor;
fill: none;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
flex-shrink: 0;
vertical-align: -2px;
}
/* Nav dropdowns */
.nav-group {
position: relative;
line-height: 1;
}
/* Invisible bridge so the hover isn't broken by the gap between trigger and panel */
.nav-group::after {
content: '';
position: absolute;
top: 100%;
left: 0;
right: 0;
height: 8px;
}
/* Fly-out submenus open to the right — bridge the margin-left gap */
.nav-dropdown .nav-group::after {
top: 0;
bottom: 0;
left: 100%;
right: auto;
height: auto;
width: 4px;
}
.nav-label {
cursor: default;
color: var(--link);
white-space: nowrap;
user-select: none;
display: flex;
align-items: center;
gap: 0.35rem;
}
.nav-label:hover {
text-decoration: underline;
}
.topbar nav>a {
display: flex;
align-items: center;
gap: 0.35rem;
}
.nav-dropdown {
display: none;
position: absolute;
top: calc(100% + 6px);
left: 0;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
padding: 0.3rem 0;
min-width: 190px;
z-index: 200;
box-shadow: 0 8px 24px var(--shadow-lg);
}
.nav-group:hover>.nav-dropdown {
display: block;
}
.nav-dropdown a {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.38rem 0.9rem;
white-space: nowrap;
color: var(--link);
}
.nav-dropdown a:hover {
background: var(--surface-2);
text-decoration: none;
}
.nav-dropdown hr {
border: none;
border-top: 1px solid var(--border);
margin: 0.3rem 0;
}
/* Second-level group inside a dropdown */
.nav-dropdown .nav-group>.nav-label {
padding: 0.38rem 0.9rem;
}
.nav-dropdown .nav-group:hover>.nav-label {
background: var(--surface-2);
text-decoration: none;
}
.nav-dropdown .nav-group>.nav-dropdown {
top: -0.3rem;
left: 100%;
margin-left: 2px;
}
.nav-chevron {
margin-left: auto;
opacity: 0.6;
font-style: normal;
font-size: 0.7em;
}
/* Cards */
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 10px;
padding: 1.25rem;
margin-bottom: 1.25rem;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.25rem;
}
@media (max-width: 720px) {
.grid {
grid-template-columns: 1fr;
}
}
h1 {
margin-top: 0;
}
h2 {
margin-top: 0;
font-size: 1.1rem;
}
/* Tables */
.table {
width: 100%;
border-collapse: collapse;
}
.table th,
.table td {
text-align: left;
padding: 0.5rem 0.6rem;
border-bottom: 1px solid var(--border);
vertical-align: middle;
}
.table th {
color: var(--muted);
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.row-actions {
display: flex;
gap: 0.4rem;
}
/* Sortable table headers */
table.sortable thead th:not([data-sort-off]) {
cursor: pointer;
user-select: none;
}
table.sortable thead th:not([data-sort-off]):hover {
color: var(--text);
}
table.sortable thead th[aria-sort]::after {
margin-left: 0.3rem;
}
table.sortable thead th[aria-sort="ascending"]::after {
content: "\25B2";
}
table.sortable thead th[aria-sort="descending"]::after {
content: "\25BC";
}
.sort-link {
color: inherit;
text-decoration: none;
}
.sort-link:hover {
text-decoration: underline;
}
/* Tags / definition lists */
.tag {
display: inline-block;
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: 999px;
padding: 0.05rem 0.55rem;
margin: 0 0.2rem 0.2rem 0;
font-size: 0.8rem;
}
.kv {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.4rem 1rem;
}
.kv dt {
color: var(--muted);
}
.kv dd {
margin: 0;
}
.links {
padding-left: 1.1rem;
}
/* Forms */
label {
display: block;
margin-bottom: 0.2rem;
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
}
label.check {
text-transform: none;
letter-spacing: 0;
font-size: 0.875rem;
font-weight: 400;
color: var(--text);
margin-bottom: 0;
}
input[type=text],
input[type=email],
input[type=password],
input[type=url],
input[type=number],
input[type=search],
textarea {
display: block;
width: 100%;
margin-top: 0;
padding: 0.4rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--border);
background: var(--surface-2);
color: var(--text);
font: inherit;
line-height: 1.4;
}
select {
display: block;
width: 100%;
margin-top: 0;
padding: 0.4rem 2rem 0.4rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--border);
background-color: var(--surface-2);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2394a3b8' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.5rem center;
background-size: 1em;
color: var(--text);
font: inherit;
line-height: 1.4;
appearance: none;
-webkit-appearance: none;
cursor: pointer;
}
input:focus,
select:focus,
textarea:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
}
::placeholder {
color: var(--muted);
opacity: 0.7;
}
.check {
display: flex;
align-items: center;
gap: 0.4rem;
}
.check input {
width: auto;
margin: 0;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem 0.75rem;
align-items: end;
}
.form-grid>button {
grid-column: 1 / -1;
justify-self: start;
margin-top: 0.25rem;
}
.roles-field {
grid-column: 1 / -1;
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.6rem;
}
.roles-field legend {
color: var(--muted);
font-size: 0.72rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 0 0.4rem;
}
.perm-matrix {
border-collapse: collapse;
font-size: 0.85rem;
}
.perm-matrix th,
.perm-matrix td {
padding: 0.2rem 0.5rem;
border: 1px solid var(--border);
text-align: center;
}
.perm-matrix th {
background: var(--surface-2);
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--muted);
}
.perm-matrix .perm-scope {
text-align: left;
font-weight: 500;
white-space: nowrap;
padding-right: 1rem;
}
.perm-matrix .perm-na {
color: var(--muted);
}
.inline-edit {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: end;
}
/* Inline attachment-points sub-section inside an edit row */
.ap-inline-section {
border-top: 1px solid var(--border);
margin-top: 1rem;
padding-top: 0.75rem;
}
.ap-inline-section h3 {
margin: 0 0 0.5rem;
font-size: 0.8rem;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.ap-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.3rem 0;
border-bottom: 1px solid var(--border);
font-size: 0.9rem;
}
.ap-item:last-of-type {
border-bottom: none;
margin-bottom: 0.5rem;
}
.ap-item-name {
font-weight: 500;
flex: 0 0 auto;
}
.ap-item-type {
color: var(--muted);
flex: 0 0 auto;
font-size: 0.8rem;
}
.ap-item-conn {
flex: 1;
}
.ap-item .row-actions {
margin-left: auto;
}
.fit-item-arrow {
color: var(--muted);
text-align: center;
}
.fit-badge {
text-transform: uppercase;
}
/* Fits table on the augmented part detail page */
.fit-table select,
.fit-table input[type="text"] {
min-width: 8rem;
}
.fit-table .fit-add-row {
background: var(--surface-2);
}
.fit-table .fit-add-row td {
vertical-align: top;
}
.fit-notes-cell {
min-width: 14rem;
}
.fit-badge-possible {
background: var(--surface-2);
color: var(--muted);
}
.fit-badge-exact {
background: #16a34a26;
color: #16a34a;
}
.fit-badge-none {
background: #dc262626;
color: #dc2626;
}
.fit-badge-possible a {
background: var(--surface-2);
color: var(--muted);
}
.fit-badge-exact a {
background: #16a34a26;
color: #16a34a;
}
.fit-badge-none a {
background: #dc262626;
color: #dc2626;
}
.fit-notes {
margin-top: 0.4rem;
padding-left: 0.25rem;
}
/* Scope guide: stacked matching-part entries within a fit column cell. */
.fit-cell-item {
display: flex;
align-items: center;
gap: 0.4rem;
font-size: 0.85rem;
white-space: nowrap;
}
.fit-cell-item+.fit-cell-item {
margin-top: 0.3rem;
}
.fit-note {
font-size: 0.85rem;
margin-bottom: 0.3rem;
}
.fit-note-meta {
color: var(--muted);
font-size: 0.75rem;
}
.fit-note-body {
margin: 0.1rem 0 0;
}
.fit-note-form {
margin-top: 0.3rem;
}
.fit-note-form input[type="text"] {
flex: 1;
min-width: 12rem;
}
/* Pagination */
.pagination {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.5rem;
flex-wrap: wrap;
}
.pagination-nav {
display: flex;
align-items: center;
gap: 0.5rem;
margin-left: auto;
}
.btn-sm {
padding: 0.25rem 0.6rem;
font-size: 0.85rem;
}
/* Filter bar */
.filter-bar {
margin-bottom: 0.75rem;
}
/* Bulk actions (e.g. delete-selected above a checkbox table) */
.bulk-actions {
margin-bottom: 0.75rem;
}
.dashboard-sync-actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: 0.75rem;
}
.filter-bar form {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
}
.filter-bar input[type="text"] {
flex: 1 1 180px;
min-width: 0;
}
.filter-bar select {
flex: 0 1 auto;
/* override full-width default from global select rule */
width: auto;
}
/* Buttons */
.btn {
font: inherit;
cursor: pointer;
border: 1px solid var(--border);
background: var(--surface-2);
color: var(--text);
padding: 0.4rem 0.8rem;
border-radius: 6px;
}
.btn:hover {
filter: brightness(1.1);
}
.btn-primary {
background: var(--primary);
border-color: var(--primary);
color: #fff;
}
.btn-danger {
background: transparent;
border-color: var(--danger);
color: var(--danger-fg);
}
.btn-ghost {
background: transparent;
}
/* Auth */
.auth-shell {
min-height: 100vh;
display: grid;
place-items: center;
padding: 1rem;
}
.auth-card {
width: 100%;
max-width: 360px;
}
.auth-card h1 {
margin: 0 0 0.25rem;
font-size: 1.4rem;
}
.auth-card button {
width: 100%;
margin-top: 0.5rem;
}
.alert {
background: rgba(239, 68, 68, 0.15);
border: 1px solid var(--danger);
color: var(--danger-fg);
padding: 0.5rem 0.75rem;
border-radius: 6px;
margin-bottom: 0.75rem;
}
.local-login-panel {
margin-top: 1.25rem;
border-top: 1px solid var(--border);
padding-top: 1rem;
}
.local-login-panel summary {
cursor: pointer;
color: var(--muted);
font-size: 0.875rem;
user-select: none;
list-style: none;
display: flex;
align-items: center;
gap: 0.4rem;
}
.local-login-panel summary::-webkit-details-marker {
display: none;
}
.local-login-panel summary::before {
content: '›';
font-size: 1.1em;
transition: transform 0.15s;
display: inline-block;
}
.local-login-panel[open] summary::before {
transform: rotate(90deg);
}
.local-login-panel summary:hover {
color: var(--text);
}
.local-login-panel form {
margin-top: 1rem;
}
/* ─── Light theme ────────────────────────────────────────────────────────── */
@media (prefers-color-scheme: light) {
:root {
--bg: #f8fafc;
--surface: #ffffff;
--surface-2: #f1f5f9;
--border: #e2e8f0;
--text: #0f172a;
--muted: #64748b;
--primary: #4f46e5;
--danger: #dc2626;
--link: #4338ca;
--danger-fg: #b91c1c;
--shadow-lg: rgba(0, 0, 0, 0.12);
}
/* Swap the select chevron to a darker arrow that reads on light backgrounds */
select {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2364748b' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
}
/* Soften the danger alert background on white cards */
.alert {
background: rgba(220, 38, 38, 0.08);
}
}