/* * Fieldwork Supply storefront. * * Organisation: cascade layers, lowest priority first (reset < tokens < base < layout < * components < motion < utilities), so rules never fight over specificity. * * Design language * - Pills (999px) for navigation and toggles: bag, close, filter chips. * - Square corners for actions and inputs: primary buttons, add, quantity, select. * - Mono caps for labels and prices; tight, bold sans for display headings. * - Every colour, size and space comes from a token below; no one-off values in components. * * Contrast (WCAG): --ink 13.8:1, --muted 6.7:1 on paper (5.8:1 on --sage), --lime on --forest * 10.5:1, --focus 5.7:1 on paper, --control 3.4:1 on paper (UI components need 3:1). */ @layer reset, tokens, base, layout, components, motion, utilities; /* ------------------------------------------------------------------ reset */ @layer reset { *, *::before, *::after { box-sizing: border-box; } body, h1, h2, h3, p { margin: 0; } img { display: block; max-width: 100%; height: auto; } button, select { font: inherit; color: inherit; } button { cursor: pointer; } button, a, select { touch-action: manipulation; } a { color: inherit; text-decoration: none; } } /* ------------------------------------------------------------------ tokens */ @layer tokens { :root { color-scheme: light; /* colour */ --paper: #f7f5ed; --sage: #e4e7d9; /* story section */ --ink: #1d2924; --muted: #50594e; --forest: #20392d; --forest-deep: #192c24; /* image caption chip */ --lime: #e2f596; --lime-strong: #d3ea78; /* lime hover */ --leaf: #53794b; /* wordmark full stop */ --line: #d8dbce; /* decorative dividers only */ --control: #808876; /* borders of interactive controls */ --on-dark: #fbfaf0; --on-dark-soft: #e1e6d9; --focus: #3d6b35; --scrim: rgb(16 27 22 / .67); /* type */ --font-sans: system-ui, sans-serif; --font-mono: ui-monospace, "SF Mono", Menlo, monospace; --text-label: .72rem; --text-small: .875rem; --text-base: 1rem; --text-title: clamp(1.05rem, .6rem + 1.6vw, 1.3rem); --text-h2: clamp(2.5rem, 5vw, 4.75rem); --text-h1: clamp(4rem, 8.4vw, 8.5rem); --track-display: -.05em; --track-label: .12em; /* space */ --space-1: .25rem; --space-2: .5rem; --space-3: .75rem; --space-4: 1rem; --space-5: 1.5rem; --space-6: 2rem; --space-7: 3rem; --space-8: 4.5rem; --page: min(1320px, 100% - 8vw); --target: 2.5rem; /* minimum control size; 44px on touch screens, see below */ /* shape, depth, motion */ --radius-pill: 999px; --shadow-float: 0 10px 30px rgb(16 27 22 / .22); --ease: cubic-bezier(.2, .7, .2, 1); --duration: .2s; } @media (pointer: coarse) { :root { --target: 2.75rem; } } } /* ------------------------------------------------------------------ base */ @layer base { html { scroll-behavior: smooth; scrollbar-gutter: stable; -webkit-text-size-adjust: 100%; } html:has(dialog[open]) { overflow: hidden; } /* no background scroll behind a modal */ body { background: var(--paper); color: var(--ink); font-family: var(--font-sans); line-height: 1.5; } h1, h2, h3 { text-wrap: balance; } :focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; } .hero :focus-visible { outline-color: var(--lime); } /* the green ring is only 2.6:1 on forest */ .eyebrow { font-family: var(--font-mono); font-size: var(--text-label); font-weight: 700; letter-spacing: var(--track-label); line-height: 1.4; } .price { font-family: var(--font-mono); font-size: var(--text-small); font-weight: 700; font-variant-numeric: tabular-nums; margin-top: var(--space-1); } .wordmark { font-size: 2rem; font-weight: 850; letter-spacing: -.06em; line-height: 1; } .wordmark span { color: var(--leaf); } } /* ------------------------------------------------------------------ layout */ @layer layout { .notice { padding: .62rem var(--space-4); background: var(--lime); text-align: center; font-family: var(--font-mono); font-size: clamp(.6rem, 2.7vw, var(--text-label)); /* scales down so it stays on one line */ font-weight: 700; letter-spacing: var(--track-label); } .top, main, footer { width: var(--page); margin-inline: auto; } .top { height: 78px; display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); } .top nav { display: flex; gap: var(--space-6); font-size: var(--text-small); } .top nav a:hover, footer a:hover { text-decoration: underline; text-underline-offset: 4px; } /* Standalone links get a full-size hit area (inline links inside paragraphs are exempt). */ .top nav a, .story > a, footer > a:last-child { display: inline-flex; align-items: center; min-height: var(--target); } /* hero */ .hero { display: grid; grid-template-columns: 43% 57%; min-height: 520px; background: var(--forest); color: var(--on-dark); } .hero-copy { padding: clamp(2rem, 5.4vw, 6rem); display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 1.3rem; } .hero .eyebrow { color: var(--lime); } .eyebrow i { display: inline-block; width: .55rem; height: .55rem; margin-right: var(--space-2); border-radius: 50%; background: currentColor; } .hero h1 { font-size: var(--text-h1); line-height: .84; letter-spacing: var(--track-display); word-spacing: .06em; } .hero h1 span { color: var(--lime); } .hero-copy > p:not(.eyebrow) { max-width: 29ch; color: var(--on-dark-soft); } .hero-art { position: relative; min-height: 100%; overflow: hidden; } .hero-art img { position: absolute; width: 100%; height: 100%; object-fit: cover; } .image-label { position: absolute; right: var(--space-4); bottom: var(--space-4); padding: .55rem var(--space-3); background: var(--forest-deep); color: #fff; font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: .07em; } /* shop */ .shop { padding: var(--space-8) 0; } .shop-heading { display: flex; align-items: end; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-5); } .shop h2, .story h2 { margin-top: var(--space-2); font-size: var(--text-h2); line-height: .98; letter-spacing: var(--track-display); word-spacing: .06em; } .shop-heading > p { color: var(--muted); } .controls { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-3) 0; margin-bottom: var(--space-5); border-block: 1px solid var(--line); } #filters { display: flex; flex-wrap: wrap; gap: var(--space-2); } .controls label { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-small); } .grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-6) var(--space-4); } /* story */ .story { padding: clamp(2rem, 6vw, 6rem); background: var(--sage); } .story h2 { max-width: 15ch; } .story > p:not(.eyebrow) { max-width: 53ch; margin: var(--space-5) 0 var(--space-4); line-height: 1.65; } .story a { text-decoration: underline; text-underline-offset: 4px; } /* footer */ footer { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--space-4); padding: 2.5rem 0; font-size: var(--text-small); } footer p { text-align: center; } footer > a:last-child { justify-self: end; text-decoration: underline; text-underline-offset: 4px; } @media (max-width: 760px) { .top { height: 65px; } .top nav { gap: var(--space-3); } .hero { grid-template-columns: 1fr; min-height: 0; } .hero-art { min-height: 310px; } .hero h1 { font-size: clamp(4.2rem, 14vw, 6.5rem); } .shop { padding: var(--space-7) 0; } .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } footer { grid-template-columns: 1fr; justify-items: start; gap: var(--space-3); } footer p { text-align: left; } footer > a:last-child { justify-self: start; } } @media (max-width: 420px) { .top nav a:last-child { display: none; } .shop-heading > p { display: none; } } @media (max-width: 380px) { .notice { padding-inline: var(--space-2); letter-spacing: .04em; } } @media (max-width: 340px) { .grid { grid-template-columns: 1fr; } } } /* ------------------------------------------------------------------ components */ @layer components { /* pills: navigation and toggles */ .bag, .close, #filters button { min-height: var(--target); padding: 0 var(--space-4); border: 1px solid var(--control); border-radius: var(--radius-pill); background: transparent; } .bag { display: inline-flex; align-items: center; gap: var(--space-2); } .bag span { display: inline-grid; place-items: center; width: 1.4rem; height: 1.4rem; border-radius: 50%; background: var(--forest); color: #fff; font-size: .75rem; font-variant-numeric: tabular-nums; } .close { min-width: var(--target); padding: 0; font-size: 1.35rem; line-height: 1; } #filters button { font-size: var(--text-small); } #filters button[aria-pressed="true"] { background: var(--forest); border-color: var(--forest); color: #fff; } /* square: actions and inputs */ .primary { display: inline-flex; align-items: center; justify-content: space-between; gap: var(--space-4); min-height: var(--target); padding: .9rem 1.15rem; border: 0; background: var(--lime); color: var(--ink); font-weight: 750; } .add, .qty button { display: grid; place-items: center; min-width: var(--target); min-height: var(--target); padding: 0; border: 1px solid var(--control); background: transparent; font-size: 1.3rem; line-height: 1; } .qty button:disabled { opacity: .4; cursor: not-allowed; } .controls select { min-height: var(--target); padding: 0 var(--space-3); border: 1px solid var(--control); border-radius: 0; background: transparent; } @media (hover: hover) { .primary:hover { background: var(--lime-strong); } .add:hover, .qty button:not(:disabled):hover { background: var(--lime); } #filters button[aria-pressed="false"]:hover, .bag:hover, .close:hover { background: var(--sage); } } /* product card */ .product { min-width: 0; } .product-image { display: block; width: 100%; padding: 0; border: 0; background: transparent; } .product-image img { transition: filter var(--duration); } @media (hover: hover) { .product-image:hover img { filter: brightness(.94); } } .product-info { display: grid; grid-template-columns: 1fr auto; align-items: start; gap: var(--space-2); padding: var(--space-3) 0; } .product h3 { font-size: var(--text-title); letter-spacing: -.03em; line-height: 1.2; } .product .eyebrow { margin-bottom: var(--space-1); color: var(--muted); } /* dialogs */ dialog { width: 100%; max-width: min(520px, calc(100% - 2rem)); max-height: 90dvh; padding: 1.3rem; overflow: auto; border: 1px solid var(--line); background: var(--paper); color: var(--ink); } dialog::backdrop { background: var(--scrim); } .dialog-head, .subtotal { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-4); } #product-detail h2 { margin-top: var(--space-4); font-size: 1.6rem; letter-spacing: -.03em; line-height: 1.15; } #product-detail > p { margin: var(--space-3) 0 var(--space-4); line-height: 1.5; } /* bag drawer */ #cart { height: 100dvh; max-height: 100dvh; max-width: min(470px, 100%); margin: 0 0 0 auto; border: 0; box-shadow: var(--shadow-float); } .cart-row { display: grid; grid-template-columns: 75px 1fr auto; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; border-bottom: 1px solid var(--line); } .qty { display: grid; grid-template-columns: var(--target) 2ch var(--target); /* fixed columns: rows line up */ align-items: center; gap: var(--space-1); text-align: center; font-variant-numeric: tabular-nums; } .subtotal { margin-top: var(--space-4); } .fine { margin-top: var(--space-3); font-size: var(--text-small); color: var(--muted); } .empty { margin-bottom: var(--space-4); color: var(--muted); } #order { padding: var(--space-4); background: var(--sage); line-height: 1.5; } #order:focus-visible { outline-offset: 2px; } #toast { position: fixed; right: var(--space-4); bottom: var(--space-4); z-index: 3; max-width: calc(100% - 2rem); padding: var(--space-3) var(--space-4); background: var(--forest); color: var(--on-dark); box-shadow: var(--shadow-float); } #toast:empty { display: none; } .notice-js { padding: var(--space-4); background: var(--sage); } @media (max-width: 760px) { #toast { left: var(--space-4); } } } /* ------------------------------------------------------------------ motion */ @layer motion { @media (prefers-reduced-motion: no-preference) { dialog[open] { animation: rise var(--duration) var(--ease); } #cart[open] { animation: slide-in .28s var(--ease); } dialog[open]::backdrop { animation: fade var(--duration) ease-out; } #toast:not(:empty) { animation: rise .24s var(--ease); } } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } * { transition: none !important; } } @keyframes rise { from { opacity: 0; translate: 0 .5rem; } } @keyframes slide-in { from { translate: 100% 0; opacity: 1; } } @keyframes fade { from { opacity: 0; } } } /* ------------------------------------------------------------------ utilities */ @layer utilities { .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } .skip-link { position: absolute; left: var(--space-4); top: var(--space-2); z-index: 10; padding: var(--space-2) var(--space-4); background: var(--forest); color: var(--on-dark); translate: 0 -200%; } .skip-link:focus { translate: 0 0; } [hidden] { display: none !important; } }