diff --git a/.eleventyignore b/.eleventyignore new file mode 100644 index 0000000..c9c43eb --- /dev/null +++ b/.eleventyignore @@ -0,0 +1,4 @@ +PRODUCT.md +DESIGN.md +readme.md +.impeccable/ diff --git a/.impeccable/review/desktop-1280.png b/.impeccable/review/desktop-1280.png new file mode 100644 index 0000000..8fd1748 Binary files /dev/null and b/.impeccable/review/desktop-1280.png differ diff --git a/.impeccable/review/desktop.png b/.impeccable/review/desktop.png new file mode 100644 index 0000000..42495ff Binary files /dev/null and b/.impeccable/review/desktop.png differ diff --git a/.impeccable/review/mobile.png b/.impeccable/review/mobile.png new file mode 100644 index 0000000..b8cc05d Binary files /dev/null and b/.impeccable/review/mobile.png differ diff --git a/.impeccable/review/post-desktop.png b/.impeccable/review/post-desktop.png new file mode 100644 index 0000000..9126586 Binary files /dev/null and b/.impeccable/review/post-desktop.png differ diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..e5fc91f --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,101 @@ +# Design + + + +A crust-punk xerox zine, held inside a tight grid. The subject is bicycles and +crust punk; the ethics are DIY and minimal consumption. The look borrows the +strict monochrome and photocopied-zine / noisy-film feel of japanese crust, but +keeps a dosnoventa-tight, ordered structure. Built code-first on Eleventy (11ty) +v3 + Nunjucks + plain CSS. + +## The two poles + +- **Chaos (crust):** photocopier grain over the sheet, halftone 1-bit photos, + heavy condensed caps, the `////` slash motif, hairline rules, `№` stamps. +- **Order (dosnoventa):** a clean 1160px shell, strict baseline rhythm, one + monochrome palette, everything on a ruled grid. + +Neither wins: the grain and the caps supply the attitude, the grid keeps it +legible. + +## Palette + +Strictly monochrome — paper and one ink. + +| token | value | role | +|---------|-----------|-----------------------------------| +| `--paper` | `#f4f1ea` | newsprint / warm photocopy ground | +| `--ink` | `#111110` | photocopier black (text, rules) | +| `--dim` | `#59544a` | faded toner grey (secondary) | +| `--faint` | `#b7b0a3` | whisper rules | + +Contrast: ink/paper 17.4:1, dim/paper 7.1:1, paper-on-ink 17.4:1 — all far above +4.5:1. + +## Type + +Self-hosted woff2 with cyrillic + latin subsets; no external font requests. + +- **Jost 300–700** — the brand display face: a **Futura** homage (geometric, + Paul Renner). Masthead, titles, labels, buttons, nav. The author's identity + sheet is set in Futura PT Light, so Jost is the web stand-in (Futura itself is + licensed and lacks a free webfont). +- **Literata 400/600/700 + italic** — the serif reading column (the text face + the author asked for). +- **JetBrains Mono 400/700** — dates, entry numbers, spec keys, captions. + +Measure 64ch; body ~17px; display titles up to 4.6rem fluid. + +## Mark + +The logo mark is the author's own `../identity/logo-mark.png`, traced to clean +inline SVG (potrace) and inlined in the masthead so no extra static file ships: +two large intersecting circles forming a lens, an ellipse iris, and a filled +**diamond** pupil. `fill="currentColor"`, so it inherits the ink colour. + +## Signature moves + +- **The `////` slash** (from the logo's four mitre strokes) recurs: the button + tail, list bullets, the caption and back-link prefixes. +- **Photocopier grain** — a fixed, non-interactive multiply layer over the whole + sheet (`static/images/grain.png`, ~14% opacity). +- **Halftone photographs** — the two real photos are dithered to 1-bit B&W + (`hero-xerox.png`, `lugs-xerox.png`) and multiply-blended onto the paper. + +## Structure + +- **Masthead** — eye mark + `cyclocrust` wordmark, uppercase nav, mono folio. +- **Cover** — newest entry leads: condensed caps title, ruled fact line + (запись · дата · материал), serif lede, ink-block CTA, halftone plate + mono + caption. +- **Log** — entry index as a ruled contents list: `№ · дата · заголовок · + материал`; hover shifts the row and underlines the title. +- **Entry** — left data rail (sticky spec table + date), serif reading column + with a condensed drop cap, ruled `h2`s, framed halftone figures. +- **Colophon** — wordmark, note, contacts, mono tag. + +## Motion + +One authored moment: rows and nav carry a single ease-out transition; the ink +button inverts on hover. No scroll effects. `prefers-reduced-motion` keeps +smooth scroll off. + +## Browser surfaces + +Selection (ink ground), caret, scrollbar (dim on paper), focus ring (2.5px ink), +underline offset, and `accent-color` are themed to the two-colour palette. + +## Content contracts + +- Titles and copy stay as written by the author; `topic`, `material`, `status` + come from frontmatter with honest defaults; no invented facts. +- Contacts ship as the author's real ones: e-mail `order@cyclocrust.net` and + Instagram `cyclocrust` (no Telegram). +- No fabricated prices, counts, testimonials, or commercial claims. +- Rasters carry provenance: the two photographs are the author's own, dithered; + the grain is generated. + +## Constraints + +Eleventy (11ty) v3 kept as-is; `dist/` is the output. `.eleventyignore` excludes +`PRODUCT.md`, `DESIGN.md`, `readme.md`, `.impeccable/`. diff --git a/PRODUCT.md b/PRODUCT.md new file mode 100644 index 0000000..772560c --- /dev/null +++ b/PRODUCT.md @@ -0,0 +1,80 @@ +# Product + + + +## Platform + +web + +## Stack + +Eleventy (11ty) v3 static site, Nunjucks templates, plain CSS. Stays on 11ty — pinned by the user. +Build path: code-led (no image generation available; only magick/ffmpeg converters reported by `impeccable context`). Comp-led is unavailable. + +## Users + +CONFIRMED (user, 2026-10-03): +1. PRIMARY — the author himself. This is an art diary: a personal record of framebuilding as an art practice. +2. SECONDARY — potential frame customers, who read the blog as a portfolio and should finish wanting to commission a frame. +Reader situation: Russian-speaking, reads on phone/desktop, evening; an enthusiast of steel frames and fixed-gear culture. + +## Product Purpose + +CONFIRMED: an art diary first (the author's self-expression through the aesthetics of classic steel frames); a portfolio second (proof of craft that turns a reader into a prospective customer). +Success (CONFIRMED): the reader understands the craft and the author's point of view, keeps reading — and, for the customer audience, wants to order a frame. + +## Positioning + +CONFIRMED (user, 2026-10-03): Cyclocrust is bicycles and crust punk. The ethic is +DIY and hardcore punk; the author is vegan and consumes minimally. Positioning = +"framebuilding as an art project", self-expression through the aesthetics of +classic steel frames — a maker's voice, not a shop. Visual code, also confirmed: +take strict monochrome and the feel of a photocopied zine / noisy film from +japanese crust punk, held inside a dosnoventa-tight, ordered structure. + +## Operating Context + +Author writes long-form Russian posts with workshop and ride photographs. Posts are the primary unit; the index is the diary's front page and doubles as the portfolio entry. A "контакты" link exists in the header but points to a non-existent `links` page. + +## Capabilities and Constraints + +- Static 11ty site, output to `dist/`; passthrough copy of `static/**` and `posts/**/*.jpg`. +- Post collection tagged `posts` via `_includes/post.njk`; `index.njk` lists posts. +- Russian-language content (lang="ru"). +- Durable assets: logo (C mark, inline SVG); `static/images/hero.jpg` (night film photo: fixed-gear rider between a Photoautomat booth and a red vending machine); `posts/intro/conno_lugs_commercial.jpg` (flat-lay of Cr-Mo "SUPER-STRONG" tubing, lugs, BB shells, dropouts, Japanese catalogue labelling). +- UNDECIDED: whether a contacts/commission page gets built; exact site title ("Cyclocrust 51" vs "cyclocrust"). + +## Brand Commitments + +- Name: Cyclocrust / "cyclocrust". +- Logo mark: the **eye** — two arcs, an iris ring, a filled diamond pupil + (author's identity sheet `../identity/logo.svg`; the "51" rhombus and the frame + wordmark are not used). Reusable motif: the four `////` mitre strokes. +- Language: Russian. +- Visual code (CONFIRMED): strict monochrome; photocopied-zine / noisy-film + texture; japanese-crust attitude inside a dosnoventa-tight grid; a serif face + for body text. Brand display face is **Futura** (the author's identity sheet is + Futura PT); the web build uses Jost, a Futura homage, since Futura has no free + webfont. +- Preserve: existing post text, the two photographs, the 11ty stack. + +## Evidence on Hand + +- `static/images/hero.jpg` — night flash film photograph, heavy grain, deep blacks, single hard light (real, author's own). The dominant visual evidence of the "art diary" world. A 1-bit halftone version (`hero-xerox.png`) ships on the site. +- `posts/intro/conno_lugs_commercial.jpg` — flat-lay component scan with Japanese catalogue labelling (real); halftone version `posts/intro/lugs-xerox.png`. Evidence of the technical/specification world. +- `posts/intro.md` — intro post. +- Contacts (CONFIRMED): e-mail `order@cyclocrust.net`, Instagram `cyclocrust`. +- Identity assets (`../identity/`): `logo-mark.png` (the eye — inlined as SVG in the masthead), `51.png`/`51.svg` (the "51" diamond — inlined in the colophon). +- ABSENT (must not be fabricated): customer testimonials, frame prices, build counts, press, awards, delivery claims. + +## Product Principles + +1. The craft is the subject: real work, real material, real process — never generic "industrial" decoration. +2. Voice over inventory: an art practice, not a shop. +3. Night-workshop, photographic atmosphere — read the light from the material already on hand. +4. Reading comfort is part of the design: a calm column inside a committed frame. +5. The portfolio duty is real: a visitor must find the path to commissioning within seconds. + +## Accessibility & Inclusion + +Keep body text contrast ≥ 4.5:1, keyboard-operable navigation, and a readable measure (~65–75ch). No product-specific standard was established beyond this. diff --git a/_includes/main.njk b/_includes/main.njk index 79aeb33..e2ed4dc 100644 --- a/_includes/main.njk +++ b/_includes/main.njk @@ -1,30 +1,90 @@ --- -title: Cyclocrust 51 +title: Cyclocrust --- - - - - - {{ title }} - - -
-

