Build responsive Buch & Bohne website from supplied design
showcase/deploy Live at https://showcase.andrefiedler.de/2608_BuB/
@@ -0,0 +1,8 @@
|
|||||||
|
.DS_Store
|
||||||
|
.venv/
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
tmp/
|
||||||
|
output/
|
||||||
|
.playwright-cli/
|
||||||
|
docs/superpowers/
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Buch & Bohne
|
||||||
|
|
||||||
|
Die Website für **Buch & Bohne e. V.**, Buchladen und Lesecafé am Markt 5 in Oelsnitz.
|
||||||
|
|
||||||
|
[Website öffnen](https://showcase.andrefiedler.de/2608_BuB/)
|
||||||
|
|
||||||
|
Umsetzung der bereitgestellten Gestaltung mit responsivem Layout, lokal eingebundenen Schriften, Kontaktlinks und Unterstützung per Überweisung oder PayPal.
|
||||||
|
|
||||||
|
Hinweise zur Pflege stehen in [docs/implementation.md](docs/implementation.md).
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
const copyButton = document.querySelector('.copy-iban');
|
||||||
|
const status = document.querySelector('#copy-status');
|
||||||
|
|
||||||
|
copyButton?.addEventListener('click', async () => {
|
||||||
|
status.textContent = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(copyButton.dataset.iban);
|
||||||
|
status.textContent = 'Die IBAN wurde in die Zwischenablage kopiert.';
|
||||||
|
copyButton.title = 'IBAN kopiert';
|
||||||
|
} catch {
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNodeContents(copyButton);
|
||||||
|
const selection = window.getSelection();
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
status.textContent = 'Bitte kopieren Sie die markierte IBAN.';
|
||||||
|
copyButton.title = 'Bitte die markierte IBAN kopieren';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 135 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,27 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 254"><defs><clipPath id="clip_53">
|
||||||
|
<path transform="matrix(1,0,0,-1,0,900)" d="M452.348 900 1200 646.206V671.203L525.985 900Z" />
|
||||||
|
</clipPath>
|
||||||
|
</defs><path transform="matrix(1,0,0,-1,0,134.74762)" d="M0 0V-23.7L1200 36.564V60.264Z" fill="#fbbb0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,0,134.74799)" d="M0 0V-2.6L23.626-22.513 78.499-19.757 51.961 2.609Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,105.8332,129.43299)" d="M0 0 26.538-22.367 81.411-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,214.5783,123.97168)" d="M0 0 26.538-22.367 81.41-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,323.3234,118.510379)" d="M0 0 26.538-22.367 81.41-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,432.0677,113.049198)" d="M0 0 26.538-22.367 81.411-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,540.812,107.58801)" d="M0 0 26.538-22.367 81.411-19.611 54.873 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,649.5579,102.12671)" d="M0 0 26.538-22.367 81.41-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,758.3023,96.66553)" d="M0 0 26.538-22.367 81.411-19.611 54.873 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,867.0474,91.20422)" d="M0 0 26.538-22.367 81.411-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,975.7925,85.74292)" d="M0 0 26.538-22.367 81.41-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,1084.5376,80.28168)" d="M0 0 26.538-22.367 81.41-19.611 54.872 2.756Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,452.3481,0)" d="M0 0 747.652-253.794V-228.797L73.637 0Z" fill="#fbbb0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,490.7219,0)" d="M0 0 8.561-15.932 60.587-33.593 44.16-3.02 35.263 0Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,602.3868,50.931276)" d="M0 0 52.026-17.661 35.599 12.912-16.427 30.573Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,705.4904,85.9303)" d="M0 0 52.026-17.66 35.599 12.912-16.428 30.573Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,808.5939,120.9292)" d="M0 0 52.026-17.661 35.599 12.912-16.427 30.573Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,911.6972,155.9281)" d="M0 0 52.026-17.66 35.599 12.912-16.428 30.573Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,1014.801,190.92713)" d="M0 0 52.027-17.661 35.599 12.912-16.427 30.573Z" fill="#0c0c0c" />
|
||||||
|
<path transform="matrix(1,0,0,-1,1117.9052,225.92627)" d="M0 0 52.026-17.661 35.599 12.913-16.427 30.573Z" fill="#0c0c0c" />
|
||||||
|
<g clip-path="url(#clip_53)">
|
||||||
|
<path transform="matrix(1,0,0,-1,1231.2191,200.76282)" d="M0 0-33.007-17.735 18.529-113.649 51.536-95.913Z" fill="#0c0c0c" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2011 The Roboto Project Authors (https://github.com/googlefonts/roboto-classic)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
https://openfontlicense.org
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 26 KiB |
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="507.62 142 184.76 146.67"><defs /><path transform="matrix(1,0,0,-1,673.2455,163.39783)" d="M0 0-58.484-28.539-58.695-28.588C-58.873-28.588-59.045-28.488-59.128-28.317-59.245-28.078-59.146-27.789-58.906-27.673L-.665 .748C-1.138 1.331-1.552 1.966-1.891 2.656L-62.216-26.782-62.427-26.831C-62.605-26.831-62.776-26.731-62.86-26.56-62.977-26.321-62.877-26.032-62.638-25.916L-2.271 3.542C-2.881 5.155-3.07 6.843-2.861 8.573-3.003 8.502-64.139-21.618-64.139-21.618-64.139-21.618-66.397-22.871-66.675-24.695-67.084-28.322-64.862-31.402-62.74-32.009-61.476-32.362-60.029-32.143-59.354-31.862-53.141-29.084 2.013-1.609 2.013-1.609 1.275-1.146 .6-.608 0 0" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,691.2115,145.61573)" d="M0 0C-.231 1.23-.231 2.412-.018 3.616L-.166 3.603C-.166 3.603-36.995-2.646-40.247-3.205-48.058-4.547-55.871-5.887-63.681-7.234-65.557-7.558-66.121-8.057-66.418-9.606-66.743-11.296-66.077-13.031-64.802-13.82-64.122-14.241-63.402-14.218-62.646-14.086-54.89-12.734-47.131-11.393-39.372-10.053-36.123-9.493-2.544-3.798 .708-3.244L1.168-3.165C.612-2.189 .212-1.131 0 0" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,669.8396,180.38739)" d="M0 0C-.172 .802-.236 1.548-.213 2.348-.314 2.318-.466 2.277-.466 2.277-.466 2.277-16.668-2.962-19.806-3.982-27.343-6.431-34.883-8.879-42.419-11.332-44.229-11.922-44.716-12.496-44.788-14.072-44.867-15.791-43.959-17.413-42.583-18.011-41.85-18.33-41.141-18.204-40.412-17.965-32.93-15.514-25.443-13.073-17.958-10.634-14.822-9.614-1.687-5.359 1.451-4.344L1.966-4.177C1.012-2.95 .331-1.547 0 0" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,679.3229,190.67407)" d="M0 0C-2.351 1.469-5.031 .807-7.477-1.216-7.763-.268-8.071 .714-8.399 1.725-8.545 2.174-9.043 2.414-9.511 2.262L-46.892-9.884C-47.36-10.036-47.622-10.523-47.476-10.971-45.313-17.627-43.161-22.758-41.499-24.802-38.47-28.527-34.62-30.583-29.994-30.967L-29.952-31.14-29.867-31.401C-29.638-32.104-28.884-32.488-28.181-32.26L-11.496-26.838C-10.793-26.61-10.409-25.856-10.637-25.153L-10.722-24.892-10.789-24.727C-8.842-23.05-7.391-21.097-6.438-18.875-3.816-18.367-1.307-16.342 .461-13.513 3.003-9.444 4.368-2.729 0 0M-1.726-12.213C-2.756-13.861-4.091-15.118-5.476-15.81-5.285-14.902-5.159-13.959-5.105-12.977-5.005-11.144-5.595-7.958-6.692-3.943-4.856-2.088-2.914-1.283-1.372-2.246 1.306-3.919 .196-9.137-1.726-12.213" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,652.7086,272.5348)" d="M0 0C0 6.153-3.782 10.036-11.902 10.036-21.03 10.036-25.417 4.993-25.417-2.975-25.417-11.902-20.374-16.138-11.397-16.138-8.019-16.138-4.539-15.482-2.017-14.121L-1.664-7.968-1.866-7.817C-3.782-8.926-6.758-9.733-9.128-9.733-12.456-9.733-14.02-8.624-14.373-4.942H-.404C-.151-3.228 0-1.664 0 0M-9.884-.958H-14.373C-14.221 4.388-13.516 6.001-11.952 6.001-10.389 6.001-9.683 4.135-9.884-.958M-38.63-15.684H-27.081C-27.434-12.356-27.535-9.834-27.535-5.749V.151C-27.535 7.161-29.704 9.935-34.848 9.935-38.025 9.935-40.95 8.573-43.018 6.203L-43.421 9.531H-54.264C-53.961 6.102-53.81 2.875-53.81-.807V-4.69C-53.81-9.128-53.961-12.356-54.314-15.684H-42.665V2.774C-42.009 3.228-41.404 3.429-40.748 3.429-39.235 3.429-38.63 2.37-38.63-1.009ZM-46.749 21.34H-35.15C-35.503 24.921-35.654 27.392-35.654 31.729V37.377C-35.654 44.185-37.924 46.909-43.017 46.909-46.094 46.909-48.716 45.698-50.733 43.631V55.078H-62.584C-62.03 48.724-61.828 43.832-61.828 38.033-61.828 32.132-62.08 26.635-62.584 21.29H-50.733V39.697C-50.178 40.1-49.472 40.403-48.867 40.403-47.304 40.403-46.749 39.394-46.749 35.965ZM-64.45 21.996-64.097 27.745-64.198 27.846C-65.711 27.241-67.022 26.938-68.333 26.938-71.157 26.938-72.771 28.753-72.771 34.755-72.771 40-71.359 41.613-68.686 41.613-67.325 41.613-66.013 41.26-64.601 40.554L-64.5 40.605-64.702 45.9C-66.719 46.556-68.787 46.959-70.905 46.959-79.68 46.959-84.118 42.521-84.118 33.746-84.118 25.677-80.336 20.735-71.309 20.735-69.039 20.735-66.366 21.239-64.45 21.996M-85.782-2.875C-85.782 5.346-90.674 10.036-99.6 10.036-108.476 10.036-113.57 5.346-113.57-2.875-113.57-11.246-108.476-16.138-99.6-16.138-90.725-16.138-85.782-11.196-85.782-2.875M-97.23-3.127C-97.23-9.834-97.886-12.255-99.651-12.255-101.466-12.255-102.122-9.935-102.122-3.177-102.122 3.732-101.567 6.102-99.651 6.102-97.886 6.102-97.23 3.681-97.23-3.127M-97.18 21.29H-85.883C-86.438 24.719-86.64 28.199-86.64 31.628V46.505H-98.239C-97.835 43.227-97.734 39.899-97.734 36.621V28.501C-98.339 27.846-98.945 27.493-99.651 27.493-101.113 27.493-101.769 28.451-101.769 31.729V46.505H-113.368C-112.964 43.378-112.914 40.201-112.914 36.066V30.367C-112.914 23.105-110.796 20.987-105.702 20.987-102.122 20.987-99.449 22.349-97.482 25.122ZM-115.233-6.405C-115.233-1.715-117.956 1.261-123.706 2.118V2.269C-118.41 3.026-116.04 5.547-116.04 9.128-116.04 13.869-119.873 17.096-129.001 17.096H-144.887C-144.382 12.154-144.231 7.06-144.231 1.614-144.231-4.438-144.382-10.641-145.088-15.684H-128.345C-120.075-15.684-115.233-12.406-115.233-6.405M-127.79 7.918C-127.79 4.993-128.95 3.681-131.875 3.681H-132.581V12.507H-132.027C-129.203 12.507-127.79 11.145-127.79 7.918M-127.236-5.547C-127.236-9.38-128.799-10.943-131.976-10.943H-132.581V.101H-131.825C-128.749 .101-127.236-1.715-127.236-5.547M-123.706 39.092V39.243C-118.41 40-116.04 42.521-116.04 46.102-116.04 50.842-119.873 54.07-129.001 54.07H-144.887C-144.382 49.128-144.231 44.034-144.231 38.588-144.231 32.536-144.382 26.333-145.088 21.29H-128.345C-120.075 21.29-115.233 24.568-115.233 30.569-115.233 35.259-117.956 38.234-123.706 39.092M-127.79 44.891C-127.79 41.966-128.95 40.655-131.875 40.655H-132.581V49.481H-132.027C-129.203 49.481-127.79 48.119-127.79 44.891M-127.236 31.426C-127.236 27.594-128.799 26.03-131.976 26.03H-132.581V37.075H-131.825C-128.749 37.075-127.236 35.259-127.236 31.426M-83.967 18.105C-83.412 11.75-83.211 6.859-83.211 1.059-83.211-4.841-83.463-10.338-83.967-15.684H-72.116V2.723C-71.561 3.127-70.855 3.429-70.25 3.429-68.686 3.429-68.132 2.421-68.132-1.009V-15.634H-56.533C-56.886-12.053-57.037-9.582-57.037-5.245V.403C-57.037 7.212-59.306 9.935-64.4 9.935-67.476 9.935-70.098 8.725-72.116 6.657V18.105Z" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,642.92,261.54908)" d="M0 0 6.872 4.635 6.857 4.748C4.045 5.734 1.176 6.804-1.622 7.861-.93 12.928-2.206 16.729-4.408 19.721L-9.004 16.622C-6.791 14.25-5.07 11.608-4.533 8.903L-15.5 12.976C-12.896 16.573-12.152 19.835-14.142 22.786-16.503 26.285-20.651 26.615-25.12 23.601-30.094 20.245-30.892 16.518-28.873 13.525-27.394 11.332-24.918 9.752-21.639 8.529-24.337 4.071-24.68-.331-22.206-3.999-19.05-8.678-13.783-9.848-8.302-6.152-5.73-4.417-3.953-1.869-2.983 1.239ZM-18.084 .621C-19.506 2.729-19.872 5.181-18.87 7.697-15.012 6.251-10.461 4.414-5.513 2.354-6.239 .883-7.291-.195-8.724-1.161-12.139-3.465-15.838-2.709-18.084 .621M-24.056 17.387C-25.109 18.947-24.932 20.231-23.414 21.255-21.77 22.364-19.891 21.669-18.554 19.687-17.332 17.875-16.911 15.705-17.999 13.499-20.924 14.47-22.919 15.701-24.056 17.387" fill="#ffffff" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.8 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 122 KiB |
@@ -0,0 +1,429 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: Roboto;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url("./fonts/roboto-latin.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Roboto;
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400 700;
|
||||||
|
font-display: swap;
|
||||||
|
src: url("./fonts/roboto-italic-latin.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: dark;
|
||||||
|
--color-burgundy: #982249;
|
||||||
|
--color-white: #fff;
|
||||||
|
--color-cream: #faf5eb;
|
||||||
|
--color-sand: #e5cd9c;
|
||||||
|
--color-announcement: #f2e6cc;
|
||||||
|
--color-focus: #ffc300;
|
||||||
|
/* One design unit is one point on the supplied 1200 × 900 layout. */
|
||||||
|
--unit: 0.0833333333vw;
|
||||||
|
--font-body: Roboto, system-ui, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
min-inline-size: 280px;
|
||||||
|
background: var(--color-burgundy);
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
position: relative;
|
||||||
|
isolation: isolate;
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-white);
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-synthesis: none;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::before {
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
inset: 0 0 auto;
|
||||||
|
min-block-size: 100svh;
|
||||||
|
block-size: calc(900 * var(--unit));
|
||||||
|
background-image: image-set(url("./background-1200.webp") 1x, url("./background-2400.webp") 2x);
|
||||||
|
background-size: 100% auto;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center top;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
min-block-size: max(100svh, calc(900 * var(--unit)));
|
||||||
|
padding: calc(142 * var(--unit)) calc(24 * var(--unit)) calc(56 * var(--unit));
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
p,
|
||||||
|
dl,
|
||||||
|
dd {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
max-inline-size: 100%;
|
||||||
|
block-size: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
text-underline-offset: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover,
|
||||||
|
.copy-iban:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:focus-visible,
|
||||||
|
button:focus-visible {
|
||||||
|
outline: 2px solid var(--color-focus);
|
||||||
|
outline-offset: 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
inline-size: calc(184.76 * var(--unit));
|
||||||
|
block-size: calc(146.67 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement {
|
||||||
|
margin-block-start: calc(31.4 * var(--unit));
|
||||||
|
color: var(--color-cream);
|
||||||
|
font-style: italic;
|
||||||
|
font-size: calc(15 * var(--unit));
|
||||||
|
line-height: calc(22 * var(--unit));
|
||||||
|
letter-spacing: 0.005em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement h1 {
|
||||||
|
margin-block-end: calc(8.64 * var(--unit));
|
||||||
|
color: var(--color-announcement);
|
||||||
|
font-size: calc(19 * var(--unit));
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: calc(23 * var(--unit));
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.design-line {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.support {
|
||||||
|
margin-block-start: calc(18.25 * var(--unit));
|
||||||
|
color: var(--color-cream);
|
||||||
|
font-size: calc(15 * var(--unit));
|
||||||
|
line-height: calc(22 * var(--unit));
|
||||||
|
font-style: italic;
|
||||||
|
letter-spacing: 0.005em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.support-title {
|
||||||
|
inline-size: calc(454.02 * var(--unit));
|
||||||
|
margin-inline: auto;
|
||||||
|
transform: translateX(calc(-9.22 * var(--unit)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.support-title img {
|
||||||
|
inline-size: 100%;
|
||||||
|
aspect-ratio: 454.02 / 47.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.support-options {
|
||||||
|
margin-block-start: calc(5.63 * var(--unit));
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thanks {
|
||||||
|
margin-block-start: calc(9 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact {
|
||||||
|
margin-block-start: calc(22.63 * var(--unit));
|
||||||
|
font-size: calc(10 * var(--unit));
|
||||||
|
line-height: calc(14 * var(--unit));
|
||||||
|
letter-spacing: 0.005em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact h2,
|
||||||
|
.bank h2 {
|
||||||
|
color: var(--color-sand);
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.015em;
|
||||||
|
}
|
||||||
|
|
||||||
|
address {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-person,
|
||||||
|
.contact-channels {
|
||||||
|
margin-block-start: calc(12 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-line,
|
||||||
|
.email-line {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instagram {
|
||||||
|
margin-block-start: calc(10 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: var(--color-sand);
|
||||||
|
}
|
||||||
|
|
||||||
|
.donations {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: calc(185 * var(--unit)) calc(119 * var(--unit));
|
||||||
|
gap: calc(24 * var(--unit));
|
||||||
|
margin-block-start: calc(19.92 * var(--unit));
|
||||||
|
text-align: start;
|
||||||
|
font-size: calc(10 * var(--unit));
|
||||||
|
line-height: calc(14 * var(--unit));
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bank {
|
||||||
|
padding-block-start: calc(14.24 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-holder {
|
||||||
|
margin-block-start: calc(12 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-holder strong {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-details {
|
||||||
|
margin-block-start: calc(14 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-details > div {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: calc(29 * var(--unit)) 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-iban {
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
letter-spacing: inherit;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: copy;
|
||||||
|
user-select: all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-link {
|
||||||
|
display: block;
|
||||||
|
inline-size: calc(85.54 * var(--unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
.paypal-address {
|
||||||
|
display: inline-block;
|
||||||
|
margin-block-start: calc(10.86 * var(--unit));
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visually-hidden {
|
||||||
|
position: absolute;
|
||||||
|
inline-size: 1px;
|
||||||
|
block-size: 1px;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip-path: inset(50%);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
inset-block-start: 1rem;
|
||||||
|
inset-inline-start: 1rem;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
background: var(--color-burgundy);
|
||||||
|
transform: translateY(-200%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link:focus {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 1024px) {
|
||||||
|
:root {
|
||||||
|
--unit: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::before {
|
||||||
|
block-size: 100%;
|
||||||
|
background-image: url("./background-mobile.webp");
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::after {
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
inset: 0 0 auto;
|
||||||
|
block-size: 254px;
|
||||||
|
background: url("./construction-tape.svg") center top / 1200px 254px no-repeat;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
min-block-size: 100svh;
|
||||||
|
padding: 154px 24px 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
inline-size: 185px;
|
||||||
|
block-size: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement,
|
||||||
|
.support {
|
||||||
|
max-inline-size: 620px;
|
||||||
|
inline-size: 100%;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement {
|
||||||
|
margin-block-start: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.announcement h1 {
|
||||||
|
margin-block-end: 16px;
|
||||||
|
font-size: 21px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.support {
|
||||||
|
margin-block-start: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.support-title {
|
||||||
|
max-inline-size: 100%;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.support-options {
|
||||||
|
margin-block-start: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thanks {
|
||||||
|
margin-block-start: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact {
|
||||||
|
margin-block-start: 30px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-channels a,
|
||||||
|
.instagram a {
|
||||||
|
display: inline-block;
|
||||||
|
padding-block: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donations {
|
||||||
|
grid-template-columns: minmax(0, 260px) 170px;
|
||||||
|
gap: 28px;
|
||||||
|
margin-block-start: 30px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-details > div {
|
||||||
|
grid-template-columns: 40px 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-link {
|
||||||
|
inline-size: 124px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-iban {
|
||||||
|
padding-block: 4px;
|
||||||
|
margin-block: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 600px) {
|
||||||
|
.page {
|
||||||
|
padding-inline: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.design-line {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-phone {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-separator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donations {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
gap: 26px;
|
||||||
|
inline-size: min(100%, 288px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bank {
|
||||||
|
padding-block-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paypal {
|
||||||
|
justify-self: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-link {
|
||||||
|
inline-size: 140px;
|
||||||
|
margin-inline: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
scroll-behavior: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 193 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 613 KiB |
@@ -0,0 +1,28 @@
|
|||||||
|
# Implementation and maintenance
|
||||||
|
|
||||||
|
The supplied 1200 × 900 PDF and its IDML source define the desktop composition. All original design files are preserved under `design/`. The photographic backdrop and construction tape are extracted together to preserve the print export's crop, tint and shadows. The logo and Lumios Marker heading retain their original outlines as SVG artwork; all other content is semantic, selectable HTML in `index.html`.
|
||||||
|
|
||||||
|
CSS lives in `assets/styles.css`; all colors are CSS custom properties. Layout scales with the design above 1024 px. At smaller sizes the type becomes larger and wraps; at 600 px the bank and PayPal details stack in their original reading order. The mobile background separates the supplied tape from the photograph so that it remains above the logo while the photo fills a tall page. `assets/app.mjs` only enhances the IBAN with clipboard support and an accessible selection fallback. Contact and payment links work without JavaScript.
|
||||||
|
|
||||||
|
## Preview and deployment
|
||||||
|
|
||||||
|
Requires Node 20.11 or newer. There are no npm dependencies and no third-party page requests.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run build
|
||||||
|
python3 -m http.server 8080 --directory dist --bind 127.0.0.1
|
||||||
|
```
|
||||||
|
|
||||||
|
`scripts/build.mjs` copies only explicit public files to `dist/`. Source PDFs, InDesign files, original TIFFs, scripts and documentation are never in the public artifact. `showcase.json` selects `dist` for the existing organization deployer. A push to `showcase/2608_BuB` on `main` deploys to `https://showcase.andrefiedler.de/2608_BuB/`; the `showcase/deploy` commit status reports completion.
|
||||||
|
|
||||||
|
## Artwork and fonts
|
||||||
|
|
||||||
|
Generated web assets are committed. Recreate them only when the design changes, using `scripts/prepare-assets.py` with PyMuPDF, Pillow, fontTools (WOFF support) and Poppler's `pdftoppm`. Its PDF object/group assertions deliberately target this exact supplied design. The script downloads the matching [Roboto 3.015 release](https://github.com/googlefonts/roboto-3-classic/releases/tag/v3.015), fixes the width axis to 100, keeps weights 400–700, and subsets Latin and punctuation. The accompanying [OFL license](../assets/fonts/OFL.txt) is bundled. The commercial handwritten font is not distributed; its original supplied heading is retained as outlined artwork.
|
||||||
|
|
||||||
|
Favicon SVG, ICO, Apple touch icon and manifest icons are derived from the original book-and-cup symbol. The PayPal QR code is extracted from the supplied PDF and reduced to a 64-color PNG; its encoded payload and geometry are preserved and verified by decoding. The social preview is a crop of the supplied design.
|
||||||
|
|
||||||
|
## Search metadata
|
||||||
|
|
||||||
|
The document contains German title/description/author information, canonical and social metadata, a local social image, and JSON-LD for the business, website and page. Only facts present in the design are used; no opening hours, ratings or registration details are invented. The canonical and all structured URLs use the requested showcase path. Update these together with `sitemap.xml`, `robots.txt` and the manifest ID when moving to a different domain.
|
||||||
|
|
||||||
|
The single canonical page is listed in `sitemap.xml`. Submit `https://showcase.andrefiedler.de/2608_BuB/sitemap.xml` in the site's search-engine webmaster accounts when available. The local `robots.txt` is supplied for hosting completeness, but crawlers only use `/robots.txt` at the domain root. The shared host currently has no root robots or sitemap; this permits crawling and does not automatically advertise this sitemap. A host administrator can add this sitemap URL to the shared root robots file. Search indexing itself is outside the deployment workflow.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Verification
|
||||||
|
|
||||||
|
Local checks on 2026-09-07:
|
||||||
|
|
||||||
|
- Compared the rendered page against the supplied PDF at 1200 × 900, retaining artwork positions and correcting body text baselines. Inspected 1800 px desktop and 320, 390 and 768 px mobile/tablet screenshots.
|
||||||
|
- Browser checks at 320, 390, 600, 768, 1024, 1200 and 1800 px: document width equals viewport width; all images load.
|
||||||
|
- No failed or third-party resource requests in the completed page.
|
||||||
|
- Clipboard action copies exactly `DE04870958245044385904` and announces success through the live status region.
|
||||||
|
- Keyboard navigation begins with the visible-on-focus skip link.
|
||||||
|
- With JavaScript disabled, the page content and seven native links remain available without overflow at 390 px.
|
||||||
|
- macOS Vision decodes the optimized PayPal QR as the original managed PayPal QR URL: `https://www.paypal.com/qrcodes/managed/d49af904-76e1-4181-9e35-064be97b4f66?utm_source=payandgetpaid`.
|
||||||
|
- Syntax checks pass for both `.mjs` files. Local asset references, unique IDs, fragment links, JSON-LD, sitemap XML, manifest icons and production-file exclusions pass.
|
||||||
|
- `npm run build` produces an approximately 807 kB static artifact, including social-preview and icon assets that are not requested during normal page rendering.
|
||||||
|
|
||||||
|
For each published revision, check the `showcase/deploy` status on its Gitea commit and compare the served files with `dist`. The repository is public by request. The organization listing is public so anonymous visitors can access it; the existing `hello-world` and `vite-example` repositories retain their private visibility.
|
||||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><rect width="128" height="128" rx="20" fill="#982249" /><svg viewBox="600 136 99 94" x="12" y="12" width="104" height="104"><defs /><path transform="matrix(1,0,0,-1,673.2455,163.39783)" d="M0 0-58.484-28.539-58.695-28.588C-58.873-28.588-59.045-28.488-59.128-28.317-59.245-28.078-59.146-27.789-58.906-27.673L-.665 .748C-1.138 1.331-1.552 1.966-1.891 2.656L-62.216-26.782-62.427-26.831C-62.605-26.831-62.776-26.731-62.86-26.56-62.977-26.321-62.877-26.032-62.638-25.916L-2.271 3.542C-2.881 5.155-3.07 6.843-2.861 8.573-3.003 8.502-64.139-21.618-64.139-21.618-64.139-21.618-66.397-22.871-66.675-24.695-67.084-28.322-64.862-31.402-62.74-32.009-61.476-32.362-60.029-32.143-59.354-31.862-53.141-29.084 2.013-1.609 2.013-1.609 1.275-1.146 .6-.608 0 0" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,691.2115,145.61573)" d="M0 0C-.231 1.23-.231 2.412-.018 3.616L-.166 3.603C-.166 3.603-36.995-2.646-40.247-3.205-48.058-4.547-55.871-5.887-63.681-7.234-65.557-7.558-66.121-8.057-66.418-9.606-66.743-11.296-66.077-13.031-64.802-13.82-64.122-14.241-63.402-14.218-62.646-14.086-54.89-12.734-47.131-11.393-39.372-10.053-36.123-9.493-2.544-3.798 .708-3.244L1.168-3.165C.612-2.189 .212-1.131 0 0" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,669.8396,180.38739)" d="M0 0C-.172 .802-.236 1.548-.213 2.348-.314 2.318-.466 2.277-.466 2.277-.466 2.277-16.668-2.962-19.806-3.982-27.343-6.431-34.883-8.879-42.419-11.332-44.229-11.922-44.716-12.496-44.788-14.072-44.867-15.791-43.959-17.413-42.583-18.011-41.85-18.33-41.141-18.204-40.412-17.965-32.93-15.514-25.443-13.073-17.958-10.634-14.822-9.614-1.687-5.359 1.451-4.344L1.966-4.177C1.012-2.95 .331-1.547 0 0" fill="#ffffff" />
|
||||||
|
<path transform="matrix(1,0,0,-1,679.3229,190.67407)" d="M0 0C-2.351 1.469-5.031 .807-7.477-1.216-7.763-.268-8.071 .714-8.399 1.725-8.545 2.174-9.043 2.414-9.511 2.262L-46.892-9.884C-47.36-10.036-47.622-10.523-47.476-10.971-45.313-17.627-43.161-22.758-41.499-24.802-38.47-28.527-34.62-30.583-29.994-30.967L-29.952-31.14-29.867-31.401C-29.638-32.104-28.884-32.488-28.181-32.26L-11.496-26.838C-10.793-26.61-10.409-25.856-10.637-25.153L-10.722-24.892-10.789-24.727C-8.842-23.05-7.391-21.097-6.438-18.875-3.816-18.367-1.307-16.342 .461-13.513 3.003-9.444 4.368-2.729 0 0M-1.726-12.213C-2.756-13.861-4.091-15.118-5.476-15.81-5.285-14.902-5.159-13.959-5.105-12.977-5.005-11.144-5.595-7.958-6.692-3.943-4.856-2.088-2.914-1.283-1.372-2.246 1.306-3.919 .196-9.137-1.726-12.213" fill="#ffffff" />
|
||||||
|
</svg></svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,150 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Buch & Bohne e. V. – Buchladen & Lesecafé in Oelsnitz</title>
|
||||||
|
<meta name="description" content="Buch & Bohne e. V.: Ihr Buchladen und Lesecafé am Markt 5 in Oelsnitz. Unsere Website wird überarbeitet – besuchen und unterstützen Sie unser Café!">
|
||||||
|
<meta name="author" content="Buch & Bohne e. V.">
|
||||||
|
<meta name="copyright" content="Buch & Bohne e. V.">
|
||||||
|
<meta name="robots" content="index, follow, max-image-preview:large">
|
||||||
|
<meta name="theme-color" content="#982249">
|
||||||
|
<meta name="color-scheme" content="dark">
|
||||||
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
<link rel="canonical" href="https://showcase.andrefiedler.de/2608_BuB/">
|
||||||
|
<link rel="sitemap" type="application/xml" href="./sitemap.xml">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:locale" content="de_DE">
|
||||||
|
<meta property="og:site_name" content="Buch & Bohne e. V.">
|
||||||
|
<meta property="og:title" content="Buch & Bohne – Buchladen & Lesecafé in Oelsnitz">
|
||||||
|
<meta property="og:description" content="Unsere Website wird überarbeitet. Besuchen Sie uns am Markt 5 in Oelsnitz – und werden Sie ein Teil von Buch & Bohne!">
|
||||||
|
<meta property="og:url" content="https://showcase.andrefiedler.de/2608_BuB/">
|
||||||
|
<meta property="og:image" content="https://showcase.andrefiedler.de/2608_BuB/assets/social-preview.jpg">
|
||||||
|
<meta property="og:image:width" content="1200">
|
||||||
|
<meta property="og:image:height" content="630">
|
||||||
|
<meta property="og:image:type" content="image/jpeg">
|
||||||
|
<meta property="og:image:alt" content="Buch & Bohne: Unsere Website wird überarbeitet. Werden Sie Teil unseres Buchladens und Lesecafés!">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:title" content="Buch & Bohne – Buchladen & Lesecafé in Oelsnitz">
|
||||||
|
<meta name="twitter:description" content="Besuchen und unterstützen Sie unser Lesecafé am Markt 5 in Oelsnitz.">
|
||||||
|
<meta name="twitter:image" content="https://showcase.andrefiedler.de/2608_BuB/assets/social-preview.jpg">
|
||||||
|
<meta name="twitter:image:alt" content="Buch & Bohne – Buchladen und Lesecafé in Oelsnitz">
|
||||||
|
<link rel="icon" href="./favicon.ico" sizes="16x16 32x32 48x48">
|
||||||
|
<link rel="icon" href="./favicon.svg" type="image/svg+xml" sizes="any">
|
||||||
|
<link rel="apple-touch-icon" href="./assets/apple-touch-icon.png" sizes="180x180">
|
||||||
|
<link rel="manifest" href="./site.webmanifest">
|
||||||
|
<link rel="preload" href="./assets/fonts/roboto-italic-latin.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="preload" href="./assets/fonts/roboto-latin.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
|
<link rel="stylesheet" href="./assets/styles.css">
|
||||||
|
<script type="module" src="./assets/app.mjs"></script>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@graph": [
|
||||||
|
{
|
||||||
|
"@type": ["BookStore", "CafeOrCoffeeShop"],
|
||||||
|
"@id": "https://showcase.andrefiedler.de/2608_BuB/#buch-und-bohne",
|
||||||
|
"name": "Buch & Bohne e. V.",
|
||||||
|
"url": "https://showcase.andrefiedler.de/2608_BuB/",
|
||||||
|
"description": "Buchladen und Lesecafé am Markt 5 in Oelsnitz.",
|
||||||
|
"logo": "https://showcase.andrefiedler.de/2608_BuB/assets/icon-512.png",
|
||||||
|
"image": "https://showcase.andrefiedler.de/2608_BuB/assets/social-preview.jpg",
|
||||||
|
"telephone": "+49 37421 23633",
|
||||||
|
"email": "lesecafe@buchundbohne.de",
|
||||||
|
"address": {
|
||||||
|
"@type": "PostalAddress",
|
||||||
|
"streetAddress": "Markt 5",
|
||||||
|
"addressLocality": "Oelsnitz",
|
||||||
|
"addressCountry": "DE"
|
||||||
|
},
|
||||||
|
"contactPoint": {
|
||||||
|
"@type": "ContactPoint",
|
||||||
|
"name": "Lilly Möbius",
|
||||||
|
"contactType": "Ansprechpartnerin",
|
||||||
|
"telephone": "+49 173 8022126",
|
||||||
|
"email": "lesecafe@buchundbohne.de",
|
||||||
|
"availableLanguage": "de"
|
||||||
|
},
|
||||||
|
"sameAs": ["https://www.instagram.com/buch_und_bohne_/"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "WebSite",
|
||||||
|
"@id": "https://showcase.andrefiedler.de/2608_BuB/#website",
|
||||||
|
"name": "Buch & Bohne e. V.",
|
||||||
|
"url": "https://showcase.andrefiedler.de/2608_BuB/",
|
||||||
|
"inLanguage": "de",
|
||||||
|
"publisher": {"@id": "https://showcase.andrefiedler.de/2608_BuB/#buch-und-bohne"}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "WebPage",
|
||||||
|
"@id": "https://showcase.andrefiedler.de/2608_BuB/#webpage",
|
||||||
|
"url": "https://showcase.andrefiedler.de/2608_BuB/",
|
||||||
|
"name": "Buch & Bohne e. V. – Buchladen & Lesecafé in Oelsnitz",
|
||||||
|
"inLanguage": "de",
|
||||||
|
"isPartOf": {"@id": "https://showcase.andrefiedler.de/2608_BuB/#website"},
|
||||||
|
"about": {"@id": "https://showcase.andrefiedler.de/2608_BuB/#buch-und-bohne"},
|
||||||
|
"author": {"@id": "https://showcase.andrefiedler.de/2608_BuB/#buch-und-bohne"}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a class="skip-link" href="#inhalt">Zum Inhalt</a>
|
||||||
|
<main class="page" id="inhalt">
|
||||||
|
<img class="logo" src="./assets/logo.svg" alt="Buch & Bohne" width="185" height="147" fetchpriority="high">
|
||||||
|
|
||||||
|
<section class="announcement" aria-labelledby="announcement-title">
|
||||||
|
<h1 id="announcement-title">Aktuell überarbeiten wir unsere Website.</h1>
|
||||||
|
<p>
|
||||||
|
<span class="design-line">Bleiben Sie gespannt. Und schauen Sie in der Zwischenzeit</span>
|
||||||
|
<span class="design-line">gerne bei uns im Buchladen und Lesecafé</span>
|
||||||
|
<span class="design-line">in Oelsnitz am Markt 5 vorbei.</span>
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="support" aria-labelledby="support-title">
|
||||||
|
<h2 class="support-title" id="support-title">
|
||||||
|
<span class="visually-hidden">Werden Sie ein Teil von „Buch & Bohne“!</span>
|
||||||
|
<img src="./assets/support-heading.svg" alt="" width="454" height="48">
|
||||||
|
</h2>
|
||||||
|
<p class="support-options">
|
||||||
|
<span class="design-line">Ob als Vereinsmitglied, Kuchen- oder Kaffeepate</span>
|
||||||
|
<span class="design-line">oder durch eine finanzielle Unterstützung – jeder Beitrag zählt.</span>
|
||||||
|
<span class="design-line">… und macht unser Café möglich.</span>
|
||||||
|
</p>
|
||||||
|
<p class="thanks">Vielen Dank für Ihre Unterstützung!</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="contact" aria-labelledby="contact-title">
|
||||||
|
<h2 id="contact-title">Ihre Ansprechpartnerin</h2>
|
||||||
|
<address>
|
||||||
|
<p class="contact-person"><strong>Lilly Möbius,</strong> Buch & Bohne e. V.</p>
|
||||||
|
<p class="contact-channels">
|
||||||
|
<span class="phone-line"><span class="label">Telefon</span> <a href="tel:+493742123633">037421 23633</a><span class="phone-separator"> . </span><span class="mobile-phone"><span class="label">mobil</span> <a href="tel:+491738022126">0173 8022126</a></span></span>
|
||||||
|
<span class="email-line"><span class="label">E-Mail</span> <a href="mailto:lesecafe@buchundbohne.de">lesecafe@buchundbohne.de</a></span>
|
||||||
|
</p>
|
||||||
|
<p class="instagram"><span class="label">Instagram:</span> <a href="https://www.instagram.com/buch_und_bohne_/">@buch_und_bohne_</a></p>
|
||||||
|
</address>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="donations" aria-labelledby="bank-title">
|
||||||
|
<div class="bank">
|
||||||
|
<h2 id="bank-title">Kontodaten</h2>
|
||||||
|
<p class="account-holder"><strong>Buch & Bohne e. V.</strong><br>Volksbank Vogtland-Saale-Orla eG</p>
|
||||||
|
<dl class="account-details">
|
||||||
|
<div><dt>IBAN:</dt><dd><button class="copy-iban" type="button" data-iban="DE04870958245044385904" title="IBAN kopieren" aria-label="IBAN DE04 8709 5824 5044 3859 04 kopieren">DE04 8709 5824 5044 3859 04</button></dd></div>
|
||||||
|
<div><dt>BIC:</dt><dd>GENODEF1PL1</dd></div>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div class="paypal">
|
||||||
|
<a class="qr-link" href="https://paypal.me/buchundbohne" aria-label="Buch & Bohne über PayPal unterstützen">
|
||||||
|
<img src="./assets/paypal-qr.png" alt="PayPal-QR-Code für Buch & Bohne" width="468" height="469">
|
||||||
|
</a>
|
||||||
|
<a class="paypal-address" href="https://paypal.me/buchundbohne"><span class="label">paypal.me</span>/buchundbohne</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<p class="visually-hidden" id="copy-status" role="status" aria-live="polite"></p>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "buch-und-bohne",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "buch-und-bohne",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.11"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"name": "buch-und-bohne",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"description": "Buch & Bohne e. V. – Buchladen und Lesecafé in Oelsnitz",
|
||||||
|
"scripts": {"build": "node scripts/build.mjs"},
|
||||||
|
"engines": {"node": ">=20.11"}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# For standalone hosting, serve this file at the origin's /robots.txt.
|
||||||
|
# The showcase site is in a subdirectory; its crawling policy is set by the host.
|
||||||
|
User-agent: *
|
||||||
|
Allow: /2608_BuB/
|
||||||
|
|
||||||
|
Sitemap: https://showcase.andrefiedler.de/2608_BuB/sitemap.xml
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { cp, mkdir, rm } from 'node:fs/promises';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
const root = new URL('../', import.meta.url);
|
||||||
|
const output = new URL('dist/', root);
|
||||||
|
const publicFiles = ['index.html', 'assets', 'favicon.ico', 'favicon.svg', 'sitemap.xml', 'robots.txt', 'site.webmanifest'];
|
||||||
|
|
||||||
|
await rm(output, { recursive: true, force: true });
|
||||||
|
await mkdir(output, { recursive: true });
|
||||||
|
for (const filename of publicFiles) {
|
||||||
|
await cp(new URL(filename, root), new URL(filename, output), { recursive: true });
|
||||||
|
}
|
||||||
|
console.log(`Static site built at ${fileURLToPath(output)}`);
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Derive web artwork from the supplied PDF; never redraw the brand assets.
|
||||||
|
|
||||||
|
Development only: uv run --with pymupdf --with pillow --with 'fonttools[woff]'
|
||||||
|
scripts/prepare-assets.py. Generated assets are committed; deployment needs only Node.
|
||||||
|
"""
|
||||||
|
from copy import deepcopy
|
||||||
|
from io import BytesIO
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import urllib.request
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from zipfile import ZipFile
|
||||||
|
|
||||||
|
import pymupdf
|
||||||
|
from PIL import Image
|
||||||
|
from fontTools import subset
|
||||||
|
from fontTools.ttLib import TTFont
|
||||||
|
from fontTools.varLib.instancer import instantiateVariableFont
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
ASSETS = ROOT / 'assets'
|
||||||
|
FONTS = ASSETS / 'fonts'
|
||||||
|
TMP = ROOT / 'tmp' / 'assets'
|
||||||
|
for directory in [ASSETS, FONTS, TMP]:
|
||||||
|
directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
SVG = 'http://www.w3.org/2000/svg'
|
||||||
|
XLINK = 'http://www.w3.org/1999/xlink'
|
||||||
|
ET.register_namespace('', SVG)
|
||||||
|
ET.register_namespace('xlink', XLINK)
|
||||||
|
pdf = pymupdf.open(ROOT / 'design/2608_BuB_website_baustelle.pdf')
|
||||||
|
page = pdf[0]
|
||||||
|
source = ET.fromstring(page.get_svg_image(text_as_path=True))
|
||||||
|
definitions = {element.get('id'): element for element in source.iter() if element.get('id')}
|
||||||
|
|
||||||
|
|
||||||
|
def artwork(elements, viewbox):
|
||||||
|
root = ET.Element(f'{{{SVG}}}svg', {'viewBox': ' '.join(map(str, viewbox))})
|
||||||
|
defs = ET.SubElement(root, f'{{{SVG}}}defs')
|
||||||
|
required = set()
|
||||||
|
|
||||||
|
def dependencies(element):
|
||||||
|
text = ET.tostring(element, encoding='unicode')
|
||||||
|
refs = re.findall(r'url\(#([^)]*)\)', text)
|
||||||
|
refs += re.findall(r'(?:xlink:)?href="#([^"]*)"', text)
|
||||||
|
for ref in refs:
|
||||||
|
if ref not in required:
|
||||||
|
required.add(ref)
|
||||||
|
dependencies(definitions[ref])
|
||||||
|
|
||||||
|
for element in elements:
|
||||||
|
dependencies(element)
|
||||||
|
for key, value in definitions.items():
|
||||||
|
if key in required:
|
||||||
|
defs.append(deepcopy(value))
|
||||||
|
root.extend(deepcopy(element) for element in elements)
|
||||||
|
return ET.tostring(root, encoding='unicode')
|
||||||
|
|
||||||
|
|
||||||
|
def raster(svg, width):
|
||||||
|
document = pymupdf.open(stream=svg.encode(), filetype='svg')
|
||||||
|
vector = pymupdf.open('pdf', document.convert_to_pdf())
|
||||||
|
pix = vector[0].get_pixmap(matrix=pymupdf.Matrix(width / vector[0].rect.width,
|
||||||
|
width / vector[0].rect.width), alpha=True)
|
||||||
|
return Image.open(BytesIO(pix.tobytes('png')))
|
||||||
|
|
||||||
|
|
||||||
|
# These drawing groups are verified against the supplied one-page PDF.
|
||||||
|
# The print export flattens photos, tint and tape shadows into clipped tiles.
|
||||||
|
# Remove only text, wholly enclosed logo/brush vectors, and the QR resource.
|
||||||
|
# Poppler preserves the original print color conversion and clipping exactly.
|
||||||
|
assert len(source[50]) == 6 and source[504].get('data-text') == 'W'
|
||||||
|
background_pdf = pymupdf.open(ROOT / 'design/2608_BuB_website_baustelle.pdf')
|
||||||
|
background_page = background_pdf[0]
|
||||||
|
background_page.add_redact_annot(background_page.rect, fill=False, cross_out=False)
|
||||||
|
background_page.apply_redactions(images=0, graphics=0, text=0)
|
||||||
|
for bounds in [(506, 141, 694, 290), (363, 435, 819, 485)]:
|
||||||
|
background_page.add_redact_annot(pymupdf.Rect(*bounds), fill=False, cross_out=False)
|
||||||
|
background_page.apply_redactions(images=0, graphics=1, text=1)
|
||||||
|
background_page.delete_image(48)
|
||||||
|
background_pdf.save(TMP / 'background.pdf')
|
||||||
|
subprocess.run(['pdftoppm', '-scale-to', '2400', '-singlefile', '-png',
|
||||||
|
str(TMP / 'background.pdf'), str(TMP / 'background')], check=True)
|
||||||
|
background = Image.open(TMP / 'background.png').convert('RGB')
|
||||||
|
for width in [1200, 2400]:
|
||||||
|
background.resize((width, width * 3 // 4), Image.Resampling.LANCZOS).save(
|
||||||
|
ASSETS / f'background-{width}.webp', quality=91, method=6)
|
||||||
|
|
||||||
|
# On tall screens the photo fills the page and the tape stays above the logo.
|
||||||
|
background.crop((0, 340, 2400, 1800)).resize((1200, 730), Image.Resampling.LANCZOS).save(
|
||||||
|
ASSETS / 'background-mobile.webp', quality=89, method=6)
|
||||||
|
tape = artwork([*list(source)[12:24], *list(source)[41:50]], (0, 0, 1200, 254))
|
||||||
|
tape = tape.replace('#fdc200', '#fbbb0c').replace('#020102', '#0c0c0c')
|
||||||
|
(ASSETS / 'construction-tape.svg').write_text(tape)
|
||||||
|
|
||||||
|
logo_paths = list(source[50])
|
||||||
|
logo = artwork(logo_paths, (507.62, 142, 184.76, 146.67))
|
||||||
|
(ASSETS / 'logo.svg').write_text(logo)
|
||||||
|
heading_glyphs = [element for element in source
|
||||||
|
if element.get(f'{{{XLINK}}}href', '').startswith('#font_63_')]
|
||||||
|
# Match the PDF's sRGB print rendering, as used for the photographic backdrop.
|
||||||
|
for element in source[503].iter():
|
||||||
|
if element.get('fill'):
|
||||||
|
element.set('fill', '#ef3a57')
|
||||||
|
heading = artwork([source[503], *heading_glyphs], (363.77, 435.92, 454.02, 47.90))
|
||||||
|
(ASSETS / 'support-heading.svg').write_text(heading)
|
||||||
|
|
||||||
|
qr = pdf.extract_image(48)
|
||||||
|
Image.open(BytesIO(qr['image'])).convert('RGB').quantize(colors=64).save(ASSETS / 'paypal-qr.png', optimize=True)
|
||||||
|
|
||||||
|
mark = artwork(logo_paths[:4], (600, 136, 99, 94))
|
||||||
|
mark_root = ET.fromstring(mark)
|
||||||
|
mark_root.set('x', '12')
|
||||||
|
mark_root.set('y', '12')
|
||||||
|
mark_root.set('width', '104')
|
||||||
|
mark_root.set('height', '104')
|
||||||
|
icon = ET.Element(f'{{{SVG}}}svg', {'viewBox': '0 0 128 128'})
|
||||||
|
ET.SubElement(icon, f'{{{SVG}}}rect', {'width': '128', 'height': '128', 'rx': '20', 'fill': '#982249'})
|
||||||
|
icon.append(mark_root)
|
||||||
|
icon_svg = ET.tostring(icon, encoding='unicode')
|
||||||
|
(ROOT / 'favicon.svg').write_text(icon_svg)
|
||||||
|
icon_image = raster(icon_svg, 512)
|
||||||
|
for filename, size in [('apple-touch-icon.png', 180), ('icon-192.png', 192), ('icon-512.png', 512)]:
|
||||||
|
icon_image.resize((size, size), Image.Resampling.LANCZOS).save(ASSETS / filename, optimize=True)
|
||||||
|
icon_image.save(ROOT / 'favicon.ico', sizes=[(16, 16), (32, 32), (48, 48)])
|
||||||
|
|
||||||
|
preview = page.get_pixmap(clip=pymupdf.Rect(0, 100, 1200, 730), alpha=False)
|
||||||
|
Image.open(BytesIO(preview.tobytes('png'))).save(ASSETS / 'social-preview.jpg', quality=90, optimize=True)
|
||||||
|
|
||||||
|
archive = ROOT / 'tmp/fonts/Roboto_v3.015.zip'
|
||||||
|
archive.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
if not archive.exists():
|
||||||
|
urllib.request.urlretrieve('https://github.com/googlefonts/roboto-3-classic/releases/download/v3.015/Roboto_v3.015.zip', archive)
|
||||||
|
with ZipFile(archive) as zipped:
|
||||||
|
for name, filename in [('Roboto', 'roboto-latin.woff2'), ('Roboto-Italic', 'roboto-italic-latin.woff2')]:
|
||||||
|
font = TTFont(BytesIO(zipped.read(f'web/split/{name}[wdth,wght].ttf')))
|
||||||
|
options = subset.Options()
|
||||||
|
options.flavor = 'woff2'
|
||||||
|
subsetter = subset.Subsetter(options=options)
|
||||||
|
subsetter.populate(unicodes=[*range(0x20, 0x100), *range(0x2000, 0x2070), 0x20AC, 0xFFFD])
|
||||||
|
subsetter.subset(font)
|
||||||
|
font = instantiateVariableFont(font, {'wdth': 100, 'wght': (400, 700)}, inplace=True)
|
||||||
|
font.flavor = 'woff2'
|
||||||
|
font.save(FONTS / filename)
|
||||||
|
urllib.request.urlretrieve('https://raw.githubusercontent.com/googlefonts/roboto-3-classic/v3.015/OFL.txt', FONTS / 'OFL.txt')
|
||||||
|
license_file = FONTS / 'OFL.txt'
|
||||||
|
license_file.write_text('\n'.join(line.rstrip() for line in license_file.read_text().splitlines()) + '\n')
|
||||||
|
print('Prepared original artwork, QR code, logo icons and local Roboto 3.015 fonts.')
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"publish": "dist"
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"id": "/2608_BuB/",
|
||||||
|
"name": "Buch & Bohne e. V. – Buchladen & Lesecafé",
|
||||||
|
"short_name": "Buch & Bohne",
|
||||||
|
"description": "Buchladen und Lesecafé am Markt 5 in Oelsnitz.",
|
||||||
|
"lang": "de",
|
||||||
|
"dir": "ltr",
|
||||||
|
"start_url": "./",
|
||||||
|
"scope": "./",
|
||||||
|
"display": "browser",
|
||||||
|
"background_color": "#982249",
|
||||||
|
"theme_color": "#982249",
|
||||||
|
"icons": [
|
||||||
|
{"src": "./assets/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any"},
|
||||||
|
{"src": "./assets/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any"}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
<url>
|
||||||
|
<loc>https://showcase.andrefiedler.de/2608_BuB/</loc>
|
||||||
|
<lastmod>2026-09-07</lastmod>
|
||||||
|
</url>
|
||||||
|
</urlset>
|
||||||