refactor(admin): extract inline styles to src/admin/admin.css

Move the ~300-line <style> block from src/pages/admin/index.astro
into a dedicated stylesheet, imported from the page frontmatter.
No rule changes — verbatim extraction so the existing admin UI
continues to render identically.

This is the first commit of the Backstage rebuild: it establishes
the shared admin stylesheet that the resource-pattern components
will consume in subsequent steps.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Hvid 2026-05-12 15:53:10 +02:00
parent 65191256ec
commit 103bfa2f0c
2 changed files with 307 additions and 298 deletions

306
src/admin/admin.css Normal file
View file

@ -0,0 +1,306 @@
/* ---------------------------------------------------------------------------
* Admin surface shared styles
*
* Extracted verbatim from src/pages/admin/index.astro's <style> block as the
* first step of the Backstage rebuild. The classes here are the design
* vocabulary the resource-driven admin will be assembled from.
*
* No new rules. No tweaks. Anything new belongs in the resource-pattern
* commits that follow.
* ------------------------------------------------------------------------- */
.page {
padding: var(--space-12) var(--space-20) var(--space-16);
max-width: var(--content-max);
margin: 0 auto;
}
/* ── Header ──────────────────────────────────────────────────────── */
.page-header {
max-width: 44rem;
margin-bottom: var(--space-8);
}
.eyebrow {
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--on-surface-muted);
margin-bottom: var(--space-3);
}
.page-title { margin: 0; }
/* ── Tabs ────────────────────────────────────────────────────────── */
.tabs {
display: flex;
gap: var(--space-1);
margin-bottom: var(--space-8);
border-bottom: var(--ghost-border);
padding-bottom: var(--space-2);
}
.tab {
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-sm);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-muted);
text-decoration: none;
border-bottom: none;
transition: color var(--duration-fast) var(--ease-standard),
background var(--duration-fast) var(--ease-standard);
}
.tab:hover { color: var(--on-surface-variant); background: var(--surface-container-low); border-bottom: none; }
.tab.active { color: var(--on-surface); background: var(--surface-container); }
.tab-count {
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--secondary);
color: var(--on-secondary);
border-radius: var(--radius-full);
font-size: var(--text-label-sm);
font-weight: 700;
min-width: 1.25rem;
height: 1.25rem;
padding: 0 var(--space-1);
margin-left: var(--space-2);
}
.section-note {
color: var(--on-surface-muted);
margin: 0;
max-width: var(--reading-max);
}
/* ── Messages ────────────────────────────────────────────────────── */
.action-msg {
padding: var(--space-3) var(--space-4);
background: rgba(109, 140, 124, 0.1);
border-radius: var(--radius-sm);
color: var(--pigment-copper);
margin-bottom: var(--space-6);
}
.form-error {
padding: var(--space-3) var(--space-4);
background: rgba(185, 107, 88, 0.08);
border-radius: var(--radius-sm);
color: var(--pigment-terracotta);
margin-bottom: var(--space-4);
}
/* ── Tab content ─────────────────────────────────────────────────── */
.tab-content {
display: flex;
flex-direction: column;
gap: var(--space-12);
}
/* ── Section ─────────────────────────────────────────────────────── */
.section {
display: flex;
flex-direction: column;
gap: var(--space-5);
}
.section-heading {
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--on-surface-muted);
}
.empty-msg {
color: var(--on-surface-muted);
margin: 0;
}
/* ── Invite result ───────────────────────────────────────────────── */
.invite-result {
background: rgba(109, 140, 124, 0.08);
border-radius: var(--radius-md);
padding: var(--space-5);
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.invite-result-label {
color: var(--pigment-copper);
letter-spacing: var(--tracking-wide);
font-weight: 600;
}
.invite-link-row {
display: flex;
align-items: center;
gap: var(--space-3);
}
.invite-link {
font-family: var(--font-mono);
background: var(--background);
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-sm);
color: var(--on-surface);
word-break: break-all;
flex: 1;
}
.copy-btn {
padding: var(--space-2) var(--space-3);
background: var(--secondary);
color: var(--on-secondary);
border: none;
border-radius: var(--radius-sm);
font-family: var(--font-sans);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
cursor: pointer;
white-space: nowrap;
flex-shrink: 0;
}
/* ── Invite form ─────────────────────────────────────────────────── */
.invite-form {
display: flex;
flex-direction: column;
gap: var(--space-5);
max-width: 48rem;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-4);
}
.field {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.field-label {
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-variant);
}
.input,
.select {
width: 100%;
padding: var(--space-3) var(--space-4);
background: var(--surface-container-lowest);
border: var(--ghost-border);
border-radius: var(--radius-sm);
font-family: var(--font-sans);
font-size: var(--text-body-md);
color: var(--on-surface);
outline: none;
transition: border-color var(--duration-fast) var(--ease-standard),
box-shadow var(--duration-fast) var(--ease-standard);
box-sizing: border-box;
}
.input:focus,
.select:focus {
border-color: var(--secondary);
box-shadow: 0 0 0 3px rgba(120, 95, 83, 0.12);
}
.btn-primary {
align-self: flex-start;
padding: var(--space-2) var(--space-6);
background: linear-gradient(180deg, var(--secondary) 0%, var(--secondary-dim) 100%);
color: var(--on-secondary);
border: none;
border-radius: var(--radius-md);
font-family: var(--font-sans);
font-weight: 600;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
cursor: pointer;
transition: opacity var(--duration-fast) var(--ease-standard);
}
.btn-primary:hover { opacity: 0.9; }
/* ── Data table ──────────────────────────────────────────────────── */
.data-table {
width: 100%;
border-collapse: collapse;
}
.data-table th {
text-align: left;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-muted);
padding: var(--space-2) var(--space-3) var(--space-2) 0;
border-bottom: var(--ghost-border);
font-weight: 500;
}
.data-table td {
padding: var(--space-3) var(--space-3) var(--space-3) 0;
border-bottom: var(--ghost-border);
color: var(--on-surface-variant);
vertical-align: middle;
}
.data-table tr.self td {
color: var(--on-surface-muted);
}
.muted { color: var(--on-surface-muted) !important; }
/* ── Inline elements ─────────────────────────────────────────────── */
.inline-form { display: inline; }
.select-inline {
background: none;
border: var(--ghost-border);
border-radius: var(--radius-sm);
font-family: var(--font-sans);
font-size: var(--text-label-md);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-variant);
padding: 0.2em var(--space-3);
cursor: pointer;
outline: none;
}
.danger-btn {
background: none;
border: none;
cursor: pointer;
font-family: var(--font-sans);
font-size: var(--text-label-md);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--pigment-terracotta);
padding: 0.2em var(--space-2);
border-radius: var(--radius-sm);
transition: background var(--duration-fast) var(--ease-standard);
}
.danger-btn:hover {
background: rgba(185, 107, 88, 0.08);
}
.action-cell { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; }
.action-link {
background: none;
border: none;
color: var(--on-surface-muted);
text-decoration: none;
border-bottom: none;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
cursor: pointer;
font-family: var(--font-sans);
font-size: var(--text-label-md);
transition: color var(--duration-fast) var(--ease-standard);
padding: 0;
}
.action-link:hover { color: var(--on-surface-variant); border-bottom: none; }

