@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--ds-color-bg: 244 246 251;
--ds-color-surface: 255 255 255;
--ds-color-surface-muted: 249 250 251;
--ds-color-text: 17 24 39;
--ds-color-text-muted: 107 114 128;
--ds-color-border: 229 231 235;
--ds-color-primary: 17 24 39;
--ds-color-accent: 59 130 246;
--ds-color-success: 22 163 74;
--ds-color-warning: 217 119 6;
--ds-color-danger: 220 38 38;
--ds-color-layer-1: 255 255 255;
--ds-color-layer-2: 255 255 255;
--ds-color-layer-3: 255 255 255;
--ds-color-layer-4: 255 255 255;
}
.dark {
--ds-color-bg: 43 45 51;
--ds-color-layer-1: 49 52 58;
--ds-color-layer-2: 56 59 66;
--ds-color-layer-3: 64 68 76;
--ds-color-layer-4: 72 76 85;
--ds-color-surface: 56 59 66;
--ds-color-surface-muted: 49 52 58;
--ds-color-text: 245 245 245;
--ds-color-text-muted: 184 184 192;
--ds-color-border: 74 78 87;
--ds-color-primary: 245 245 245;
--ds-color-accent: 91 140 255;
--ds-color-success: 52 211 153;
--ds-color-warning: 251 191 36;
--ds-color-danger: 248 113 113;
}
.theme-brand,
.theme-rust {
--ds-color-bg: 255 250 248;
--ds-color-surface: 255 255 255;
--ds-color-surface-muted: 255 245 241;
--ds-color-text: 17 24 39;
--ds-color-text-muted: 107 114 128;
--ds-color-border: 239 230 225;
--ds-color-primary: 17 24 39;
--ds-color-accent: 194 65 12;
--ds-color-success: 22 163 74;
--ds-color-warning: 217 119 6;
--ds-color-danger: 220 38 38;
}
}
@layer base {
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("/static/fonts/Inter-Regular.woff2") format("woff2");
}
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("/static/fonts/Inter-Medium.woff2") format("woff2");
}
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("/static/fonts/Inter-SemiBold.woff2") format("woff2");
}
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("/static/fonts/Inter-Bold.woff2") format("woff2");
}
html { @apply text-body; }
body {
@apply bg-paper text-metal antialiased font-sans dark:bg-bg dark:text-text;
font-feature-settings: "ss01", "tnum";
line-height: 1.6;
}
h1 { @apply text-h1 font-heading font-bold tracking-tight text-metal leading-tight; }
h2 { @apply text-h2 font-heading font-semibold tracking-tight text-metal; }
h3 { @apply text-h3 font-heading font-semibold text-metal; }
a { @apply text-rust hover:text-rust-hover transition-colors; }
::selection { @apply bg-rust text-white; }
}
@layer base {
:focus { outline: none; }
:focus-visible { @apply ring-2 ring-accent/30 outline-none; }
}
@layer components {
.admin-shell { @apply min-h-screen flex flex-col; }
.topbar { @apply h-16 px-6 flex items-center justify-between bg-metal-surface text-white border-b border-metal-dark; }
.topbar-brand { @apply flex items-center gap-3 font-bold text-body tracking-tight; }
.topbar-mark { @apply w-8 h-8 rounded-md bg-rust text-white text-small font-bold inline-flex items-center justify-center shadow-mark; }
.topbar-tools { @apply flex items-center gap-5 text-body text-gray-300; }
.topbar-tools a { @apply text-gray-300 hover:text-white no-underline transition-colors; }
.topbar-tools .link-button {
@apply bg-transparent border-0 text-gray-300 hover:text-white cursor-pointer p-0 text-body transition-colors;
font-family: inherit;
}
.topbar-tools .inline-form { @apply inline; }
.admin-body { @apply flex-1 flex; }
.sidebar { @apply hidden md:flex flex-col w-60 shrink-0 bg-surface border-r border-border py-5 px-3 gap-0.5; }
.sidebar-section { @apply text-caption uppercase tracking-wider text-text-muted font-semibold px-3 py-2 mt-3 first:mt-0; }
.sidebar-link {
@apply flex items-center gap-3 px-3 py-2.5 rounded-md text-body font-medium text-metal hover:bg-gray-100 no-underline transition-colors duration-150;
}
.sidebar-link svg { @apply w-[17px] h-[17px] shrink-0 text-text-muted; }
.sidebar-link-active {
@apply flex items-center gap-3 px-3 py-2.5 rounded-md text-body font-semibold text-rust bg-rust/10 no-underline relative;
box-shadow: inset 3px 0 0 0 theme("colors.rust.DEFAULT");
}
.sidebar-link-active svg { @apply w-[17px] h-[17px] shrink-0 text-rust; }
.content-shell { @apply flex-1 min-w-0 flex flex-col; }
.content-area { @apply flex-1 px-6 md:px-8 py-6 md:py-8 max-w-7xl w-full; }
.demo-banner {
@apply px-5 py-3 bg-amber-50 text-amber-900 border-b border-amber-200 text-body font-medium;
}
.demo-banner code { @apply bg-amber-100 px-1.5 py-0.5 rounded text-small font-mono; }
.breadcrumbs {
@apply text-small text-gray-600 mb-4;
}
.breadcrumbs a { @apply text-gray-600 hover:text-rust no-underline transition-colors; }
.btn-primary {
@apply inline-flex items-center gap-2 px-5 py-2.5 rounded-md bg-rust text-white font-semibold text-body shadow-btn hover:bg-rust-hover hover:shadow-btn-hover hover:-translate-y-px transition-all duration-150 no-underline cursor-pointer border-0;
}
.btn-ghost {
@apply inline-flex items-center gap-2 px-5 py-2.5 rounded-md bg-surface text-metal font-semibold text-body border border-border hover:border-gray-400 hover:bg-surface-muted transition-colors duration-150 no-underline cursor-pointer;
}
.btn-back { @apply btn-ghost; }
.btn-edit { @apply btn-primary; }
.deletelink-inline {
@apply text-red-700 font-medium hover:text-red-800 hover:underline transition-colors text-small;
}
.card {
@apply bg-surface border border-border rounded-xl p-6 transition-shadow duration-150;
}
.module {
@apply bg-surface border border-border rounded-xl mb-4 overflow-hidden;
}
.module h2, .module caption {
@apply bg-surface-muted text-gray-700 px-5 py-3 text-caption font-semibold uppercase tracking-wider border-b border-border;
}
.module table { @apply w-full border-collapse; }
.module td, .module th {
@apply px-4 py-3.5 border-b border-gray-100 text-left text-body;
}
.module tr:last-child td { @apply border-b-0; }
.object-tools {
@apply flex items-center justify-between gap-4 mb-5 list-none p-0;
}
.object-tools h1 { @apply m-0; }
.object-tools-actions {
@apply flex gap-3 list-none m-0 p-0 items-center;
}
.object-tools-actions a { @apply text-small font-medium text-emerald-700 no-underline hover:underline; }
.object-tools-actions .historylink { @apply text-rust no-underline; }
.object-tools-actions .historylink::before { content: "↻ "; }
.object-tools-actions .addlink { @apply text-emerald-700; }
.object-tools-actions .addlink::before { content: "+ "; }
.object-tools-row { @apply flex items-center gap-2 mb-5 flex-wrap; }
#toolbar {
@apply bg-surface-muted border border-border rounded-md p-3.5 mb-5;
border-left: 3px solid theme("colors.rust.DEFAULT");
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
#toolbar .search { @apply flex gap-2.5 items-center; }
#toolbar .search input {
@apply flex-1 pl-10 pr-3 py-2.5 rounded-md border border-border bg-surface text-body font-sans;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%238B949E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><path d='m21 21-4.3-4.3'/></svg>");
background-repeat: no-repeat;
background-position: 12px center;
background-size: 15px 15px;
}
#toolbar .search input:focus {
@apply outline-none border-accent ring-2 ring-accent/10;
}
#toolbar .search input::placeholder { @apply text-text-muted; }
#toolbar .search button {
@apply px-4 py-2.5 rounded-md bg-metal text-white text-small font-semibold hover:bg-metal-dark border-0 cursor-pointer transition-colors;
}
.results {
@apply w-full border-collapse bg-surface border border-border rounded-md text-body overflow-hidden;
}
.results th, .results td {
@apply px-4 py-3.5 text-left border-b border-gray-100;
}
.results th {
@apply bg-surface-muted text-metal font-semibold text-caption uppercase tracking-wider;
}
.results tbody tr:nth-child(even) td { @apply bg-surface-muted/50; }
.results tr:hover td { @apply bg-rust/5; }
.results.row-clickable td { @apply p-0; }
.results.row-clickable .row-link {
@apply block px-4 py-3.5 text-metal no-underline transition-colors;
}
.results.row-clickable .row-link:hover { @apply no-underline; }
.results.row-clickable td:first-child .row-link { @apply font-semibold; }
.results.row-clickable .row-link.help { @apply text-gray-600 text-small; }
.user-row { @apply transition-colors; }
.actions {
@apply px-3.5 py-2.5 mb-3 bg-surface-muted border border-border rounded-md flex items-center gap-3 text-small text-gray-700;
}
.actions select {
@apply px-2.5 py-1.5 rounded-md border border-border bg-surface text-small;
}
.actions button {
@apply px-3 py-1.5 rounded-md bg-metal text-white text-small font-semibold border-0 cursor-pointer hover:bg-metal-dark transition-colors;
}
.action-counter { @apply text-text-muted text-small ml-auto; }
.action-checkbox { @apply w-10 text-center pr-0; }
.action-checkbox input[type=checkbox] { @apply w-4 h-4 rounded border-gray-300 text-rust focus:ring-accent; }
.form-row { @apply mb-4; }
.form-row-grid { @apply grid grid-cols-1 md:grid-cols-2 gap-4; }
.form-row label, .form-label {
@apply block text-small font-semibold text-metal mb-1.5;
}
.form-input,
.form-row input[type=text],
.form-row input[type=email],
.form-row input[type=password],
.form-row input[type=search],
.form-row input[type=number],
.form-row input[type=url],
.form-row input[type=tel],
.form-row input[type=date],
.form-row input[type=time],
.form-row input[type=datetime-local],
.form-row select,
.form-row textarea {
@apply w-full px-3.5 py-2.5 rounded-md border border-border bg-surface text-body font-sans transition-colors;
}
.form-row textarea { @apply min-h-32 leading-relaxed; }
.form-input:focus,
.form-row input:focus,
.form-row select:focus,
.form-row textarea:focus {
@apply outline-none border-accent ring-2 ring-accent/10;
}
.form-row label .required { @apply text-rust font-semibold ml-0.5; }
.form-help, .help { @apply text-small text-gray-600 leading-snug; }
.field-input { @apply w-full; }
fieldset.module {
@apply bg-surface border border-border rounded-xl p-0 mb-5;
}
fieldset.module h2 {
@apply bg-surface-muted text-gray-700 px-5 py-3 text-caption font-semibold uppercase tracking-wider border-b border-border m-0 rounded-t-xl;
}
fieldset.module .form-row {
@apply px-5 py-4 border-b border-gray-100;
}
fieldset.module .form-row:last-child { @apply border-b-0; }
fieldset.module.aligned .form-row { @apply md:grid md:grid-cols-[200px_1fr] md:gap-4 md:items-start; }
.submit-row { @apply flex gap-2.5 items-center mt-6 flex-wrap; }
.submit-row input[type=submit], .submit-row button {
@apply btn-primary;
}
.checkbox-list { @apply flex flex-col gap-2.5; }
.checkbox-list label.checkbox-item { @apply flex items-center gap-2.5 text-body font-normal m-0; }
.errornote {
@apply px-4 py-3.5 mb-4 bg-red-50 text-red-800 border border-red-200 rounded-md text-body;
}
.warningnote {
@apply px-4 py-3.5 mb-4 bg-amber-50 text-amber-900 border border-amber-200 rounded-md text-body;
}
.warningnote code { @apply bg-amber-100 px-1.5 py-0.5 rounded text-small font-mono; }
.messagelist { @apply px-4 py-3.5 mb-4 rounded-md text-body border; }
.message-success { @apply bg-emerald-50 text-emerald-800 border-emerald-200; }
.message-warning { @apply bg-amber-50 text-amber-900 border-amber-200; }
.message-error { @apply bg-red-50 text-red-800 border-red-200; }
.empty-list {
@apply px-7 py-12 text-center text-gray-600 bg-surface-muted border border-dashed border-gray-300 rounded-md text-body;
}
.paginator { @apply mt-6 text-small text-gray-600 flex flex-wrap items-center gap-1.5; }
.paginator .this-page {
@apply bg-rust text-white px-2.5 py-1 rounded-md font-semibold;
}
.paginator a {
@apply px-2.5 py-1 rounded-md border border-border text-rust no-underline hover:bg-surface-muted transition-colors;
}
#changelist {
@apply grid gap-5 mt-2;
grid-template-columns: minmax(0, 1fr) 230px;
}
#changelist-filter {
@apply bg-surface border border-border rounded-xl p-4 self-start;
}
#changelist-filter h2 { @apply text-caption uppercase tracking-wider text-gray-700 m-0 mb-2; }
#changelist-filter h3 { @apply text-caption text-gray-600 mt-3 mb-1.5 uppercase tracking-wider; }
#changelist-filter ul { @apply list-none m-0 p-0 flex flex-col gap-1; }
#changelist-filter li { @apply text-small; }
#changelist-filter li.selected a { @apply text-rust font-semibold; }
#changelist-filter li a { @apply text-metal hover:text-rust no-underline transition-colors; }
@media (max-width: 768px) {
#changelist { grid-template-columns: 1fr; }
}
body.login { @apply bg-paper; }
#login-form {
@apply w-[400px] max-w-[92vw] mx-auto mt-16 bg-surface border border-border rounded-xl overflow-hidden shadow-md;
}
#login-form .module h2 {
@apply bg-metal-surface text-rust px-6 py-5 text-body font-semibold normal-case tracking-normal border-0;
}
#login-form form { @apply p-6; }
#login-form .form-row { @apply mb-5; }
#login-form button { @apply w-full uppercase tracking-wide py-3; }
.forbidden-page,
.coming-soon-body {
@apply max-w-xl mx-auto my-16 text-center py-10 px-6 bg-surface border border-border rounded-xl;
}
.forbidden-page h1 { @apply text-rust mb-3; }
.coming-soon-body h1 { @apply mb-3; }
.danger-zone {
@apply mt-6 border-red-200;
}
.danger-zone h2 {
@apply bg-red-50 text-red-800;
}
.user-view .profile-group-list,
.user-view .profile-perm-list {
@apply list-disc pl-5 my-1.5 text-body;
}
.user-view .muted { @apply text-gray-600 italic m-0 text-small; }
.cascade-list { @apply list-disc pl-5 my-3 space-y-1.5 text-body; }
.confirm-form .submit-row { @apply justify-start; }
.btn-primary {
@apply inline-flex items-center justify-center gap-2 h-[40px] px-md rounded-md
bg-primary text-surface font-semibold text-small no-underline border-0
shadow-card cursor-pointer transition-colors duration-150
hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent;
}
.btn-secondary {
@apply inline-flex items-center justify-center gap-2 h-[40px] px-md rounded-md
bg-surface text-text font-semibold text-small no-underline border border-border
cursor-pointer transition-colors duration-150
hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent;
}
.btn-ghost {
@apply inline-flex items-center justify-center gap-2 h-[40px] px-md rounded-md
bg-transparent text-text font-semibold text-small no-underline border-0
cursor-pointer transition-colors duration-150
hover:bg-surface-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent;
}
.btn-danger {
@apply inline-flex items-center justify-center gap-2 h-[40px] px-md rounded-md
bg-danger text-surface font-semibold text-small no-underline border-0
shadow-card cursor-pointer transition-colors duration-150
hover:bg-danger/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent;
}
.btn-primary:disabled, .btn-primary[disabled],
.btn-secondary:disabled, .btn-secondary[disabled],
.btn-ghost:disabled, .btn-ghost[disabled],
.btn-danger:disabled, .btn-danger[disabled] {
@apply opacity-50 cursor-not-allowed pointer-events-none;
}
.input {
@apply w-full h-[42px] px-sm rounded-md bg-surface text-text text-body
border border-border font-sans transition-colors
placeholder:text-text-muted
focus:outline-none focus:border-accent focus:ring-2 focus:ring-accent/20;
}
.card {
@apply bg-surface text-text border border-border rounded-lg shadow-card p-lg
transition-shadow duration-150;
}
.card-compact {
@apply bg-surface text-text border border-border rounded-md shadow-card p-md;
}
.table {
@apply w-full border-collapse bg-surface text-text rounded-md overflow-hidden border border-border;
}
.table th, .table td {
@apply px-md text-left border-b border-border;
height: 48px;
}
.table th {
@apply bg-surface-muted text-text-muted font-semibold text-caption uppercase tracking-wider;
}
.table tbody tr:last-child td { @apply border-b-0; }
.table-compact th, .table-compact td {
@apply px-sm text-small;
height: 36px;
}
.badge-success {
@apply inline-flex items-center px-2.5 py-1 rounded-md
bg-success/10 text-success
text-caption font-semibold uppercase tracking-wider;
}
.badge-warning {
@apply inline-flex items-center px-2.5 py-1 rounded-md
bg-warning/10 text-warning
text-caption font-semibold uppercase tracking-wider;
}
.badge-danger {
@apply inline-flex items-center px-2.5 py-1 rounded-md
bg-danger/10 text-danger
text-caption font-semibold uppercase tracking-wider;
}
.badge-neutral {
@apply inline-flex items-center px-2.5 py-1 rounded-md
bg-surface-muted text-text-muted
text-caption font-semibold uppercase tracking-wider;
}
.page-header {
@apply flex items-end justify-between gap-md mb-lg flex-wrap;
}
.hero-icon {
@apply inline-flex items-center justify-center w-10 h-10 rounded-full;
}
.hero-icon-lg { @apply w-12 h-12; }
.hero-icon-avatar { @apply font-bold text-lg; }
.hero-icon-accent { @apply bg-accent/10 text-accent; }
.hero-icon-rust { @apply bg-rust/10 text-rust; }
.hero-icon-danger { @apply bg-red-100 text-red-700; }
.code-pill {
@apply bg-paper px-1.5 py-0.5 rounded text-small font-mono;
}
.page-actions {
@apply flex items-center gap-sm mb-lg flex-wrap;
}
.subhead-note {
@apply text-text-muted text-small mt-xs;
}
}