nav had no flex-wrap, so the brand + 3 links overflowed a phone-width viewport at the site's 150% base font size - Customers (last link) got clipped off-screen, only reachable by rotating to landscape. Nav now wraps, and below 430px the brand drops to its own line above the links.
415 lines
7.6 KiB
CSS
415 lines
7.6 KiB
CSS
:root {
|
|
/* Surfaces */
|
|
--color-bg: #F2E8D5; /* aged parchment — page background */
|
|
--color-surface: #EAD9BE; /* light oak — cards, panels */
|
|
--color-border: #C4A882; /* tan grain — dividers, input borders */
|
|
|
|
/* Wood tones */
|
|
--color-wood-dark: #4A2810; /* dark mahogany — nav, headings */
|
|
--color-wood-mid: #6B4527; /* dark walnut — buttons, interactive (darkened for contrast) */
|
|
--color-wood-light: #B5842A; /* brass — hover states, focus rings */
|
|
|
|
/* Text */
|
|
--color-text: #2C1A0E; /* near-black brown — body copy */
|
|
--color-text-muted: #5A3D22; /* dark oak — labels, secondary info (darkened for contrast) */
|
|
--color-text-on-dark: #F2E8D5; /* parchment — text on dark backgrounds */
|
|
|
|
/* Status */
|
|
--color-status-open: #6B4527; /* dark walnut */
|
|
--color-status-inprogress:#7A5419; /* dark brass */
|
|
--color-status-done: #47602F; /* muted forest green */
|
|
--color-status-paid: #3D5C2A; /* deeper green */
|
|
|
|
--font-heading: Georgia, 'Times New Roman', serif;
|
|
--font-body: system-ui, sans-serif;
|
|
}
|
|
|
|
html {
|
|
font-size: 150%; /* Dad's eyes aren't what they used to be */
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--color-bg);
|
|
color: var(--color-text);
|
|
font-family: var(--font-body);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
h1, h2, h3 {
|
|
font-family: var(--font-heading);
|
|
color: var(--color-wood-dark);
|
|
margin: 0 0 0.5em;
|
|
}
|
|
|
|
a {
|
|
color: var(--color-wood-mid);
|
|
}
|
|
|
|
nav {
|
|
background: var(--color-wood-dark);
|
|
padding: 0.75rem 1.5rem;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.75rem 1.5rem;
|
|
align-items: center;
|
|
}
|
|
|
|
nav a {
|
|
color: var(--color-text-on-dark);
|
|
text-decoration: none;
|
|
font-family: var(--font-body);
|
|
}
|
|
|
|
nav a.brand {
|
|
font-family: var(--font-heading);
|
|
font-weight: bold;
|
|
font-size: 1.1rem;
|
|
margin-right: auto;
|
|
}
|
|
|
|
nav a:hover {
|
|
color: var(--color-wood-light);
|
|
}
|
|
|
|
/* Below ~430px (a phone in portrait, at this site's 150% base font size)
|
|
the brand name alone can approach full width - drop it to its own line
|
|
above the links instead of letting the flex row overflow the viewport. */
|
|
@media (max-width: 430px) {
|
|
nav {
|
|
padding: 0.6rem 1rem;
|
|
gap: 0.5rem 1rem;
|
|
}
|
|
|
|
nav a.brand {
|
|
flex-basis: 100%;
|
|
margin-right: 0;
|
|
}
|
|
}
|
|
|
|
main {
|
|
max-width: 960px;
|
|
margin: 0 auto;
|
|
padding: 1.5rem;
|
|
}
|
|
|
|
.page-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 1rem;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.header-actions {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.card {
|
|
background: var(--color-surface);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
padding: 1.25rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.two-col {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
.empty {
|
|
color: var(--color-text-muted);
|
|
font-style: italic;
|
|
}
|
|
|
|
.hint {
|
|
color: var(--color-text-muted);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
/* Forms */
|
|
|
|
fieldset {
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
margin-bottom: 1.25rem;
|
|
padding: 1rem;
|
|
}
|
|
|
|
legend {
|
|
font-family: var(--font-heading);
|
|
color: var(--color-wood-dark);
|
|
padding: 0 0.5rem;
|
|
}
|
|
|
|
label {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.25rem;
|
|
font-size: 0.9rem;
|
|
color: var(--color-text-muted);
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.grid-2 {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 0 1.5rem;
|
|
}
|
|
|
|
input, select, textarea {
|
|
font-family: var(--font-body);
|
|
font-size: 1rem;
|
|
padding: 0.4rem 0.5rem;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
background: var(--color-bg);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
input:focus, select:focus, textarea:focus {
|
|
outline: 2px solid var(--color-wood-light);
|
|
outline-offset: 1px;
|
|
}
|
|
|
|
button, .button-link {
|
|
font-family: var(--font-body);
|
|
font-size: 0.95rem;
|
|
line-height: 1.4;
|
|
background: var(--color-wood-mid);
|
|
color: var(--color-text-on-dark);
|
|
border: none;
|
|
border-radius: 4px;
|
|
padding: 0.5rem 1rem;
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
}
|
|
|
|
button:hover, .button-link:hover {
|
|
background: var(--color-wood-light);
|
|
}
|
|
|
|
button.danger {
|
|
background: transparent;
|
|
border: 1px solid var(--color-wood-dark);
|
|
color: var(--color-wood-dark);
|
|
}
|
|
|
|
.icon-button {
|
|
background: transparent;
|
|
color: var(--color-text-muted);
|
|
padding: 0.2rem 0.5rem;
|
|
}
|
|
|
|
.inline-form {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.work-log-form {
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.work-log-form textarea {
|
|
flex: 1 1 100%;
|
|
resize: vertical;
|
|
}
|
|
|
|
.search-form {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
/* Tables */
|
|
|
|
.data-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
.data-table th, .data-table td {
|
|
text-align: left;
|
|
padding: 0.5rem 0.75rem;
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
.data-table th {
|
|
color: var(--color-text-muted);
|
|
font-weight: normal;
|
|
text-transform: uppercase;
|
|
font-size: 0.75rem;
|
|
letter-spacing: 0.03em;
|
|
}
|
|
|
|
.row-link {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.row-link:hover {
|
|
background: var(--color-bg);
|
|
}
|
|
|
|
/* Status badges */
|
|
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 0.15rem 0.6rem;
|
|
border-radius: 999px;
|
|
font-size: 0.75rem;
|
|
color: var(--color-text-on-dark);
|
|
}
|
|
|
|
.status-open { background: var(--color-status-open); }
|
|
.status-in-progress { background: var(--color-status-inprogress); }
|
|
.status-done { background: var(--color-status-done); }
|
|
.status-paid { background: var(--color-status-paid); }
|
|
|
|
/* Totals */
|
|
|
|
.totals-summary {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
gap: 0.5rem 1.5rem;
|
|
margin: 1rem 0 0;
|
|
padding-top: 1rem;
|
|
border-top: 1px solid var(--color-border);
|
|
}
|
|
|
|
.totals-summary div {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.totals-summary dt {
|
|
color: var(--color-text-muted);
|
|
}
|
|
|
|
.totals-summary dd {
|
|
margin: 0;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.totals-summary .balance-due dd {
|
|
color: var(--color-wood-dark);
|
|
font-size: 1.15rem;
|
|
}
|
|
|
|
/* Work log */
|
|
|
|
.work-log-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.work-log-item {
|
|
padding: 0.5rem 0;
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
.work-log-item time {
|
|
display: block;
|
|
color: var(--color-text-muted);
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
/* Invoice */
|
|
|
|
.invoice-toolbar {
|
|
padding: 1rem;
|
|
text-align: right;
|
|
}
|
|
|
|
.invoice {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
padding: 2rem;
|
|
background: white;
|
|
color: #111;
|
|
}
|
|
|
|
.invoice-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
border-bottom: 2px solid var(--color-wood-dark);
|
|
padding-bottom: 1rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.invoice-meta {
|
|
text-align: right;
|
|
}
|
|
|
|
.invoice-parties {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 1.5rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.invoice-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.invoice-table th, .invoice-table td {
|
|
text-align: left;
|
|
padding: 0.4rem 0.5rem;
|
|
border-bottom: 1px solid #ccc;
|
|
}
|
|
|
|
.invoice-totals dl {
|
|
max-width: 320px;
|
|
margin-left: auto;
|
|
}
|
|
|
|
.invoice-totals div {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 0.2rem 0;
|
|
}
|
|
|
|
.invoice-totals .grand {
|
|
border-top: 1px solid #999;
|
|
margin-top: 0.3rem;
|
|
padding-top: 0.4rem;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.invoice-totals .balance-due {
|
|
font-weight: bold;
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
.invoice-footer {
|
|
margin-top: 2rem;
|
|
text-align: center;
|
|
color: #666;
|
|
}
|
|
|
|
.invoice-terms-note {
|
|
font-weight: bold;
|
|
color: #111;
|
|
}
|
|
|
|
@media print {
|
|
html { font-size: 100%; } /* keep the printed invoice at normal scale so it still fits one page */
|
|
.no-print { display: none !important; }
|
|
body { background: white; }
|
|
.invoice { box-shadow: none; padding: 0; }
|
|
}
|