View file

@ -25,6 +25,7 @@ import ActivityTab from '../../components/admin/ActivityTab.astro';
import DispatchesTab from '../../components/admin/DispatchesTab.astro';
import UserEditTab from '../../components/admin/UserEditTab.astro';
import type { Role, RoadmapStatus, EventKind, DispatchKind, DispatchStatus } from '../../lib/db';
import '../../admin/admin.css';
const user = Astro.locals.user;
@ -604,301 +605,3 @@ actionMsg = Astro.url.searchParams.get('msg');
</div>
</AppLayout>
<style>
.page {
padding: var(--space-12) var(--space-20) var(--space-16);
max-width: var(--content-max);
margin: 0 auto;
}
/* ── Header ──────────────────────────────────────────────────────── */
.page-header {
max-width: 44rem;
margin-bottom: var(--space-8);
}
.eyebrow {
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--on-surface-muted);
margin-bottom: var(--space-3);
}
.page-title { margin: 0; }
/* ── Tabs ────────────────────────────────────────────────────────── */
.tabs {
display: flex;
gap: var(--space-1);
margin-bottom: var(--space-8);
border-bottom: var(--ghost-border);
padding-bottom: var(--space-2);
}
.tab {
padding: var(--space-2) var(--space-4);
border-radius: var(--radius-sm);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-muted);
text-decoration: none;
border-bottom: none;
transition: color var(--duration-fast) var(--ease-standard),
background var(--duration-fast) var(--ease-standard);
}
.tab:hover { color: var(--on-surface-variant); background: var(--surface-container-low); border-bottom: none; }
.tab.active { color: var(--on-surface); background: var(--surface-container); }
.tab-count {
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--secondary);
color: var(--on-secondary);
border-radius: var(--radius-full);
font-size: var(--text-label-sm);
font-weight: 700;
min-width: 1.25rem;
height: 1.25rem;
padding: 0 var(--space-1);
margin-left: var(--space-2);
}
.section-note {
color: var(--on-surface-muted);
margin: 0;
max-width: var(--reading-max);
}
/* ── Messages ────────────────────────────────────────────────────── */
.action-msg {
padding: var(--space-3) var(--space-4);
background: rgba(109, 140, 124, 0.1);
border-radius: var(--radius-sm);
color: var(--pigment-copper);
margin-bottom: var(--space-6);
}
.form-error {
padding: var(--space-3) var(--space-4);
background: rgba(185, 107, 88, 0.08);
border-radius: var(--radius-sm);
color: var(--pigment-terracotta);
margin-bottom: var(--space-4);
}
/* ── Tab content ─────────────────────────────────────────────────── */
.tab-content {
display: flex;
flex-direction: column;
gap: var(--space-12);
}
/* ── Section ─────────────────────────────────────────────────────── */
.section {
display: flex;
flex-direction: column;
gap: var(--space-5);
}
.section-heading {
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--on-surface-muted);
}
.empty-msg {
color: var(--on-surface-muted);
margin: 0;
}
/* ── Invite result ───────────────────────────────────────────────── */
.invite-result {
background: rgba(109, 140, 124, 0.08);
border-radius: var(--radius-md);
padding: var(--space-5);
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.invite-result-label {
color: var(--pigment-copper);
letter-spacing: var(--tracking-wide);
font-weight: 600;
}
.invite-link-row {
display: flex;
align-items: center;
gap: var(--space-3);
}
.invite-link {
font-family: var(--font-mono);
background: var(--background);
padding: var(--space-2) var(--space-3);
border-radius: var(--radius-sm);
color: var(--on-surface);
word-break: break-all;
flex: 1;
}
.copy-btn {
padding: var(--space-2) var(--space-3);
background: var(--secondary);
color: var(--on-secondary);
border: none;
border-radius: var(--radius-sm);
font-family: var(--font-sans);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
cursor: pointer;
white-space: nowrap;
flex-shrink: 0;
}
/* ── Invite form ─────────────────────────────────────────────────── */
.invite-form {
display: flex;
flex-direction: column;
gap: var(--space-5);
max-width: 48rem;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-4);
}
.field {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.field-label {
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-variant);
}
.input,
.select {
width: 100%;
padding: var(--space-3) var(--space-4);
background: var(--surface-container-lowest);
border: var(--ghost-border);
border-radius: var(--radius-sm);
font-family: var(--font-sans);
font-size: var(--text-body-md);
color: var(--on-surface);
outline: none;
transition: border-color var(--duration-fast) var(--ease-standard),
box-shadow var(--duration-fast) var(--ease-standard);
box-sizing: border-box;
}
.input:focus,
.select:focus {
border-color: var(--secondary);
box-shadow: 0 0 0 3px rgba(120, 95, 83, 0.12);
}
.btn-primary {
align-self: flex-start;
padding: var(--space-2) var(--space-6);
background: linear-gradient(180deg, var(--secondary) 0%, var(--secondary-dim) 100%);
color: var(--on-secondary);
border: none;
border-radius: var(--radius-md);
font-family: var(--font-sans);
font-weight: 600;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
cursor: pointer;
transition: opacity var(--duration-fast) var(--ease-standard);
}
.btn-primary:hover { opacity: 0.9; }
/* ── Data table ──────────────────────────────────────────────────── */
.data-table {
width: 100%;
border-collapse: collapse;
}
.data-table th {
text-align: left;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-muted);
padding: var(--space-2) var(--space-3) var(--space-2) 0;
border-bottom: var(--ghost-border);
font-weight: 500;
}
.data-table td {
padding: var(--space-3) var(--space-3) var(--space-3) 0;
border-bottom: var(--ghost-border);
color: var(--on-surface-variant);
vertical-align: middle;
}
.data-table tr.self td {
color: var(--on-surface-muted);
}
.muted { color: var(--on-surface-muted) !important; }
/* ── Inline elements ─────────────────────────────────────────────── */
.inline-form { display: inline; }
.select-inline {
background: none;
border: var(--ghost-border);
border-radius: var(--radius-sm);
font-family: var(--font-sans);
font-size: var(--text-label-md);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--on-surface-variant);
padding: 0.2em var(--space-3);
cursor: pointer;
outline: none;
}
.danger-btn {
background: none;
border: none;
cursor: pointer;
font-family: var(--font-sans);
font-size: var(--text-label-md);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
color: var(--pigment-terracotta);
padding: 0.2em var(--space-2);
border-radius: var(--radius-sm);
transition: background var(--duration-fast) var(--ease-standard);
}
.danger-btn:hover {
background: rgba(185, 107, 88, 0.08);
}
.action-cell { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; }
.action-link {
background: none;
border: none;
color: var(--on-surface-muted);
text-decoration: none;
border-bottom: none;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
cursor: pointer;
font-family: var(--font-sans);
font-size: var(--text-label-md);
transition: color var(--duration-fast) var(--ease-standard);
padding: 0;
}
.action-link:hover { color: var(--on-surface-variant); border-bottom: none; }
</style>