cyclocrust 51

- - -
-
- {{ content | safe }} -
- + + + + {% if page.url != "/" %}{{ title }} · Cyclocrust{% else %}Cyclocrust — журнал фреймбилдинга{% endif %} + + + + + + + + +
+
+ + + + cyclocrust + фреймбилдинг · журнал + + + + + +

+ записей {{ collections.posts | length }}
+ журнал с 2025 +

+
+
+ +
+ {{ content | safe }} +
+ + + diff --git a/_includes/post.njk b/_includes/post.njk index e44deb7..7be21c1 100644 --- a/_includes/post.njk +++ b/_includes/post.njk @@ -1,8 +1,39 @@ --- layout: main --- +
+
+ -
-

{{ title }}

- {{ content | safe }} -
+
+

{{ title }}

+ +
+ {{ content | safe }} +
+ + +
+
+
diff --git a/eleventy.config.js b/eleventy.config.js index a545036..79b9f9a 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -1,5 +1,27 @@ export default async function (eleventyConfig) { - eleventyConfig.setOutputDirectory("dist"); - eleventyConfig.addPassthroughCopy("static/**/*"); - eleventyConfig.addPassthroughCopy("posts/**/*.jpg"); + eleventyConfig.setOutputDirectory("dist"); + eleventyConfig.addPassthroughCopy("static/**/*"); + eleventyConfig.addPassthroughCopy("posts/**/*.{jpg,jpeg,png,webp,mp4}"); + + // Log-book date: "26 · 04 · 2026" — reads like a stamped entry, not a feed. + eleventyConfig.addFilter("logdate", (date) => { + const d = new Date(date); + if (Number.isNaN(d.getTime())) return ""; + const p = (n) => String(n).padStart(2, "0"); + return `${p(d.getUTCDate())} · ${p(d.getUTCMonth() + 1)} · ${d.getUTCFullYear()}`; + }); + + // Entry numbers, zero-padded like a log folio. + eleventyConfig.addFilter("pad3", (n) => String(n).padStart(3, "0")); + + return { + dir: { + input: ".", + includes: "_includes", + output: "dist", + }, + templateFormats: ["njk", "md"], + markdownTemplateEngine: "njk", + htmlTemplateEngine: "njk", + }; } diff --git a/index.njk b/index.njk index fc9d72a..7d3a31d 100644 --- a/index.njk +++ b/index.njk @@ -2,11 +2,50 @@ layout: main --- -
-{%- for post in collections.posts -%} -
- {{ post.data.title }} - {{ post.title }} +{% set latest = collections.posts | reverse | first %} +{% if latest %} +
+
+
+
+

{{ latest.data.title }}

+
+ запись №{{ (collections.posts | length) | pad3 }} + дата {{ latest.date | logdate }} + материал {{ latest.data.material or "хромомолибден" }} +
+

+ Журнал сборки стальных рам — процесс, материал и медленный труд, + описанные с точки зрения мастера. +

+

+ Читать запись +

+
+
+ Ночная фотография: человек с фиксом у автоматов Photoautomat и Rocky Boxer +
ночь · фикс · двое автоматов · плёнка
+
+
+
+
+{% endif %} + +
+
+ записи + + {{ collections.posts | length }} шт. +
+ + -{%- endfor -%}
diff --git a/posts/intro.md b/posts/intro.md index 1448f53..c332df6 100644 --- a/posts/intro.md +++ b/posts/intro.md @@ -1,5 +1,9 @@ --- title: Что такое Cyclocrust? +date: 2026-04-26 +topic: фреймбилдинг +material: хромомолибден +status: в работе --- Это фреймбилдинг как арт проект. Способ моего самовыражения @@ -7,4 +11,7 @@ title: Что такое Cyclocrust? Медитатция в процессе производства -![узлы](./conno_lugs_commercial.jpg) +
+ Узлы и трубы: оригинальные компоненты рамы Cr-Mo «SUPER-STRONG» +
узлы и трубы · оригинальные компоненты рамы Cr-Mo «SUPER-STRONG»
+
diff --git a/posts/intro/lugs-xerox.png b/posts/intro/lugs-xerox.png new file mode 100644 index 0000000..9456852 Binary files /dev/null and b/posts/intro/lugs-xerox.png differ diff --git a/static/css/base.css b/static/css/base.css index 440fe6c..012a15b 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -1,46 +1,371 @@ -body { - max-width: 1200px; - background: black; - color: white; - margin-inline: auto; - padding-inline: clamp(1rem, 5vw, 120px); +/* ========================================================================== + Cyclocrust — crust punk xerox zine + Bicycles and crust punk, DIY, minimal consumption. A black-and-white + photocopied zine: paper ground, one black ink, halftone photographs, + hairline rules, //// slashes, faint photocopier grain. + Two poles held at once: japanese-crust monochrome chaos (grain, condensed + caps, slash marks) inside a dosnoventa-tight, ordered grid. + ========================================================================== */ + +:root { + --paper: #f4f1ea; /* newsprint / warm photocopy paper */ + --ink: #111110; /* photocopier black */ + --dim: #59544a; /* faded toner grey */ + --faint: #b7b0a3; /* whisper rules */ + --rule: color-mix(in srgb, var(--ink) 16%, transparent); + --rule-strong: color-mix(in srgb, var(--ink) 40%, transparent); + + /* scrollbar roles (kept separate so they can be overridden for contrast) */ + --scrollbar-thumb: var(--dim); + --scrollbar-track: var(--paper); + + --cond: "Jost", "Futura", "Century Gothic", system-ui, sans-serif; + --serif: "Literata", Georgia, "Times New Roman", serif; + --mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", monospace; + + --measure: 64ch; + --gutter: clamp(1.1rem, 5vw, 4rem); + --shell: 1160px; + --ease: cubic-bezier(0.16, 1, 0.3, 1); + --grain-opacity: 0.12; /* photocopier grain strength over the sheet */ + + /* One scheme on purpose: the site is a light "paper" zine. Declaring it on + :root lets the browser theme native UI (controls, canvas, scrollbars) to + match and avoids a white flash. */ + color-scheme: light; +} + +@media (prefers-reduced-motion: no-preference) { + html { scroll-behavior: smooth; } +} + +/* Photocopier grain over the whole sheet (fixed, non-interactive) -------- */ +body::before { + content: ""; + position: fixed; + inset: 0; + z-index: 9999; + pointer-events: none; + opacity: var(--grain-opacity); + mix-blend-mode: multiply; + background-image: url("/static/images/grain.png"); + background-size: 160px 160px; +} +/* Torn/uneven toner edges along the sheet */ +body::after { + content: ""; + position: fixed; + inset: 0; + z-index: 9998; + pointer-events: none; + box-shadow: inset 0 0 90px color-mix(in srgb, var(--ink) 10%, transparent); } -.head { - align-items: center; +body { + background: var(--paper); + color: var(--ink); + font-family: var(--serif); + font-size: clamp(1rem, 0.95rem + 0.25vw, 1.09rem); + line-height: 1.66; + /* Normalize fallback x-height so Georgia/Times don't shift layout while + Literata loads (or if it fails). */ + font-size-adjust: from-font; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-kerning: normal; + min-height: 100vh; display: flex; - flex-wrap: wrap; - gap: 20px; - justify-content: center; - padding-top: 2rem; + flex-direction: column; } -.head > * { - flex: 1 1 200px; - flex-basis: calc((600px - 100%) * 999); - text-align: center; +/* Browser surfaces carry the design ------------------------------------- */ +::selection { background: var(--ink); color: var(--paper); } +:focus-visible { outline: 2.5px solid var(--ink); outline-offset: 3px; } +html { accent-color: var(--ink); caret-color: var(--ink); scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); scrollbar-gutter: stable; } +/* Legacy WebKit fallback, guarded so it never conflicts with scrollbar-color */ +@supports not (scrollbar-color: auto) { + ::-webkit-scrollbar { width: 12px; height: 12px; } + ::-webkit-scrollbar-track { background: var(--scrollbar-track); } + ::-webkit-scrollbar-thumb { background: var(--scrollbar-thumb); border: 3px solid var(--scrollbar-track); } +} +/* High-contrast preference: stark black thumb on white */ +@media (prefers-contrast: more) { + :root { --scrollbar-thumb: #000; --scrollbar-track: #fff; } } -.head > h1 { - white-space: nowrap; +a { color: inherit; text-decoration-thickness: 1.5px; text-underline-offset: 0.2em; } + +.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gutter); } + +.skip { + position: absolute; left: -9999px; top: 0; z-index: 100; + background: var(--ink); color: var(--paper); + padding: 0.6rem 1rem; font-family: var(--mono); font-size: 0.8rem; +} +.skip:focus { left: 1rem; top: 1rem; } + +/* ========================================================================== + Masthead — a zine cover strip + ========================================================================== */ +.masthead { border-bottom: 2px solid var(--ink); background: var(--paper); } +.masthead__inner { + display: flex; align-items: center; gap: clamp(0.9rem, 4vw, 2.4rem); + padding-block: 0.85rem; min-height: 4.6rem; +} +.plate { flex: none; display: flex; align-items: center; gap: 0.75rem; text-decoration: none; color: var(--ink); } +.plate__mark { width: 40px; height: 39px; flex: none; color: var(--ink); } +.plate__lockup { display: flex; flex-direction: column; line-height: 1; } +.plate__name { + font-family: var(--cond); font-weight: 500; font-size: 1.55rem; + letter-spacing: 0.005em; text-transform: lowercase; +} +.plate__sub { + font-family: var(--mono); font-size: 0.6rem; letter-spacing: 0.22em; + text-transform: uppercase; color: var(--dim); margin-top: 0.34rem; +} + +.nav { margin-left: auto; } +.nav__list { display: flex; align-items: center; gap: clamp(1rem, 3vw, 2.1rem); } +.nav a { + font-family: var(--cond); font-weight: 500; font-size: 0.9rem; + letter-spacing: 0.16em; text-transform: uppercase; text-decoration: none; + color: var(--ink); padding-block: 0.35rem; + border-bottom: 2px solid transparent; + transition: border-color 0.25s var(--ease); } +.nav a:hover, .nav a[aria-current="page"] { border-bottom-color: var(--ink); } -.head > .logo { - max-width: fit-content; +.folio { + flex: none; font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.05em; + color: var(--dim); padding-left: clamp(1rem, 3vw, 2rem); + border-left: 1px solid var(--rule); text-align: right; } +.folio b { color: var(--ink); font-weight: 700; } -.head > .logo > svg { - display: block; - fill: white; - height: auto; - width: 100px; +@media (max-width: 760px) { + .masthead__inner { flex-wrap: wrap; gap: 0.5rem 1rem; } + .nav { order: 3; margin-left: 0; width: 100%; border-top: 1px solid var(--rule); padding-top: 0.6rem; } + .folio { display: none; } } -.head > .links { - list-style: none; +/* ========================================================================== + Cover — the zine's lead page + ========================================================================== */ +.cover { border-bottom: 2px solid var(--ink); } +.cover__grid { display: grid; grid-template-columns: 1.15fr 1fr; align-items: stretch; } +.cover__text { + padding: clamp(2rem, 5vw, 4rem) clamp(1.2rem, 4vw, 3rem) clamp(2rem, 5vw, 3.6rem); + display: flex; flex-direction: column; justify-content: center; gap: 1.2rem; +} +.cover__title { + font-family: var(--cond); font-weight: 500; + font-size: clamp(2.4rem, 6.6vw, 4.6rem); line-height: 0.94; + letter-spacing: -0.01em; text-transform: uppercase; + text-wrap: balance; max-width: 15ch; + /* Cap-height normalization suits an all-caps display line. */ + font-size-adjust: cap-height from-font; +} +.cover__facts { + display: flex; flex-wrap: wrap; gap: 0.4rem 1.3rem; + font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.04em; + color: var(--dim); border-top: 1px solid var(--rule-strong); padding-top: 0.85rem; +} +.cover__facts b { color: var(--ink); font-weight: 700; } +.cover__lede { + font-size: clamp(1.05rem, 1rem + 0.4vw, 1.25rem); color: color-mix(in srgb, var(--ink) 82%, var(--paper)); + max-width: 36ch; text-wrap: pretty; +} +.cover__figure { position: relative; border-left: 2px solid var(--ink); overflow: hidden; } +.cover__figure img { + width: 100%; height: 100%; object-fit: cover; + filter: contrast(1.06) saturate(0); + mix-blend-mode: multiply; +} +.cover__figure figcaption { + position: absolute; left: 0; bottom: 0; right: 0; + padding: 0.7rem 0.9rem; background: var(--paper); + border-top: 1px solid var(--ink); + font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.04em; +} +@media (max-width: 860px) { + .cover__grid { grid-template-columns: 1fr; } + .cover__figure { order: -1; border-left: 0; border-bottom: 2px solid var(--ink); aspect-ratio: 4/3; } } -.head > .links a { - color: white; - font-size: 1.5em; +/* ========================================================================== + Section band + ========================================================================== */ +.band { + display: flex; align-items: center; gap: 1rem; + padding-top: clamp(2.4rem, 6vw, 4rem); padding-bottom: 0.7rem; +} +.band__label { + font-family: var(--cond); font-weight: 600; font-size: 1.05rem; + letter-spacing: 0.2em; text-transform: uppercase; flex: none; +} +.band__rule { flex: 1; height: 2px; background: var(--ink); } +.band__count { flex: none; font-family: var(--mono); font-size: 0.72rem; color: var(--dim); } + +/* ========================================================================== + Log — entry index as a ruled zine contents list + ========================================================================== */ +.log { border-top: 2px solid var(--ink); margin-bottom: clamp(3rem, 8vw, 5.5rem); } +.log__row { + display: grid; grid-template-columns: 4rem 8.4rem minmax(0, 1fr) auto; + align-items: baseline; gap: 1.1rem; padding-block: 1rem; + border-bottom: 1px solid var(--rule); text-decoration: none; color: var(--ink); + transition: background 0.25s var(--ease), transform 0.25s var(--ease); +} +.log__row:hover { background: color-mix(in srgb, var(--ink) 6%, var(--paper)); transform: translateX(0.5rem); } +.log__no { font-family: var(--mono); font-size: 0.82rem; color: var(--dim); } +.log__date { font-family: var(--mono); font-size: 0.76rem; color: var(--dim); } +.log__title { + font-family: var(--cond); font-weight: 500; + font-size: clamp(1.15rem, 0.95rem + 1vw, 1.75rem); line-height: 1.06; + text-transform: uppercase; +} +.log__meta { font-family: var(--mono); font-size: 0.7rem; color: var(--dim); text-align: right; white-space: nowrap; } +.log__row:hover .log__title { text-decoration: underline; text-decoration-thickness: 3px; text-underline-offset: 0.12em; } +@media (max-width: 760px) { + .log__row { grid-template-columns: 3rem minmax(0, 1fr); gap: 0.35rem 0.8rem; padding-block: 0.9rem; } + .log__no { grid-row: 1 / span 2; } + .log__date { grid-column: 2; } + .log__title { grid-column: 2; } + .log__meta { grid-column: 2; text-align: left; } +} + +/* ========================================================================== + Entry — reading page + ========================================================================== */ +.entry { padding-block: clamp(2.2rem, 6vw, 4.2rem); flex: 1; } +.entry__layout { + display: grid; grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr); + gap: clamp(1.6rem, 5vw, 4.2rem); align-items: start; +} +.entry__rail { position: sticky; top: 1.6rem; align-self: start; } +.entry__spec { border-top: 2px solid var(--ink); } +.entry__spec > div { padding-block: 0.55rem; border-bottom: 1px solid var(--rule); } +.entry__spec dt { + font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.14em; + text-transform: uppercase; color: var(--dim); margin-bottom: 0.22rem; +} +.entry__spec dd { + font-family: var(--cond); font-weight: 600; font-size: 1.02rem; + line-height: 1.1; text-transform: uppercase; +} +.entry__index { + margin-top: 0.9rem; font-family: var(--mono); font-size: 0.68rem; + letter-spacing: 0.06em; text-transform: uppercase; color: var(--dim); + display: flex; flex-direction: column; gap: 0.2rem; +} +.entry__index b { color: var(--ink); font-weight: 700; } +.entry__body { max-width: var(--measure); } +@media (max-width: 820px) { + .entry__layout { grid-template-columns: 1fr; gap: 1.6rem; } + .entry__rail { position: static; } + /* single ruled spec list — no empty grid cell, no clipped long values */ + .entry__spec { display: block; border-top: 2px solid var(--ink); } + .entry__spec > div { + display: grid; grid-template-columns: 6.5rem minmax(0, 1fr); + gap: 0.3rem 0.8rem; padding-block: 0.55rem; + border-bottom: 1px solid var(--rule); + } + .entry__spec dt { padding-top: 0.22rem; margin: 0; } + .entry__spec dd { overflow-wrap: anywhere; } + .entry__index { display: none; } +} +.entry__title { + font-family: var(--cond); font-weight: 500; + font-size: clamp(1.9rem, 5vw, 3.4rem); line-height: 0.98; letter-spacing: -0.01em; + text-transform: uppercase; text-wrap: balance; margin-bottom: clamp(1.2rem, 3vw, 1.9rem); + padding-bottom: clamp(0.9rem, 2.4vw, 1.4rem); border-bottom: 2px solid var(--ink); +} + +/* prose ------------------------------------------------------------------- */ +.prose { max-width: var(--measure); } +.prose > * + * { margin-top: 1.05em; } +.prose > h2 { + font-family: var(--cond); font-weight: 600; + font-size: clamp(1.6rem, 1.25rem + 1.5vw, 2.3rem); line-height: 1.02; + text-transform: uppercase; margin-top: 2.2em; padding-top: 0.6em; + border-top: 1px solid var(--rule-strong); +} +.prose > h2 + * { margin-top: 0.6em; } +.prose > h3 { font-family: var(--cond); font-weight: 600; font-size: 1.3rem; letter-spacing: 0.03em; text-transform: uppercase; margin-top: 1.8em; } +.prose > p:first-of-type::first-letter { + float: left; font-family: var(--cond); font-weight: 700; font-size: 3.5em; + line-height: 0.7; padding: 0.06em 0.14em 0 0; +} +.prose a { text-decoration-color: var(--ink); } +.prose a:hover { background: var(--ink); color: var(--paper); text-decoration: none; } +.prose strong { font-weight: 700; } +.prose blockquote { + font-style: italic; padding-block: 0.6rem; + border-top: 1px solid var(--rule-strong); border-bottom: 1px solid var(--rule-strong); +} +.prose code { font-family: var(--mono); font-size: 0.86em; background: color-mix(in srgb, var(--ink) 8%, var(--paper)); padding: 0.1em 0.35em; } +.prose pre { font-family: var(--mono); font-size: 0.84rem; line-height: 1.6; background: var(--ink); color: var(--paper); padding: 1rem 1.1rem; overflow-x: auto; } +.prose pre code { background: none; padding: 0; } +.prose ul, .prose ol { padding-left: 1.3rem; } +.prose li { list-style: none; position: relative; } +.prose li + li { margin-top: 0.35em; } +.prose ul > li::before { content: "//"; position: absolute; left: -1.35rem; font-family: var(--mono); font-size: 0.8em; color: var(--dim); } +.prose ol { counter-reset: n; } +.prose ol > li { counter-increment: n; } +.prose ol > li::before { content: counter(n) "."; position: absolute; left: -1.5rem; font-family: var(--mono); font-size: 0.82em; } +.prose hr { border: 0; border-top: 2px solid var(--ink); margin-block: 2.2em; } + +/* figures: framed halftone plates ---------------------------------------- */ +.prose figure { margin-block: 2em; } +.prose figure img { width: 100%; border: 2px solid var(--ink); filter: contrast(1.06) saturate(0); mix-blend-mode: multiply; } +.prose figcaption { + font-family: var(--mono); font-size: 0.7rem; line-height: 1.5; color: var(--dim); + margin-top: 0.5rem; +} +.prose figcaption::before { content: "// "; color: var(--ink); font-weight: 700; } +.prose video { width: 100%; border: 2px solid var(--ink); } + +.entry__foot { + margin-top: clamp(2.6rem, 6vw, 4.4rem); padding-top: 1.2rem; + border-top: 2px solid var(--ink); display: flex; justify-content: space-between; align-items: center; gap: 1rem; +} +.entry__back { + font-family: var(--cond); font-weight: 500; font-size: 0.92rem; + letter-spacing: 0.16em; text-transform: uppercase; text-decoration: none; color: var(--dim); +} +.entry__back:hover { color: var(--ink); } +.entry__back::before { content: "//"; font-family: var(--mono); margin-right: 0.5rem; } + +/* ========================================================================== + Buttons — stamped ink block + ========================================================================== */ +.btn { + display: inline-flex; align-items: center; gap: 0.6rem; + font-family: var(--cond); font-weight: 500; font-size: 0.95rem; + letter-spacing: 0.14em; text-transform: uppercase; text-decoration: none; + color: var(--paper); background: var(--ink); border: 2px solid var(--ink); + padding: 0.72rem 1.3rem; + transition: background 0.25s var(--ease), color 0.25s var(--ease); +} +.btn::after { content: "////"; font-family: var(--mono); font-size: 0.82em; letter-spacing: -0.16em; } +.btn:hover { background: transparent; color: var(--ink); } + +/* ========================================================================== + Colophon — zine back page + ========================================================================== */ +.colophon { border-top: 2px solid var(--ink); margin-top: auto; } +.colophon__inner { + display: grid; grid-template-columns: 1.4fr 1fr auto; gap: clamp(1.2rem, 4vw, 3rem); + padding-block: clamp(1.8rem, 5vw, 3rem); +} +.colophon__wordmark { font-family: var(--cond); font-weight: 500; font-size: 1.35rem; text-transform: lowercase; } +.colophon__note { font-family: var(--mono); font-size: 0.72rem; line-height: 1.7; color: var(--dim); max-width: 42ch; margin-top: 0.6rem; } +.colophon__col h3 { font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--dim); margin-bottom: 0.6rem; } +.colophon__col ul { display: flex; flex-direction: column; gap: 0.4rem; } +.colophon__col a { font-family: var(--cond); font-weight: 500; font-size: 0.95rem; text-transform: lowercase; letter-spacing: 0.04em; text-decoration: none; color: var(--ink); } +.colophon__col a:hover { text-decoration: underline; text-decoration-thickness: 3px; } +.colophon__mark { width: 44px; height: 54px; color: var(--ink); justify-self: end; align-self: end; } +@media (max-width: 720px) { + .colophon__inner { grid-template-columns: 1fr 1fr; } + .colophon__mark { grid-column: 1 / -1; justify-self: start; } } diff --git a/static/css/bundle.css b/static/css/bundle.css index 31485bd..37f7dbe 100644 --- a/static/css/bundle.css +++ b/static/css/bundle.css @@ -1,2 +1,3 @@ +@import "./fonts.css"; @import "./reset.css"; @import "./base.css"; diff --git a/static/css/fonts.css b/static/css/fonts.css new file mode 100644 index 0000000..2f8a696 --- /dev/null +++ b/static/css/fonts.css @@ -0,0 +1,77 @@ +/* Cyclocrust — self-hosted faces (no external requests). + Jost = brand display face — a Futura homage (geometric, Renner). + Masthead, titles, labels, buttons, nav. + Literata = serif reading column. + JetBrains Mono = dates, entry numbers, spec keys, captions. */ + +/* --- Jost (Futura) --------------------------------------------------------- */ +@font-face{font-family:"Jost";font-style:normal;font-weight:300;font-display:swap; + src:url("/static/fonts/jost-300-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Jost";font-style:normal;font-weight:300;font-display:swap; + src:url("/static/fonts/jost-300-lat.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:"Jost";font-style:normal;font-weight:400;font-display:swap; + src:url("/static/fonts/jost-400-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Jost";font-style:normal;font-weight:400;font-display:swap; + src:url("/static/fonts/jost-400-lat.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:"Jost";font-style:normal;font-weight:500;font-display:swap; + src:url("/static/fonts/jost-500-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Jost";font-style:normal;font-weight:500;font-display:swap; + src:url("/static/fonts/jost-500-lat.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:"Jost";font-style:normal;font-weight:600;font-display:swap; + src:url("/static/fonts/jost-600-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Jost";font-style:normal;font-weight:600;font-display:swap; + src:url("/static/fonts/jost-600-lat.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:"Jost";font-style:normal;font-weight:700;font-display:swap; + src:url("/static/fonts/jost-700-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Jost";font-style:normal;font-weight:700;font-display:swap; + src:url("/static/fonts/jost-700-lat.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;} + +/* --- Literata -------------------------------------------------------------- */ +@font-face{font-family:"Literata";font-style:normal;font-weight:400;font-display:swap; + src:url("/static/fonts/literata-400-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Literata";font-style:normal;font-weight:400;font-display:swap; + src:url("/static/fonts/literata-400-lat.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:"Literata";font-style:italic;font-weight:400;font-display:swap; + src:url("/static/fonts/literata-400-i-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Literata";font-style:italic;font-weight:400;font-display:swap; + src:url("/static/fonts/literata-400-i-lat.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:"Literata";font-style:normal;font-weight:600;font-display:swap; + src:url("/static/fonts/literata-600-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Literata";font-style:normal;font-weight:600;font-display:swap; + src:url("/static/fonts/literata-600-lat.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:"Literata";font-style:normal;font-weight:700;font-display:swap; + src:url("/static/fonts/literata-700-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"Literata";font-style:normal;font-weight:700;font-display:swap; + src:url("/static/fonts/literata-700-lat.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;} + +/* --- JetBrains Mono (dates, numbers, keys) --------------------------------- */ +@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:400;font-display:swap; + src:url("/static/fonts/jbmono-400-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:400;font-display:swap; + src:url("/static/fonts/jbmono-400-lat.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:"JetBrains Mono";font-style:normal;font-weight:700;font-display:swap; + src:url("/static/fonts/jbmono-700-cyr.woff2") format("woff2"); + unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;} +@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:700;font-display:swap; + src:url("/static/fonts/jbmono-700-lat.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;} diff --git a/static/css/reset.css b/static/css/reset.css index c98df43..f6d4a1b 100644 --- a/static/css/reset.css +++ b/static/css/reset.css @@ -1,19 +1,67 @@ +/* Cyclocrust 51 — reset */ + +*, +*::before, +*::after { + box-sizing: border-box; +} + * { margin: 0; } -p, h1, h2, h3, h4, h5, h6 { +html { + -webkit-text-size-adjust: 100%; + text-size-adjust: 100%; +} + +img, +svg, +video { + display: block; + max-width: 100%; +} + +img { + height: auto; +} + +p, +h1, +h2, +h3, +h4, +h5, +h6 { overflow-wrap: break-word; } -p { +p, +blockquote, +li, +.prose { text-wrap: pretty; } -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { text-wrap: balance; } -ul { - padding: 0; +ul, +ol { + padding: 0; + list-style: none; +} + +button, +input, +select, +textarea { + font: inherit; + color: inherit; } diff --git a/static/fonts/jbmono-400-cyr.woff2 b/static/fonts/jbmono-400-cyr.woff2 new file mode 100644 index 0000000..de39acb Binary files /dev/null and b/static/fonts/jbmono-400-cyr.woff2 differ diff --git a/static/fonts/jbmono-400-lat.woff2 b/static/fonts/jbmono-400-lat.woff2 new file mode 100644 index 0000000..4d09cda Binary files /dev/null and b/static/fonts/jbmono-400-lat.woff2 differ diff --git a/static/fonts/jbmono-500-cyr.woff2 b/static/fonts/jbmono-500-cyr.woff2 new file mode 100644 index 0000000..de39acb Binary files /dev/null and b/static/fonts/jbmono-500-cyr.woff2 differ diff --git a/static/fonts/jbmono-500-lat.woff2 b/static/fonts/jbmono-500-lat.woff2 new file mode 100644 index 0000000..4d09cda Binary files /dev/null and b/static/fonts/jbmono-500-lat.woff2 differ diff --git a/static/fonts/jbmono-700-cyr.woff2 b/static/fonts/jbmono-700-cyr.woff2 new file mode 100644 index 0000000..de39acb Binary files /dev/null and b/static/fonts/jbmono-700-cyr.woff2 differ diff --git a/static/fonts/jbmono-700-lat.woff2 b/static/fonts/jbmono-700-lat.woff2 new file mode 100644 index 0000000..4d09cda Binary files /dev/null and b/static/fonts/jbmono-700-lat.woff2 differ diff --git a/static/fonts/jost-300-cyr.woff2 b/static/fonts/jost-300-cyr.woff2 new file mode 100644 index 0000000..52e1f88 Binary files /dev/null and b/static/fonts/jost-300-cyr.woff2 differ diff --git a/static/fonts/jost-300-lat.woff2 b/static/fonts/jost-300-lat.woff2 new file mode 100644 index 0000000..08a7b80 Binary files /dev/null and b/static/fonts/jost-300-lat.woff2 differ diff --git a/static/fonts/jost-400-cyr.woff2 b/static/fonts/jost-400-cyr.woff2 new file mode 100644 index 0000000..52e1f88 Binary files /dev/null and b/static/fonts/jost-400-cyr.woff2 differ diff --git a/static/fonts/jost-400-lat.woff2 b/static/fonts/jost-400-lat.woff2 new file mode 100644 index 0000000..08a7b80 Binary files /dev/null and b/static/fonts/jost-400-lat.woff2 differ diff --git a/static/fonts/jost-500-cyr.woff2 b/static/fonts/jost-500-cyr.woff2 new file mode 100644 index 0000000..52e1f88 Binary files /dev/null and b/static/fonts/jost-500-cyr.woff2 differ diff --git a/static/fonts/jost-500-lat.woff2 b/static/fonts/jost-500-lat.woff2 new file mode 100644 index 0000000..08a7b80 Binary files /dev/null and b/static/fonts/jost-500-lat.woff2 differ diff --git a/static/fonts/jost-600-cyr.woff2 b/static/fonts/jost-600-cyr.woff2 new file mode 100644 index 0000000..52e1f88 Binary files /dev/null and b/static/fonts/jost-600-cyr.woff2 differ diff --git a/static/fonts/jost-600-lat.woff2 b/static/fonts/jost-600-lat.woff2 new file mode 100644 index 0000000..08a7b80 Binary files /dev/null and b/static/fonts/jost-600-lat.woff2 differ diff --git a/static/fonts/jost-700-cyr.woff2 b/static/fonts/jost-700-cyr.woff2 new file mode 100644 index 0000000..52e1f88 Binary files /dev/null and b/static/fonts/jost-700-cyr.woff2 differ diff --git a/static/fonts/jost-700-lat.woff2 b/static/fonts/jost-700-lat.woff2 new file mode 100644 index 0000000..08a7b80 Binary files /dev/null and b/static/fonts/jost-700-lat.woff2 differ diff --git a/static/fonts/literata-400-cyr.woff2 b/static/fonts/literata-400-cyr.woff2 new file mode 100644 index 0000000..2b32dc8 Binary files /dev/null and b/static/fonts/literata-400-cyr.woff2 differ diff --git a/static/fonts/literata-400-i-cyr.woff2 b/static/fonts/literata-400-i-cyr.woff2 new file mode 100644 index 0000000..53e7d40 Binary files /dev/null and b/static/fonts/literata-400-i-cyr.woff2 differ diff --git a/static/fonts/literata-400-i-lat.woff2 b/static/fonts/literata-400-i-lat.woff2 new file mode 100644 index 0000000..1cbf486 Binary files /dev/null and b/static/fonts/literata-400-i-lat.woff2 differ diff --git a/static/fonts/literata-400-lat.woff2 b/static/fonts/literata-400-lat.woff2 new file mode 100644 index 0000000..cae7062 Binary files /dev/null and b/static/fonts/literata-400-lat.woff2 differ diff --git a/static/fonts/literata-600-cyr.woff2 b/static/fonts/literata-600-cyr.woff2 new file mode 100644 index 0000000..2b32dc8 Binary files /dev/null and b/static/fonts/literata-600-cyr.woff2 differ diff --git a/static/fonts/literata-600-lat.woff2 b/static/fonts/literata-600-lat.woff2 new file mode 100644 index 0000000..cae7062 Binary files /dev/null and b/static/fonts/literata-600-lat.woff2 differ diff --git a/static/fonts/literata-700-cyr.woff2 b/static/fonts/literata-700-cyr.woff2 new file mode 100644 index 0000000..2b32dc8 Binary files /dev/null and b/static/fonts/literata-700-cyr.woff2 differ diff --git a/static/fonts/literata-700-lat.woff2 b/static/fonts/literata-700-lat.woff2 new file mode 100644 index 0000000..cae7062 Binary files /dev/null and b/static/fonts/literata-700-lat.woff2 differ diff --git a/static/images/grain.png b/static/images/grain.png new file mode 100644 index 0000000..6b13327 Binary files /dev/null and b/static/images/grain.png differ diff --git a/static/images/hero-xerox.png b/static/images/hero-xerox.png new file mode 100644 index 0000000..f79fe11 Binary files /dev/null and b/static/images/hero-xerox.png differ diff --git a/static/images/lugs-xerox.png b/static/images/lugs-xerox.png new file mode 100644 index 0000000..9456852 Binary files /dev/null and b/static/images/lugs-xerox.png differ