feat: phase 1 public site skeleton — layout, routes, CSS, logo pipeline
Ship base Jinja layout (header/nav/main/footer with skip link and aria-current), mobile-first single-file CSS using the ROADMAP palette tokens, and four public routes: /, /about, /contact, /shop. Blog index renders via a stable PostService.list_published() stub returning [] — Phase 2 only swaps the body. About is static placeholder copy, /contact ships an inert form plus a mailto: link driven by ADMIN_CONTACT_EMAIL, /shop shows a "Coming soon" card. Adds a Pillow-based scripts/generate_static_assets.py producing resized logo PNG + WebP, multi-size favicon.ico, and a 180x180 apple-touch-icon on a cream background. Outputs committed for a reproducible build. Also ship docs/MANUAL_TESTING.md with per-route / responsive / a11y / static- asset checklists, and mark Phase 1 complete in docs/ROADMAP.md.
This commit is contained in:
496
app/static/css/site.css
Normal file
496
app/static/css/site.css
Normal file
@@ -0,0 +1,496 @@
|
||||
/* -------------------------------------------------------------------------
|
||||
* Chicken Babies R Us — site.css
|
||||
*
|
||||
* Single stylesheet for the public brochure site. Mobile-first; one
|
||||
* breakpoint at 48rem (~768px) for tablet and up. Self-hosted only; no
|
||||
* external font imports or third-party CSS.
|
||||
*
|
||||
* Table of contents
|
||||
* 1. Reset
|
||||
* 2. Design tokens (:root custom properties from ROADMAP palette)
|
||||
* 3. Base typography + body
|
||||
* 4. Layout primitives (.wrap, header, nav, main, footer)
|
||||
* 5. Components (.post-card, .shop-card, .contact-form, .btn, skip-link)
|
||||
* 6. Responsive (48rem breakpoint)
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* 1. Reset ---------------------------------------------------------------- */
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
h1, h2, h3, h4, h5, h6,
|
||||
p,
|
||||
figure,
|
||||
blockquote,
|
||||
dl,
|
||||
dd {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1.5;
|
||||
min-height: 100vh;
|
||||
text-rendering: optimizeSpeed;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
img,
|
||||
picture {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
/* 2. Design tokens -------------------------------------------------------- */
|
||||
:root {
|
||||
/* Palette (authoritative values from docs/ROADMAP.md Visual Design). */
|
||||
--c-sky: #A9CCE3;
|
||||
--c-sky-deep: #5D8AA8;
|
||||
--c-cream: #FAF3E7;
|
||||
--c-wheat: #E4D4A8;
|
||||
--c-ink: #2B3A42;
|
||||
--c-leaf: #7FA66B;
|
||||
|
||||
/* Type stacks: system fonts only so we never hit a third-party CDN. */
|
||||
--font-serif: Georgia, "Times New Roman", serif;
|
||||
--font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
||||
|
||||
/* Spacing scale (rem-based; base = 1rem = 16px). */
|
||||
--space-1: 0.25rem;
|
||||
--space-2: 0.5rem;
|
||||
--space-3: 1rem;
|
||||
--space-4: 1.5rem;
|
||||
--space-5: 2.5rem;
|
||||
--space-6: 4rem;
|
||||
|
||||
--radius: 0.5rem;
|
||||
--max-width: 68rem;
|
||||
}
|
||||
|
||||
|
||||
/* 3. Base typography + body ---------------------------------------------- */
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
background-color: var(--c-cream);
|
||||
color: var(--c-ink);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-serif);
|
||||
color: var(--c-ink);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 { font-size: 2rem; }
|
||||
h2 { font-size: 1.5rem; }
|
||||
h3 { font-size: 1.25rem; }
|
||||
|
||||
p {
|
||||
margin-block: var(--space-3);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--c-sky-deep);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus-visible {
|
||||
color: var(--c-ink);
|
||||
}
|
||||
|
||||
/* Utility: visually hide but keep available to assistive tech. */
|
||||
.visually-hidden {
|
||||
position: absolute !important;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
/* 4. Layout primitives ---------------------------------------------------- */
|
||||
.wrap {
|
||||
width: 100%;
|
||||
max-width: var(--max-width);
|
||||
margin-inline: auto;
|
||||
padding-inline: var(--space-3);
|
||||
}
|
||||
|
||||
/* Skip link — hidden offscreen until focused by keyboard. */
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
background-color: var(--c-ink);
|
||||
color: var(--c-cream);
|
||||
text-decoration: none;
|
||||
transform: translateY(-120%);
|
||||
transition: transform 0.15s ease-out;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.skip-link:focus {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* Header / brand / nav ---------------------------------------------------- */
|
||||
.site-header {
|
||||
background-color: var(--c-sky);
|
||||
border-bottom: 1px solid rgba(43, 58, 66, 0.1);
|
||||
}
|
||||
|
||||
.site-header__wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
padding-block: var(--space-3);
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.site-header__brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site-header__logo {
|
||||
height: 48px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Mobile nav toggle (shown < 48rem, hidden ≥ 48rem). */
|
||||
.site-nav__toggle {
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
border: 1px solid var(--c-ink);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--space-2);
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 4px;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
.site-nav__toggle-bar {
|
||||
display: block;
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
background-color: var(--c-ink);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* Collapsed by default on narrow viewports. */
|
||||
.site-nav {
|
||||
flex-basis: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.site-nav.is-open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.site-nav__list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-2);
|
||||
padding-block: var(--space-2);
|
||||
}
|
||||
|
||||
.site-nav__link {
|
||||
display: block;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
border-radius: var(--radius);
|
||||
text-decoration: none;
|
||||
color: var(--c-ink);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.site-nav__link:hover,
|
||||
.site-nav__link:focus-visible {
|
||||
background-color: rgba(255, 255, 255, 0.35);
|
||||
color: var(--c-ink);
|
||||
}
|
||||
|
||||
.site-nav__link.is-active {
|
||||
background-color: var(--c-cream);
|
||||
color: var(--c-sky-deep);
|
||||
}
|
||||
|
||||
/* Muted link for not-yet-live destinations (Shop in Phase 1). */
|
||||
.site-nav__link.nav--muted {
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
/* Main + footer ----------------------------------------------------------- */
|
||||
.site-main {
|
||||
flex: 1 0 auto;
|
||||
padding-block: var(--space-5);
|
||||
}
|
||||
|
||||
/* Remove default focus ring on <main> when focused via the skip link. */
|
||||
.site-main:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
background-color: var(--c-ink);
|
||||
color: var(--c-cream);
|
||||
padding-block: var(--space-4);
|
||||
margin-top: var(--space-6);
|
||||
}
|
||||
|
||||
.site-footer a {
|
||||
color: var(--c-sky);
|
||||
}
|
||||
|
||||
.site-footer__tag {
|
||||
margin: 0;
|
||||
font-family: var(--font-serif);
|
||||
}
|
||||
|
||||
.site-footer__legal {
|
||||
margin-top: var(--space-2);
|
||||
font-size: 0.875rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
|
||||
/* 5. Components ---------------------------------------------------------- */
|
||||
|
||||
/* Page intro block on home. */
|
||||
.page-intro {
|
||||
margin-bottom: var(--space-5);
|
||||
}
|
||||
|
||||
.page-intro__title {
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.page-intro__lede {
|
||||
font-size: 1.125rem;
|
||||
color: var(--c-ink);
|
||||
max-width: 48rem;
|
||||
}
|
||||
|
||||
/* Generic article wrapper for About, Contact, Shop. */
|
||||
.page-article {
|
||||
max-width: 48rem;
|
||||
}
|
||||
|
||||
.page-article__header {
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.page-article__title {
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
/* Post list + card. */
|
||||
.post-list {
|
||||
display: grid;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.post-list__empty {
|
||||
padding: var(--space-4);
|
||||
background-color: var(--c-wheat);
|
||||
border-radius: var(--radius);
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.post-card {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid var(--c-wheat);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--space-4);
|
||||
box-shadow: 0 1px 2px rgba(43, 58, 66, 0.06);
|
||||
}
|
||||
|
||||
.post-card__header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-1);
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.post-card__title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.post-card__title a {
|
||||
color: var(--c-ink);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.post-card__title a:hover,
|
||||
.post-card__title a:focus-visible {
|
||||
color: var(--c-sky-deep);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.post-card__date {
|
||||
font-size: 0.875rem;
|
||||
color: var(--c-sky-deep);
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.post-card__excerpt {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Shop "coming soon" card. */
|
||||
.shop-card {
|
||||
background-color: var(--c-wheat);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--space-4);
|
||||
}
|
||||
|
||||
.shop-card__title {
|
||||
margin-bottom: var(--space-2);
|
||||
color: var(--c-ink);
|
||||
}
|
||||
|
||||
.shop-card__body {
|
||||
margin-block: var(--space-2);
|
||||
}
|
||||
|
||||
/* Contact form (inert in Phase 1). */
|
||||
.contact-mailto {
|
||||
background-color: var(--c-sky);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--space-3);
|
||||
}
|
||||
|
||||
.contact-mailto--muted {
|
||||
background-color: var(--c-wheat);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.contact-form {
|
||||
display: grid;
|
||||
gap: var(--space-3);
|
||||
max-width: 32rem;
|
||||
margin-top: var(--space-3);
|
||||
}
|
||||
|
||||
.contact-form__note {
|
||||
margin-top: var(--space-3);
|
||||
font-style: italic;
|
||||
color: var(--c-sky-deep);
|
||||
}
|
||||
|
||||
.contact-form__field {
|
||||
display: grid;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.contact-form__field label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.contact-form__field input,
|
||||
.contact-form__field textarea {
|
||||
padding: var(--space-2);
|
||||
border: 1px solid var(--c-wheat);
|
||||
border-radius: var(--radius);
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.contact-form__field input:disabled,
|
||||
.contact-form__field textarea:disabled {
|
||||
background-color: #f5f1e6;
|
||||
color: #7a7a7a;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.contact-form__actions {
|
||||
margin-top: var(--space-2);
|
||||
}
|
||||
|
||||
/* Generic button. */
|
||||
.btn {
|
||||
display: inline-block;
|
||||
padding: var(--space-2) var(--space-4);
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid transparent;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn--primary {
|
||||
background-color: var(--c-sky-deep);
|
||||
color: var(--c-cream);
|
||||
}
|
||||
|
||||
.btn--primary:hover,
|
||||
.btn--primary:focus-visible {
|
||||
background-color: var(--c-ink);
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
|
||||
/* 6. Responsive — tablet & up ------------------------------------------- */
|
||||
@media (min-width: 48rem) {
|
||||
h1 { font-size: 2.5rem; }
|
||||
h2 { font-size: 1.75rem; }
|
||||
|
||||
.site-header__wrap {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
/* Hide the mobile toggle; show the nav inline. */
|
||||
.site-nav__toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
display: block;
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.site-nav__list {
|
||||
flex-direction: row;
|
||||
gap: var(--space-3);
|
||||
padding-block: 0;
|
||||
}
|
||||
|
||||
.post-list {
|
||||
gap: var(--space-5);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user