Adopt the Stitch design system

Google Stitch produced an Atelier Dining & Hospitality system for this app: warm
ivory linen and espresso for the guest surfaces, burnished gold for the single
active thing, Playfair Display for the restaurant's voice and Plus Jakarta Sans
for everything transactional, editorial rows with dot leaders, pill controls,
hairline containment instead of drop shadows. The four screens and the system
document are kept in docs/design/stitch/ as the source.

Both fonts are now self-hosted with their licences, the guest stylesheet is
rebuilt on the system, and the admin is the same system in its dark mode
(espresso workspace, obsidian pods, gold actions) by overriding the same tokens
at a higher specificity, since the per-Site theme is injected inline after the
stylesheets. The Site theme in config/ moves to the system's palette, which is
where per-Site branding belongs; the old Archivo font is dropped.
This commit is contained in:
tanshu committed 2026-09-22 23:07:38 +05:30
1 parent a29c5c4b0c
commit b13042f0db
17 files changed
+679 -191

No files matched your search

+218 -175
View File
@@ -1,49 +1,54 @@
/* Hops n Grains menus.
The chrome is the shelf; the menus are the paper standing on it. Brass is the
taproom's metal, the logo's teal is the only active colour, and the paper of
the photographed menus is the brightest thing on the page. */
/* Hops n Grains menus, to the Atelier Dining & Hospitality system that came out
of Stitch: ivory linen and espresso for the guest's menu, burnished gold for
the one active thing on screen, Playfair Display carrying the restaurant's
voice and Plus Jakarta Sans carrying everything transactional.
See docs/design/stitch/atelier-dining-hospitality.md. */
@font-face {
font-family: 'Archivo';
font-family: 'Playfair Display';
font-style: normal;
font-weight: 100 900;
font-stretch: 62% 125%;
font-weight: 400 700;
font-display: swap;
src: url('/assets/fonts/archivo-latin.woff2') format('woff2');
src: url('/assets/fonts/playfair-display-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Archivo';
font-family: 'Plus Jakarta Sans';
font-style: normal;
font-weight: 100 900;
font-stretch: 62% 125%;
font-weight: 200 800;
font-display: swap;
src: url('/assets/fonts/archivo-latin-ext.woff2') format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
U+2C60-2C7F, U+A720-A7FF;
src: url('/assets/fonts/plus-jakarta-sans-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
:root {
--steel: #101719;
--rail: #182125;
--paper: #efeae0;
--accent: #0088aa;
--copper: #c08544;
--ink: #e8e5dd;
--ink-dim: #8f979a;
--ink-on-paper: #1b1f22;
--brass-edge: color-mix(in srgb, var(--copper) 42%, transparent);
--hairline: color-mix(in srgb, var(--copper) 26%, transparent);
--hairline-soft: color-mix(in srgb, var(--copper) 14%, transparent);
--sheet-shadow: color-mix(in srgb, #000 45%, transparent);
/* guest surfaces: warm ivory linen, never stark white */
--steel: #faf8f5;
--rail: #f4f1ea;
--paper: #ffffff;
--ink: #121110;
--ink-soft: #4b4640;
--ink-dim: #8c857b;
--ink-on-paper: #121110;
--accent: #c59b58;
--copper: #b08544;
--hairline: #e6e1d8;
--hairline-soft: #efebe4;
--sheet-shadow: rgba(18, 17, 16, 0.06);
--shadow-card: 0 4px 20px -2px rgba(18, 17, 16, 0.04), 0 2px 6px -1px rgba(18, 17, 16, 0.02);
--shadow-float: 0 12px 36px -4px rgba(18, 17, 16, 0.08), 0 4px 12px -2px rgba(18, 17, 16, 0.04);
--font-display: 'Playfair Display', Georgia, 'Times New Roman', serif;
--font-ui: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
--radius-card: 0.5rem;
--radius-pill: 9999px;
--step-0: 1rem;
--step-1: 1.25rem;
--step-2: 1.55rem;
--step-2: 1.75rem;
--page-max: 780px;
--content-max: 52rem;
--content-max: 46rem;
}
*,
@@ -60,7 +65,7 @@ body {
margin: 0;
background: var(--steel);
color: var(--ink);
font-family: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
font-family: var(--font-ui);
font-size: var(--step-0);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
@@ -76,70 +81,62 @@ a {
outline-offset: 3px;
}
/* ---------- Landing: the menus as tap handles ----------
Each category is a card whose face is the first page of that menu, so the
navigation is made of the restaurant's own paper. The row scrolls sideways
and snaps; on a wide screen it wraps into a grid instead. */
/* Every uppercase label in this system is tracked, never tight. */
.label {
font-size: 0.68rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
}
/* ---------- Landing: the menu directory ---------- */
.landing {
max-width: var(--content-max);
margin: 0 auto;
padding: 0 0 3rem;
padding: 0 1.25rem 3.5rem;
}
.masthead {
padding: clamp(2.2rem, 10vh, 4.5rem) 1.1rem 1.5rem;
padding: clamp(2.25rem, 10vh, 4.5rem) 0 1.75rem;
border-bottom: 1px solid var(--hairline);
}
.wordmark {
margin: 0;
font-size: clamp(1.95rem, 8.5vw, 2.9rem);
font-weight: 700;
font-stretch: 118%;
letter-spacing: -0.025em;
line-height: 1;
font-family: var(--font-display);
font-size: clamp(2rem, 8vw, 2.75rem);
font-weight: 400;
letter-spacing: -0.02em;
line-height: 1.05;
}
.masthead__tagline {
margin: 0.5rem 0 0;
color: var(--ink-dim);
font-size: 0.98rem;
margin: 0.6rem 0 0;
color: var(--ink-soft);
font-size: 0.95rem;
}
.shelves {
display: flex;
gap: 0.85rem;
padding: 0.15rem 0 1rem 1.1rem;
overflow-x: auto;
scroll-snap-type: x mandatory;
/* snap against the same inset the first card starts at, so nothing is ever
left half-scrolled under the screen edge */
scroll-padding-left: 1.1rem;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
}
.shelves::-webkit-scrollbar {
display: none;
display: block;
}
.shelf {
position: relative;
flex: 0 0 10.5rem;
height: 15rem;
overflow: hidden;
background: var(--paper);
box-shadow: 0 1px 0 var(--sheet-shadow);
scroll-snap-align: start;
display: flex;
align-items: center;
gap: 0.9rem;
padding: 0.95rem 0;
border-bottom: 1px solid var(--hairline);
}
.shelf__peek {
position: absolute;
top: 0;
right: 0;
bottom: 3.2rem;
left: 0;
display: block;
flex: 0 0 auto;
width: 3.4rem;
height: 4.4rem;
overflow: hidden;
border: 1px solid var(--hairline);
border-radius: var(--radius-card);
background: var(--paper);
}
.shelf__peek img {
@@ -152,49 +149,48 @@ a {
}
.shelf__name {
position: absolute;
right: 0;
bottom: 3.2rem;
left: 0;
padding: 0.45rem 0.6rem;
background: color-mix(in srgb, var(--steel) 88%, transparent);
font-size: 1.05rem;
font-weight: 700;
font-family: var(--font-display);
font-size: 1.45rem;
font-weight: 400;
letter-spacing: -0.01em;
}
.shelf__pages {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 3.2rem;
padding: 0.85rem 0.6rem;
background: var(--paper);
color: var(--ink-on-paper);
font-size: 0.8rem;
font-variant-numeric: tabular-nums;
line-height: 1.15;
}
.shelf:hover .shelf__name,
.shelf:focus-visible .shelf__name {
background: color-mix(in srgb, var(--accent) 90%, transparent);
color: var(--steel);
color: var(--amber-deep, #b08544);
}
.shelf:hover .shelf__peek img,
.shelf:focus-visible .shelf__peek img {
transform: scale(1.04);
transform: scale(1.05);
}
/* the dot leader that carries the eye from the name to the count */
.leader {
flex: 1 1 auto;
align-self: flex-end;
margin-bottom: 0.4rem;
border-bottom: 1px dotted #cdc5bd;
}
.shelf__pages {
flex: 0 0 auto;
color: var(--ink-soft);
font-size: 0.78rem;
font-weight: 600;
font-variant-numeric: tabular-nums;
letter-spacing: 0.02em;
}
.empty {
max-width: 34ch;
margin: 1rem 1.1rem 0;
color: var(--ink-dim);
font-size: var(--step-1);
margin: 1.25rem 0 0;
color: var(--ink-soft);
font-size: 1.05rem;
}
/* ---------- Section page: the bar and the switcher ---------- */
/* ---------- Section page: the menu bar ---------- */
.bar {
position: sticky;
@@ -202,27 +198,38 @@ a {
z-index: 20;
display: flex;
align-items: center;
gap: 0.7rem;
padding: 0.5rem 0.85rem 0.45rem;
background: color-mix(in srgb, var(--rail) 94%, transparent);
backdrop-filter: blur(6px);
gap: 1rem;
padding: 0.6rem 1.25rem;
background: color-mix(in srgb, var(--steel) 92%, transparent);
backdrop-filter: blur(8px);
border-bottom: 1px solid var(--hairline);
}
.bar__brand {
display: flex;
align-items: center;
gap: 0.55rem;
flex: 0 0 auto;
}
.bar__brand img {
display: block;
width: 24px;
height: 24px;
width: 26px;
height: 26px;
border-radius: var(--radius-pill);
}
.bar__name {
font-family: var(--font-display);
font-size: 1.05rem;
letter-spacing: -0.01em;
white-space: nowrap;
}
.bar__nav {
display: flex;
flex: 1 1 auto;
gap: 0.15rem;
gap: 0.35rem;
overflow-x: auto;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
@@ -233,38 +240,41 @@ a {
}
.bar__link {
padding: 0.35rem 0.65rem;
background: color-mix(in srgb, var(--ink) 9%, transparent);
color: var(--ink-dim);
font-size: 0.95rem;
padding: 0.42rem 0.9rem;
border: 1px solid transparent;
border-radius: var(--radius-pill);
color: var(--ink-soft);
font-size: 0.78rem;
font-weight: 600;
letter-spacing: 0.02em;
white-space: nowrap;
transition: background 0.18s ease, color 0.18s ease;
}
.bar__link:hover {
background: color-mix(in srgb, var(--accent) 16%, transparent);
color: var(--ink);
background: color-mix(in srgb, var(--ink) 15%, transparent);
}
.bar__link.is-current {
background: var(--accent);
background: var(--ink);
color: var(--steel);
font-weight: 700;
}
.pour {
position: absolute;
right: 0;
bottom: 0;
bottom: -1px;
left: 0;
height: 2px;
background: var(--hairline-soft);
background: transparent;
}
.pour__fill {
display: block;
width: 0;
height: 100%;
background: var(--copper);
background: var(--accent);
}
/* ---------- The pages themselves ---------- */
@@ -275,52 +285,58 @@ a {
justify-content: space-between;
gap: 1rem;
max-width: var(--page-max);
margin: 1.2rem auto 0.75rem;
padding: 0 0.9rem;
margin: 1.75rem auto 1rem;
padding: 0 1.25rem;
}
.section-heading__label {
font-family: var(--font-display);
font-size: var(--step-2);
font-weight: 700;
letter-spacing: -0.02em;
font-weight: 400;
letter-spacing: -0.015em;
}
.section-heading__date {
color: var(--ink-dim);
font-size: 0.88rem;
font-size: 0.68rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
font-variant-numeric: tabular-nums;
}
.notice {
max-width: var(--page-max);
margin: 0 auto 1rem;
padding: 0.6rem 0.8rem;
border-left: 2px solid var(--copper);
margin: 0 auto 1.25rem;
padding: 0.7rem 0.9rem;
border-left: 2px solid var(--accent);
background: var(--rail);
font-size: 0.95rem;
font-size: 0.9rem;
}
.notice a {
color: var(--accent);
color: var(--copper);
text-decoration: underline;
}
.notice--admin {
max-width: none;
border-left-color: var(--accent);
background: color-mix(in srgb, var(--accent) 20%, var(--rail));
background: color-mix(in srgb, var(--accent) 12%, var(--rail));
}
.pages {
max-width: var(--page-max);
margin: 0 auto;
padding: 0 0.7rem 1.25rem;
padding: 0 1.25rem 1.5rem;
}
.page {
margin: 0 0 0.6rem;
margin: 0 0 0.85rem;
padding: 0.4rem;
background: var(--paper);
box-shadow: 0 1px 0 color-mix(in srgb, #000 35%, transparent);
border: 1px solid var(--hairline);
border-radius: var(--radius-card);
box-shadow: var(--shadow-card);
}
.page__zoom {
@@ -331,25 +347,29 @@ a {
display: block;
width: 100%;
height: auto;
border-radius: 0.25rem;
}
/* ---------- Footer: page index and older menus ---------- */
.foot {
max-width: var(--page-max);
margin: 0 auto 4.5rem;
padding: 0 0.9rem 1rem;
border-top: 1px solid var(--hairline-soft);
margin: 0 auto 5rem;
padding: 0 1.25rem 1rem;
border-top: 1px solid var(--hairline);
}
.fold {
padding: 0.7rem 0;
border-bottom: 1px solid var(--hairline-soft);
padding: 0.85rem 0;
border-bottom: 1px solid var(--hairline);
}
.fold summary {
color: var(--ink-dim);
font-size: 0.92rem;
color: var(--ink-soft);
font-size: 0.68rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
cursor: pointer;
}
@@ -360,29 +380,33 @@ a {
.index {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
gap: 0.45rem;
margin: 0;
padding: 0.85rem 0 0;
padding: 1rem 0 0;
list-style: none;
}
.index a {
display: block;
min-width: 2.3rem;
padding: 0.3rem 0.45rem;
background: var(--rail);
min-width: 2.4rem;
padding: 0.35rem 0.5rem;
border: 1px solid var(--hairline);
border-radius: var(--radius-pill);
color: var(--ink-soft);
font-size: 0.78rem;
font-weight: 600;
font-variant-numeric: tabular-nums;
text-align: center;
}
.index a:hover,
.index a:focus-visible {
background: var(--accent);
background: var(--ink);
color: var(--steel);
}
.older {
margin: 0.5rem 0 0;
margin: 0.6rem 0 0;
padding: 0;
list-style: none;
}
@@ -391,25 +415,30 @@ a {
display: flex;
justify-content: space-between;
gap: 1rem;
padding: 0.45rem 0.15rem;
padding: 0.55rem 0.15rem;
border-bottom: 1px solid var(--hairline-soft);
}
.older__label {
font-weight: 500;
font-family: var(--font-display);
font-size: 1.05rem;
}
.older__date {
color: var(--ink-dim);
font-size: 0.88rem;
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
font-variant-numeric: tabular-nums;
}
.fold__back {
margin: 0.7rem 0 0;
margin: 0.85rem 0 0;
}
.fold__back a {
color: var(--accent);
color: var(--copper);
text-decoration: underline;
}
@@ -417,19 +446,24 @@ a {
.counter {
position: fixed;
right: 0.85rem;
bottom: calc(0.85rem + env(safe-area-inset-bottom));
right: 1.25rem;
bottom: calc(1.25rem + env(safe-area-inset-bottom));
z-index: 30;
display: inline-flex;
align-items: baseline;
gap: 0.3rem;
padding: 0.45rem 0.7rem;
border: 1px solid var(--brass-edge);
background: var(--paper);
color: var(--ink-on-paper);
gap: 0.35rem;
padding: 0.55rem 0.9rem;
border: 0;
border-radius: var(--radius-pill);
background: var(--ink);
color: var(--steel);
font: inherit;
font-size: 0.88rem;
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
font-variant-numeric: tabular-nums;
box-shadow: var(--shadow-float);
cursor: pointer;
}
@@ -438,7 +472,7 @@ a {
}
.counter__total {
color: color-mix(in srgb, var(--ink-on-paper) 55%, transparent);
color: color-mix(in srgb, var(--steel) 62%, transparent);
}
.zoom {
@@ -446,8 +480,10 @@ a {
inset: 0;
z-index: 50;
overflow: auto;
background: rgba(6, 9, 10, 0.96);
background: rgba(18, 17, 16, 0.45);
backdrop-filter: blur(8px);
-webkit-overflow-scrolling: touch;
padding: 1.25rem 0;
}
.zoom img {
@@ -455,34 +491,41 @@ a {
width: min(100%, 1600px);
height: auto;
margin: 0 auto;
border-radius: var(--radius-card);
box-shadow: var(--shadow-float);
}
.zoom__close {
position: fixed;
top: 0.6rem;
right: 0.6rem;
top: 0.75rem;
right: 0.75rem;
z-index: 1;
padding: 0.5rem 0.75rem;
border: 1px solid var(--brass-edge);
background: var(--paper);
color: var(--ink-on-paper);
padding: 0.55rem 1rem;
border: 0;
border-radius: var(--radius-pill);
background: var(--ink);
color: var(--steel);
font: inherit;
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
cursor: pointer;
}
/* ---------- Wider screens ---------- */
@media (min-width: 62rem) {
.shelves {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
gap: 1rem;
padding: 0.15rem 1.1rem 1rem;
overflow: visible;
.landing {
padding-bottom: 4.5rem;
}
.shelf {
height: 16rem;
padding: 1.15rem 0;
}
.shelf__name {
font-size: 1.7rem;
}
.pages {
@@ -492,7 +535,6 @@ a {
@media print {
.bar,
.sheet,
.counter,
.fold,
.notice {
@@ -501,10 +543,11 @@ a {
body {
background: #fff;
color: #000;
}
.page {
border: 0;
box-shadow: none;
break-inside: avoid;
}
}