Add Sass build pipeline and production deploy script
- Move hand-authored CSS into src/scss/styles.scss, compiled to the tracked styles.css via `npm run build` (sass, no source maps). - Add package.json/package-lock.json with dev tooling: sass, and a `dev` script running php + sass --watch + browser-sync together. - Add scripts/build-dist.js (npm run dist): assembles an allowlisted, production-only copy of the site into dist/ (gitignored) for pushing to hosting — excludes node_modules, src/, package files, and the live db/fitz.sqlite while including config.php. - .gitignore: ignore node_modules/, styles.css.map, and dist/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cd4c6c1969
commit
2145094e55
6 files changed
+4822
-106
No files matched your search
@@ -16,3 +16,10 @@ db/fitz.sqlite-shm
|
|||||||
.hintrc
|
.hintrc
|
||||||
dev.sh
|
dev.sh
|
||||||
.claude/
|
.claude/
|
||||||
|
|
||||||
|
# Node development dependencies and Sass source maps
|
||||||
|
node_modules/
|
||||||
|
styles.css.map
|
||||||
|
|
||||||
|
# Generated deploy folder (npm run dist) — includes config.php, never commit
|
||||||
|
dist/
|
||||||
Generated
+2430
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "theoldfitz",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "The Old Fitz Public House website",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "concurrently --kill-others-on-fail \"npm:dev:php\" \"npm:dev:sass\" \"npm:dev:browser\"",
|
||||||
|
"dev:php": "php -S localhost:8000",
|
||||||
|
"dev:sass": "sass --watch --source-map src/scss/styles.scss:styles.css",
|
||||||
|
"dev:browser": "browser-sync start --proxy http://localhost:8000 --files \"*.php,admin/**/*.php,inc/**/*.php,main.js,styles.css\" --no-open",
|
||||||
|
"build": "sass --no-source-map src/scss/styles.scss:styles.css",
|
||||||
|
"dist": "npm run build && node scripts/build-dist.js"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitea.home.daviddyer.me/david/the-old-fitz.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"type": "commonjs",
|
||||||
|
"devDependencies": {
|
||||||
|
"browser-sync": "^3.0.4",
|
||||||
|
"concurrently": "^10.0.5",
|
||||||
|
"sass": "^1.103.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles a clean, production-only copy of the site into dist/.
|
||||||
|
*
|
||||||
|
* This is an allowlist by design: only the files and folders listed below
|
||||||
|
* are copied. Dev-only stuff (node_modules/, src/, package*.json, .git/,
|
||||||
|
* .claude/, docker-compose.yaml, dev.sh, .hintrc, config.example.php, the
|
||||||
|
* live db/fitz.sqlite, ...) never ends up in dist/ — including anything
|
||||||
|
* added later, since it has to be added here explicitly first.
|
||||||
|
*
|
||||||
|
* Run with: npm run dist
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const ROOT = path.resolve(__dirname, '..');
|
||||||
|
const DIST = path.join(ROOT, 'dist');
|
||||||
|
|
||||||
|
const FILES = [
|
||||||
|
'index.php',
|
||||||
|
'menu.php',
|
||||||
|
'main.js',
|
||||||
|
'styles.css',
|
||||||
|
'robots.txt',
|
||||||
|
'config.php', // holds the live FB_PAGE_ACCESS_TOKEN — see README before sharing dist/ anywhere but the server
|
||||||
|
];
|
||||||
|
|
||||||
|
const DIRS = ['admin', 'assets', 'inc'];
|
||||||
|
|
||||||
|
function copyDir(src, dest) {
|
||||||
|
fs.cpSync(src, dest, {
|
||||||
|
recursive: true,
|
||||||
|
filter: (source) => path.basename(source) !== '.DS_Store',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fresh start every run so a file removed from the source tree doesn't
|
||||||
|
// linger in dist/ from a previous build.
|
||||||
|
fs.rmSync(DIST, { recursive: true, force: true });
|
||||||
|
fs.mkdirSync(DIST, { recursive: true });
|
||||||
|
|
||||||
|
const missing = [];
|
||||||
|
|
||||||
|
for (const file of FILES) {
|
||||||
|
const src = path.join(ROOT, file);
|
||||||
|
if (!fs.existsSync(src)) {
|
||||||
|
missing.push(file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fs.copyFileSync(src, path.join(DIST, file));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const dir of DIRS) {
|
||||||
|
const src = path.join(ROOT, dir);
|
||||||
|
if (!fs.existsSync(src)) {
|
||||||
|
missing.push(dir + '/');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
copyDir(src, path.join(DIST, dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
// db/ ships with just .htaccess (denies direct web access to the sqlite
|
||||||
|
// file) — never the live fitz.sqlite itself. inc/db.php creates the
|
||||||
|
// schema on first run if the file isn't there, so shipping the dev
|
||||||
|
// database would just overwrite whatever is already live on the server.
|
||||||
|
const dbHtaccess = path.join(ROOT, 'db', '.htaccess');
|
||||||
|
if (fs.existsSync(dbHtaccess)) {
|
||||||
|
fs.mkdirSync(path.join(DIST, 'db'), { recursive: true });
|
||||||
|
fs.copyFileSync(dbHtaccess, path.join(DIST, 'db', '.htaccess'));
|
||||||
|
} else {
|
||||||
|
missing.push('db/.htaccess');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missing.length) {
|
||||||
|
console.warn('Warning: expected but not found, skipped:\n ' + missing.join('\n '));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Deploy folder built at ${path.relative(ROOT, DIST)}/`);
|
||||||
File diff suppressed because it is too large.
Load diff
+99
-106
@@ -1,3 +1,4 @@
|
|||||||
|
@charset "UTF-8";
|
||||||
:root {
|
:root {
|
||||||
--ground: #171310;
|
--ground: #171310;
|
||||||
--ground-2: #0f0c0a;
|
--ground-2: #0f0c0a;
|
||||||
@@ -11,11 +12,9 @@
|
|||||||
--ink: #f1e8d8;
|
--ink: #f1e8d8;
|
||||||
--ink-muted: #a89a83;
|
--ink-muted: #a89a83;
|
||||||
--rule: #42362590;
|
--rule: #42362590;
|
||||||
|
|
||||||
--font-serif: 'Fraunces', Georgia, 'Times New Roman', serif;
|
--font-serif: 'Fraunces', Georgia, 'Times New Roman', serif;
|
||||||
--font-mono: 'IBM Plex Mono', ui-monospace, Menlo, monospace;
|
--font-mono: 'IBM Plex Mono', ui-monospace, Menlo, monospace;
|
||||||
--font-sans: 'Karla', ui-sans-serif, system-ui, sans-serif;
|
--font-sans: 'Karla', ui-sans-serif, system-ui, sans-serif;
|
||||||
|
|
||||||
--danger-bg: rgba(180, 50, 40, 0.15);
|
--danger-bg: rgba(180, 50, 40, 0.15);
|
||||||
--danger-text: #ff9d9d;
|
--danger-text: #ff9d9d;
|
||||||
}
|
}
|
||||||
@@ -33,7 +32,6 @@
|
|||||||
scroll-behavior: auto;
|
scroll-behavior: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- wrap-aware separators (JS-toggled, see main.js) ----------
|
/* ---------- wrap-aware separators (JS-toggled, see main.js) ----------
|
||||||
Shared hook used by the announcement banner and hero tagline row: a
|
Shared hook used by the announcement banner and hero tagline row: a
|
||||||
"·" between two pieces of text that can independently wrap onto
|
"·" between two pieces of text that can independently wrap onto
|
||||||
@@ -117,7 +115,7 @@
|
|||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
font-family: var(--font-mono);
|
font-family: var(--font-mono);
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
transition: top .15s ease;
|
transition: top 0.15s ease;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +338,7 @@
|
|||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
color: var(--ink-muted);
|
color: var(--ink-muted);
|
||||||
padding: 0.4rem 0.2rem;
|
padding: 0.4rem 0.2rem;
|
||||||
transition: color .15s ease;
|
transition: color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav.links a:hover {
|
nav.links a:hover {
|
||||||
@@ -387,11 +385,11 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-toggle[aria-expanded="true"] .icon-menu {
|
.nav-toggle[aria-expanded=true] .icon-menu {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-toggle[aria-expanded="true"] .icon-close {
|
.nav-toggle[aria-expanded=true] .icon-close {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,11 +397,9 @@
|
|||||||
.nav-toggle {
|
.nav-toggle {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-cta {
|
.nav-cta {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav.links {
|
nav.links {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -417,16 +413,13 @@
|
|||||||
border-bottom: 1px solid var(--rule);
|
border-bottom: 1px solid var(--rule);
|
||||||
padding: 0.5rem 0;
|
padding: 0.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav.links.is-open {
|
nav.links.is-open {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav.links a {
|
nav.links a {
|
||||||
padding: 0.9rem 1.5rem;
|
padding: 0.9rem 1.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- hero ---------- */
|
/* ---------- hero ---------- */
|
||||||
.hero {
|
.hero {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -447,8 +440,7 @@
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
background:
|
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.12), transparent 22%, transparent 78%, rgba(0, 0, 0, 0.18));
|
||||||
linear-gradient(to bottom, rgba(0, 0, 0, 0.12), transparent 22%, transparent 78%, rgba(0, 0, 0, 0.18));
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,16 +449,14 @@
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-image: url('./assets/brick-texture.png');
|
background-image: url("./assets/brick-texture.png");
|
||||||
background-repeat: repeat;
|
background-repeat: repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-scrim {
|
.hero-scrim {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background:
|
background: linear-gradient(180deg, rgba(15, 12, 10, 0.35) 0%, rgba(15, 12, 10, 0.2) 45%, rgba(15, 12, 10, 0.6) 100%), radial-gradient(ellipse 60% 48% at 50% 18%, rgba(201, 163, 92, 0.16), transparent 58%);
|
||||||
linear-gradient(180deg, rgba(15, 12, 10, 0.35) 0%, rgba(15, 12, 10, 0.2) 45%, rgba(15, 12, 10, 0.6) 100%),
|
|
||||||
radial-gradient(ellipse 60% 48% at 50% 18%, rgba(201, 163, 92, 0.16), transparent 58%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-inner {
|
.hero-inner {
|
||||||
@@ -545,7 +535,7 @@
|
|||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
transition: transform .15s ease, background .15s ease, border-color .15s ease;
|
transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn:hover {
|
.btn:hover {
|
||||||
@@ -688,7 +678,6 @@
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hours / visit band */
|
/* hours / visit band */
|
||||||
.visit {
|
.visit {
|
||||||
background: var(--ground-2);
|
background: var(--ground-2);
|
||||||
@@ -805,7 +794,7 @@
|
|||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
color: var(--ink-muted);
|
color: var(--ink-muted);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: border-color .15s ease, color .15s ease;
|
transition: border-color 0.15s ease, color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.social-row a:hover {
|
.social-row a:hover {
|
||||||
@@ -823,7 +812,6 @@
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* live music band */
|
/* live music band */
|
||||||
.music {
|
.music {
|
||||||
background: linear-gradient(180deg, var(--green-deep), var(--green));
|
background: linear-gradient(180deg, var(--green-deep), var(--green));
|
||||||
@@ -895,20 +883,16 @@
|
|||||||
gap: 2.5rem;
|
gap: 2.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.music-content {
|
.music-content {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.music .section-head {
|
.music .section-head {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.music .hero-ctas {
|
.music .hero-ctas {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* menu band */
|
/* menu band */
|
||||||
.menu-band .container {
|
.menu-band .container {
|
||||||
max-width: 60rem;
|
max-width: 60rem;
|
||||||
@@ -1021,12 +1005,11 @@
|
|||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* scroll reveal */
|
/* scroll reveal */
|
||||||
.reveal {
|
.reveal {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translateY(0.875rem);
|
transform: translateY(0.875rem);
|
||||||
transition: opacity .6s ease, transform .6s ease;
|
transition: opacity 0.6s ease, transform 0.6s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reveal.is-visible {
|
.reveal.is-visible {
|
||||||
@@ -1041,7 +1024,6 @@
|
|||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- admin / management styles ---------- */
|
/* ---------- admin / management styles ---------- */
|
||||||
.admin-login-body {
|
.admin-login-body {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
@@ -1118,7 +1100,7 @@
|
|||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
outline: none;
|
outline: none;
|
||||||
transition: border-color .15s ease;
|
transition: border-color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control:focus,
|
.form-control:focus,
|
||||||
@@ -1209,7 +1191,6 @@
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* two classes each, so these reliably outrank .admin-nav-links's and
|
/* two classes each, so these reliably outrank .admin-nav-links's and
|
||||||
.admin-user's own base-rule gap regardless of source order */
|
.admin-user's own base-rule gap regardless of source order */
|
||||||
.admin-nav-inner .admin-nav-links,
|
.admin-nav-inner .admin-nav-links,
|
||||||
@@ -1218,7 +1199,6 @@
|
|||||||
gap: 0.5rem 1rem;
|
gap: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-layout {
|
.dashboard-layout {
|
||||||
padding-block: 2.5rem 4rem;
|
padding-block: 2.5rem 4rem;
|
||||||
}
|
}
|
||||||
@@ -1268,7 +1248,6 @@
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-actions {
|
.form-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
@@ -1297,7 +1276,7 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-label input[type="checkbox"] {
|
.checkbox-label input[type=checkbox] {
|
||||||
width: 1.15rem;
|
width: 1.15rem;
|
||||||
height: 1.15rem;
|
height: 1.15rem;
|
||||||
accent-color: var(--gold);
|
accent-color: var(--gold);
|
||||||
@@ -1344,7 +1323,7 @@
|
|||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
transition: opacity .15s ease;
|
transition: opacity 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.status-badge:hover {
|
button.status-badge:hover {
|
||||||
@@ -1406,7 +1385,6 @@
|
|||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-sm {
|
.btn-sm {
|
||||||
padding: 0.4rem 0.8rem;
|
padding: 0.4rem 0.8rem;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
@@ -1457,7 +1435,7 @@
|
|||||||
color: var(--ink-muted);
|
color: var(--ink-muted);
|
||||||
padding: 0.35rem 0.65rem;
|
padding: 0.35rem 0.65rem;
|
||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
transition: color .15s ease, background .15s ease;
|
transition: color 0.15s ease, background 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-nav-links a:hover {
|
.admin-nav-links a:hover {
|
||||||
@@ -1592,9 +1570,7 @@
|
|||||||
.category-panel .panel-head {
|
.category-panel .panel-head {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
grid-template-areas:
|
grid-template-areas: "name actions" "desc actions";
|
||||||
"name actions"
|
|
||||||
"desc actions";
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
column-gap: 0.75rem;
|
column-gap: 0.75rem;
|
||||||
}
|
}
|
||||||
@@ -1688,39 +1664,90 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.col-status,
|
.col-status,
|
||||||
.item-row [data-label="Status"],
|
.item-row [data-label=Status],
|
||||||
.ann-row [data-label="Status"],
|
.ann-row [data-label=Status],
|
||||||
.user-row [data-label="Status"] {
|
.user-row [data-label=Status] {
|
||||||
grid-area: status;
|
grid-area: status;
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-actions,
|
.col-actions,
|
||||||
.item-row [data-label="Actions"],
|
.item-row [data-label=Actions],
|
||||||
.ann-row [data-label="Actions"],
|
.ann-row [data-label=Actions],
|
||||||
.user-row [data-label="Actions"] {
|
.user-row [data-label=Actions] {
|
||||||
grid-area: actions;
|
grid-area: actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-item { grid-area: item; }
|
.col-item {
|
||||||
.col-price { grid-area: price; }
|
grid-area: item;
|
||||||
.item-row [data-label="Item"] { grid-area: item; }
|
}
|
||||||
.item-row [data-label="Price"] { grid-area: price; }
|
|
||||||
|
|
||||||
.col-headline { grid-area: headline; }
|
.col-price {
|
||||||
.col-type { grid-area: type; }
|
grid-area: price;
|
||||||
.col-schedule { grid-area: schedule; }
|
}
|
||||||
.col-placements { grid-area: placements; }
|
|
||||||
.ann-row [data-label="Headline"] { grid-area: headline; }
|
|
||||||
.ann-row [data-label="Type"] { grid-area: type; }
|
|
||||||
.ann-row [data-label="Schedule"] { grid-area: schedule; }
|
|
||||||
.ann-row [data-label="Placements"] { grid-area: placements; }
|
|
||||||
|
|
||||||
.col-username { grid-area: username; }
|
.item-row [data-label=Item] {
|
||||||
.col-role { grid-area: role; }
|
grid-area: item;
|
||||||
.col-created { grid-area: created; }
|
}
|
||||||
.user-row [data-label="Username"] { grid-area: username; }
|
|
||||||
.user-row [data-label="Role"] { grid-area: role; }
|
.item-row [data-label=Price] {
|
||||||
.user-row [data-label="Created"] { grid-area: created; }
|
grid-area: price;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-headline {
|
||||||
|
grid-area: headline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-type {
|
||||||
|
grid-area: type;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-schedule {
|
||||||
|
grid-area: schedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-placements {
|
||||||
|
grid-area: placements;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ann-row [data-label=Headline] {
|
||||||
|
grid-area: headline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ann-row [data-label=Type] {
|
||||||
|
grid-area: type;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ann-row [data-label=Schedule] {
|
||||||
|
grid-area: schedule;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ann-row [data-label=Placements] {
|
||||||
|
grid-area: placements;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-username {
|
||||||
|
grid-area: username;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-role {
|
||||||
|
grid-area: role;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-created {
|
||||||
|
grid-area: created;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-row [data-label=Username] {
|
||||||
|
grid-area: username;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-row [data-label=Role] {
|
||||||
|
grid-area: role;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-row [data-label=Created] {
|
||||||
|
grid-area: created;
|
||||||
|
}
|
||||||
|
|
||||||
/* .item-rows being display:contents makes this a direct child of the
|
/* .item-rows being display:contents makes this a direct child of the
|
||||||
.item-grid-wrap grid when a category is empty — span every column or
|
.item-grid-wrap grid when a category is empty — span every column or
|
||||||
@@ -1783,7 +1810,6 @@
|
|||||||
.user-grid-wrap {
|
.user-grid-wrap {
|
||||||
grid-template-columns: 1fr minmax(0, auto);
|
grid-template-columns: 1fr minmax(0, auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Users' actions column gets a fixed cap instead of auto: "Change
|
/* Users' actions column gets a fixed cap instead of auto: "Change
|
||||||
Password" is long enough that its max-content size (what auto would
|
Password" is long enough that its max-content size (what auto would
|
||||||
size the column to) is wider than this corner has room for, which
|
size the column to) is wider than this corner has room for, which
|
||||||
@@ -1792,7 +1818,6 @@
|
|||||||
.user-grid-wrap {
|
.user-grid-wrap {
|
||||||
grid-template-columns: minmax(0, 1fr) 6rem;
|
grid-template-columns: minmax(0, 1fr) 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Every row's Actions cell holds one or two .action-stacks (move
|
/* Every row's Actions cell holds one or two .action-stacks (move
|
||||||
up/down, edit/delete, etc. — each stacked vertically, see
|
up/down, edit/delete, etc. — each stacked vertically, see
|
||||||
.action-stack itself further up) side by side. Keeps those stacks
|
.action-stack itself further up) side by side. Keeps those stacks
|
||||||
@@ -1803,13 +1828,11 @@
|
|||||||
.user-row .row-actions {
|
.user-row .row-actions {
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-grid-head,
|
.item-grid-head,
|
||||||
.ann-grid-head,
|
.ann-grid-head,
|
||||||
.user-grid-head {
|
.user-grid-head {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-row,
|
.item-row,
|
||||||
.ann-row,
|
.ann-row,
|
||||||
.user-row {
|
.user-row {
|
||||||
@@ -1819,14 +1842,12 @@
|
|||||||
padding: 0.9rem 1rem;
|
padding: 0.9rem 1rem;
|
||||||
margin-bottom: 0.85rem;
|
margin-bottom: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-row:last-child,
|
.item-row:last-child,
|
||||||
.ann-row:last-child,
|
.ann-row:last-child,
|
||||||
.user-row:last-child {
|
.user-row:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-row [data-label]::before,
|
.item-row [data-label]::before,
|
||||||
.ann-row [data-label]::before,
|
.ann-row [data-label]::before,
|
||||||
.user-row [data-label]::before {
|
.user-row [data-label]::before {
|
||||||
@@ -1839,12 +1860,8 @@
|
|||||||
color: var(--gold);
|
color: var(--gold);
|
||||||
margin-bottom: 0.3rem;
|
margin-bottom: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-row {
|
.item-row {
|
||||||
grid-template-areas:
|
grid-template-areas: "status actions" "item item" "price price";
|
||||||
"status actions"
|
|
||||||
"item item"
|
|
||||||
"price price";
|
|
||||||
/* Overrides the shared align-items: center above — on desktop that
|
/* Overrides the shared align-items: center above — on desktop that
|
||||||
vertically centers Status against the taller Item cell in one wide
|
vertically centers Status against the taller Item cell in one wide
|
||||||
row, which is fine, but here it also centers Status against the
|
row, which is fine, but here it also centers Status against the
|
||||||
@@ -1852,26 +1869,14 @@
|
|||||||
keeping both flush with the card's top edge. */
|
keeping both flush with the card's top edge. */
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ann-row {
|
.ann-row {
|
||||||
grid-template-areas:
|
grid-template-areas: "status actions" "headline headline" "type type" "schedule schedule" "placements placements";
|
||||||
"status actions"
|
|
||||||
"headline headline"
|
|
||||||
"type type"
|
|
||||||
"schedule schedule"
|
|
||||||
"placements placements";
|
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-row {
|
.user-row {
|
||||||
grid-template-areas:
|
grid-template-areas: "status actions" "username username" "role role" "created created";
|
||||||
"status actions"
|
|
||||||
"username username"
|
|
||||||
"role role"
|
|
||||||
"created created";
|
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stretches Actions' whole flex chain out to the fixed 6rem column
|
/* Stretches Actions' whole flex chain out to the fixed 6rem column
|
||||||
above (each is shrink-wrapped by default), then lets "Change
|
above (each is shrink-wrapped by default), then lets "Change
|
||||||
Password" — long enough on its own to blow out this corner next to a
|
Password" — long enough on its own to blow out this corner next to a
|
||||||
@@ -1883,21 +1888,15 @@
|
|||||||
.user-row .row-actions .btn {
|
.user-row .row-actions .btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-row .btn-change-password {
|
.user-row .btn-change-password {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-panel .panel-head {
|
.category-panel .panel-head {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-areas:
|
grid-template-areas: "name" "desc" "actions";
|
||||||
"name"
|
|
||||||
"desc"
|
|
||||||
"actions";
|
|
||||||
row-gap: 0.5rem;
|
row-gap: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- admin modal dialogs ---------- */
|
/* ---------- admin modal dialogs ---------- */
|
||||||
.admin-modal-backdrop {
|
.admin-modal-backdrop {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -1911,7 +1910,7 @@
|
|||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: opacity .2s ease;
|
transition: opacity 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-modal-backdrop.is-open {
|
.admin-modal-backdrop.is-open {
|
||||||
@@ -1930,7 +1929,7 @@
|
|||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.6);
|
box-shadow: 0 1.5rem 3rem rgba(0, 0, 0, 0.6);
|
||||||
transform: translateY(0.75rem);
|
transform: translateY(0.75rem);
|
||||||
transition: transform .2s ease;
|
transition: transform 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-modal-backdrop.is-open .admin-modal {
|
.admin-modal-backdrop.is-open .admin-modal {
|
||||||
@@ -1961,7 +1960,7 @@
|
|||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: color .15s ease;
|
transition: color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close:hover {
|
.modal-close:hover {
|
||||||
@@ -2002,7 +2001,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
transition: color .15s ease;
|
transition: color 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.password-toggle-btn:hover {
|
.password-toggle-btn:hover {
|
||||||
@@ -2089,11 +2088,9 @@
|
|||||||
.hours-grid-wrap {
|
.hours-grid-wrap {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hours-grid-head {
|
.hours-grid-head {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hours-day-row {
|
.hours-day-row {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
row-gap: 0.5rem;
|
row-gap: 0.5rem;
|
||||||
@@ -2102,11 +2099,9 @@
|
|||||||
padding: 0.9rem 1rem;
|
padding: 0.9rem 1rem;
|
||||||
margin-bottom: 0.85rem;
|
margin-bottom: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hours-day-row:last-child {
|
.hours-day-row:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hours-day-row [data-label]::before {
|
.hours-day-row [data-label]::before {
|
||||||
content: attr(data-label);
|
content: attr(data-label);
|
||||||
display: block;
|
display: block;
|
||||||
@@ -2117,12 +2112,10 @@
|
|||||||
color: var(--gold);
|
color: var(--gold);
|
||||||
margin-bottom: 0.3rem;
|
margin-bottom: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hours-day-row .form-control {
|
.hours-day-row .form-control {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Live preview panel: mimics the public site's Visit card and footer
|
/* Live preview panel: mimics the public site's Visit card and footer
|
||||||
mini-summary without depending on their .card/footer ancestor scoping
|
mini-summary without depending on their .card/footer ancestor scoping
|
||||||
(this lives inside an admin .panel, which already shares that same
|
(this lives inside an admin .panel, which already shares that same
|
||||||
|
|||||||
Reference in new issue
Block a user