Files
menu/public/styles.css
T
tanshu a29c5c4b0c Make the navigation out of the menus themselves
Variant B of the prototype (/prototype/menu-design branch): each category is a
card whose face is the first page of that menu, so the landing is built from the
restaurant's own paper instead of labels on a dark page. The row scrolls and
snaps on a phone and wraps into a grid on a desktop; the cards are drawn from
the existing tokens, not the prototype's hexes. The bar's links become filled
segments, the current one the only teal thing on screen.

Fixes the scroller's first card being clipped: a negative-margin full bleed was
fighting scroll-snap, so the row now insets its first card and snaps to the same
inset.
2026-09-22 22:39:01 +05:30

521 lines
9.6 KiB
CSS

/* 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. */
@font-face {
font-family: 'Archivo';
font-style: normal;
font-weight: 100 900;
font-stretch: 62% 125%;
font-display: swap;
src: url('/assets/fonts/archivo-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-style: normal;
font-weight: 100 900;
font-stretch: 62% 125%;
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;
}
: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);
--step-0: 1rem;
--step-1: 1.25rem;
--step-2: 1.55rem;
--page-max: 780px;
--content-max: 52rem;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
background: var(--steel);
color: var(--ink);
font-family: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
font-size: var(--step-0);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
a {
color: inherit;
text-decoration: none;
}
:focus-visible {
outline: 2px solid var(--accent);
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. */
.landing {
max-width: var(--content-max);
margin: 0 auto;
padding: 0 0 3rem;
}
.masthead {
padding: clamp(2.2rem, 10vh, 4.5rem) 1.1rem 1.5rem;
}
.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;
}
.masthead__tagline {
margin: 0.5rem 0 0;
color: var(--ink-dim);
font-size: 0.98rem;
}
.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;
}
.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;
}
.shelf__peek {
position: absolute;
top: 0;
right: 0;
bottom: 3.2rem;
left: 0;
display: block;
}
.shelf__peek img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-position: top center;
transition: transform 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.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;
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;
}
.shelf:hover .shelf__name,
.shelf:focus-visible .shelf__name {
background: color-mix(in srgb, var(--accent) 90%, transparent);
color: var(--steel);
}
.shelf:hover .shelf__peek img,
.shelf:focus-visible .shelf__peek img {
transform: scale(1.04);
}
.empty {
max-width: 34ch;
margin: 1rem 1.1rem 0;
color: var(--ink-dim);
font-size: var(--step-1);
}
/* ---------- Section page: the bar and the switcher ---------- */
.bar {
position: sticky;
top: 0;
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);
}
.bar__brand {
display: flex;
align-items: center;
}
.bar__brand img {
display: block;
width: 24px;
height: 24px;
}
.bar__nav {
display: flex;
flex: 1 1 auto;
gap: 0.15rem;
overflow-x: auto;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
}
.bar__nav::-webkit-scrollbar {
display: none;
}
.bar__link {
padding: 0.35rem 0.65rem;
background: color-mix(in srgb, var(--ink) 9%, transparent);
color: var(--ink-dim);
font-size: 0.95rem;
white-space: nowrap;
}
.bar__link:hover {
color: var(--ink);
background: color-mix(in srgb, var(--ink) 15%, transparent);
}
.bar__link.is-current {
background: var(--accent);
color: var(--steel);
font-weight: 700;
}
.pour {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 2px;
background: var(--hairline-soft);
}
.pour__fill {
display: block;
width: 0;
height: 100%;
background: var(--copper);
}
/* ---------- The pages themselves ---------- */
.section-heading {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 1rem;
max-width: var(--page-max);
margin: 1.2rem auto 0.75rem;
padding: 0 0.9rem;
}
.section-heading__label {
font-size: var(--step-2);
font-weight: 700;
letter-spacing: -0.02em;
}
.section-heading__date {
color: var(--ink-dim);
font-size: 0.88rem;
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);
background: var(--rail);
font-size: 0.95rem;
}
.notice a {
color: var(--accent);
text-decoration: underline;
}
.notice--admin {
max-width: none;
border-left-color: var(--accent);
background: color-mix(in srgb, var(--accent) 20%, var(--rail));
}
.pages {
max-width: var(--page-max);
margin: 0 auto;
padding: 0 0.7rem 1.25rem;
}
.page {
margin: 0 0 0.6rem;
background: var(--paper);
box-shadow: 0 1px 0 color-mix(in srgb, #000 35%, transparent);
}
.page__zoom {
display: block;
}
.page img {
display: block;
width: 100%;
height: auto;
}
/* ---------- 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);
}
.fold {
padding: 0.7rem 0;
border-bottom: 1px solid var(--hairline-soft);
}
.fold summary {
color: var(--ink-dim);
font-size: 0.92rem;
cursor: pointer;
}
.fold[open] summary {
color: var(--ink);
}
.index {
display: flex;
flex-wrap: wrap;
gap: 0.4rem;
margin: 0;
padding: 0.85rem 0 0;
list-style: none;
}
.index a {
display: block;
min-width: 2.3rem;
padding: 0.3rem 0.45rem;
background: var(--rail);
font-variant-numeric: tabular-nums;
text-align: center;
}
.index a:hover,
.index a:focus-visible {
background: var(--accent);
color: var(--steel);
}
.older {
margin: 0.5rem 0 0;
padding: 0;
list-style: none;
}
.older a {
display: flex;
justify-content: space-between;
gap: 1rem;
padding: 0.45rem 0.15rem;
}
.older__label {
font-weight: 500;
}
.older__date {
color: var(--ink-dim);
font-size: 0.88rem;
font-variant-numeric: tabular-nums;
}
.fold__back {
margin: 0.7rem 0 0;
}
.fold__back a {
color: var(--accent);
text-decoration: underline;
}
/* ---------- Counter and zoom ---------- */
.counter {
position: fixed;
right: 0.85rem;
bottom: calc(0.85rem + 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);
font: inherit;
font-size: 0.88rem;
font-variant-numeric: tabular-nums;
cursor: pointer;
}
.counter[hidden] {
display: none;
}
.counter__total {
color: color-mix(in srgb, var(--ink-on-paper) 55%, transparent);
}
.zoom {
position: fixed;
inset: 0;
z-index: 50;
overflow: auto;
background: rgba(6, 9, 10, 0.96);
-webkit-overflow-scrolling: touch;
}
.zoom img {
display: block;
width: min(100%, 1600px);
height: auto;
margin: 0 auto;
}
.zoom__close {
position: fixed;
top: 0.6rem;
right: 0.6rem;
z-index: 1;
padding: 0.5rem 0.75rem;
border: 1px solid var(--brass-edge);
background: var(--paper);
color: var(--ink-on-paper);
font: inherit;
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;
}
.shelf {
height: 16rem;
}
.pages {
max-width: 820px;
}
}
@media print {
.bar,
.sheet,
.counter,
.fold,
.notice {
display: none;
}
body {
background: #fff;
color: #000;
}
.page {
break-inside: avoid;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation: none !important;
transition: none !important;
scroll-behavior: auto !important;
}
}