Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9693dfd24 |
@@ -1,8 +0,0 @@
|
||||
.git
|
||||
.gitignore
|
||||
docker-compose.yml
|
||||
docker-compose.registry.yml
|
||||
docker-compose.traefik.yml
|
||||
id.env
|
||||
scripts/publish-image.sh
|
||||
README.md
|
||||
@@ -1,21 +0,0 @@
|
||||
[*.{css,scss,less,js,json,ts,sass,html,hbs,mustache,phtml,html.twig,md,yml}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[site/templates/**.php]
|
||||
indent_size = 2
|
||||
|
||||
[site/snippets/**.php]
|
||||
indent_size = 2
|
||||
|
||||
[package.json,.{babelrc,editorconfig,eslintrc,lintstagedrc,stylelintrc}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
@@ -1,3 +0,0 @@
|
||||
# git
|
||||
.gitattributes export-ignore
|
||||
.github export-ignore
|
||||
@@ -1,51 +1,30 @@
|
||||
# System files
|
||||
# ------------
|
||||
# ---> WebMethods
|
||||
**/IntegrationServer/datastore/
|
||||
**/IntegrationServer/db/
|
||||
**/IntegrationServer/DocumentStore/
|
||||
**/IntegrationServer/lib/
|
||||
**/IntegrationServer/logs/
|
||||
**/IntegrationServer/replicate/
|
||||
**/IntegrationServer/sdk/
|
||||
**/IntegrationServer/support/
|
||||
**/IntegrationServer/update/
|
||||
**/IntegrationServer/userFtpRoot/
|
||||
**/IntegrationServer/web/
|
||||
**/IntegrationServer/WmRepository4/
|
||||
**/IntegrationServer/XAStore/
|
||||
**/IntegrationServer/packages/Wm*/
|
||||
|
||||
Icon
|
||||
.DS_Store
|
||||
# ---> JDeveloper
|
||||
# default application storage directory used by the IDE Performance Cache feature
|
||||
.data/
|
||||
|
||||
# Temporary files
|
||||
# ---------------
|
||||
# used for ADF styles caching
|
||||
temp/
|
||||
|
||||
/media/*
|
||||
!/media/index.html
|
||||
# default output directories
|
||||
classes/
|
||||
deploy/
|
||||
javadoc/
|
||||
|
||||
# Lock files
|
||||
# ---------------
|
||||
|
||||
.lock
|
||||
|
||||
# Editors
|
||||
# (sensitive workspace files)
|
||||
# ---------------------------
|
||||
*.sublime-workspace
|
||||
/.vscode
|
||||
/.idea
|
||||
|
||||
# -------------SECURITY-------------
|
||||
# NEVER publish these files via Git!
|
||||
# -------------SECURITY-------------
|
||||
|
||||
# Cache Files
|
||||
# ---------------
|
||||
|
||||
/site/cache/*
|
||||
!/site/cache/index.html
|
||||
|
||||
# Accounts
|
||||
# ---------------
|
||||
|
||||
/site/accounts/*
|
||||
!/site/accounts/index.html
|
||||
|
||||
# Sessions
|
||||
# ---------------
|
||||
|
||||
/site/sessions/*
|
||||
!/site/sessions/index.html
|
||||
|
||||
# License
|
||||
# ---------------
|
||||
|
||||
/site/config/.license
|
||||
/site/config/config.starterkit.test.php
|
||||
# lock file, a part of Oracle Credential Store Framework
|
||||
cwallet.sso.lck
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
# Kirby .htaccess
|
||||
# revision 2023-07-22
|
||||
|
||||
# rewrite rules
|
||||
<IfModule mod_rewrite.c>
|
||||
|
||||
# enable awesome urls. i.e.:
|
||||
# http://yourdomain.com/about-us/team
|
||||
RewriteEngine on
|
||||
|
||||
# make sure to set the RewriteBase correctly
|
||||
# if you are running the site in a subfolder;
|
||||
# otherwise links or the entire site will break.
|
||||
#
|
||||
# If your homepage is http://yourdomain.com/mysite,
|
||||
# set the RewriteBase to:
|
||||
#
|
||||
# RewriteBase /mysite
|
||||
|
||||
# In some environments it's necessary to
|
||||
# set the RewriteBase to:
|
||||
#
|
||||
# RewriteBase /
|
||||
|
||||
# block files and folders beginning with a dot, such as .git
|
||||
# except for the .well-known folder, which is used for Let's Encrypt and security.txt
|
||||
RewriteRule (^|/)\.(?!well-known\/) index.php [L]
|
||||
|
||||
# block all files in the content folder from being accessed directly
|
||||
RewriteRule ^content/(.*) index.php [L]
|
||||
|
||||
# block all files in the site folder from being accessed directly
|
||||
RewriteRule ^site/(.*) index.php [L]
|
||||
|
||||
# block direct access to Kirby and the Panel sources
|
||||
RewriteRule ^kirby/(.*) index.php [L]
|
||||
|
||||
# make site links work
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.*) index.php [L]
|
||||
|
||||
</IfModule>
|
||||
|
||||
# pass the Authorization header to PHP
|
||||
SetEnvIf Authorization "(.+)" HTTP_AUTHORIZATION=$1
|
||||
|
||||
# compress text file responses
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/plain
|
||||
AddOutputFilterByType DEFLATE text/html
|
||||
AddOutputFilterByType DEFLATE text/css
|
||||
AddOutputFilterByType DEFLATE text/javascript
|
||||
AddOutputFilterByType DEFLATE application/json
|
||||
AddOutputFilterByType DEFLATE application/javascript
|
||||
AddOutputFilterByType DEFLATE application/x-javascript
|
||||
</IfModule>
|
||||
|
||||
# set security headers in all responses
|
||||
<IfModule mod_headers.c>
|
||||
|
||||
# serve files as plain text if the actual content type is not known
|
||||
# (hardens against attacks from malicious file uploads)
|
||||
Header set Content-Type "text/plain" "expr=-z %{CONTENT_TYPE}"
|
||||
Header set X-Content-Type-Options "nosniff"
|
||||
|
||||
</IfModule>
|
||||
@@ -1,57 +0,0 @@
|
||||
# Use latest official Ubuntu image
|
||||
FROM ubuntu:latest
|
||||
|
||||
# Set timezone
|
||||
ENV TZ=Europe/Berlin
|
||||
|
||||
# Configure timezone data during build
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
# Avoid interactive prompts during apt install
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install Apache, PHP and required extensions
|
||||
RUN apt-get update && apt-get install -y \
|
||||
apache2 \
|
||||
apache2-utils \
|
||||
ca-certificates \
|
||||
php \
|
||||
libapache2-mod-php \
|
||||
php-curl \
|
||||
php-dom \
|
||||
php-gd \
|
||||
php-intl \
|
||||
php-json \
|
||||
php-mbstring \
|
||||
php-xml \
|
||||
php-zip && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Ensure shared group ownership for collaborative editing
|
||||
RUN groupadd -g 1111 kirbygroup && usermod -aG kirbygroup www-data
|
||||
|
||||
# Provide Apache vhost configuration and entrypoint
|
||||
COPY default.conf /etc/apache2/sites-available/000-default.conf
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
# Remove default Apache placeholder page
|
||||
RUN rm -rf /var/www/html/*
|
||||
|
||||
# Copy project into the image
|
||||
COPY --chown=www-data:kirbygroup . /var/www/html
|
||||
|
||||
# Enable required Apache modules
|
||||
RUN a2enmod headers rewrite
|
||||
|
||||
# Ensure collaborative permissions at runtime
|
||||
RUN chmod -R g+rw /var/www/html && find /var/www/html -type d -exec chmod g+xs {} \;
|
||||
|
||||
# Expose web port
|
||||
EXPOSE 80
|
||||
|
||||
# Allow UID remapping before Apache starts
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
|
||||
# Start Apache in foreground
|
||||
CMD ["/usr/sbin/apache2ctl", "-DFOREGROUND"]
|
||||
@@ -1,55 +0,0 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
REGISTRY_HOST = 'gitea.mindboost.team'
|
||||
IMAGE_NAME = 'interkollektives/lichterei-web'
|
||||
IMAGE_TAG = '0.0.1'
|
||||
IMAGE_REF = "${REGISTRY_HOST}/${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build & Push image') {
|
||||
steps {
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: 'gitea-container-registry',
|
||||
usernameVariable: 'REGISTRY_USER',
|
||||
passwordVariable: 'REGISTRY_PASSWORD'
|
||||
)]) {
|
||||
sh """
|
||||
if ! docker buildx inspect jenkins-builder >/dev/null 2>&1; then
|
||||
docker buildx create --name jenkins-builder --use
|
||||
else
|
||||
docker buildx use jenkins-builder
|
||||
fi
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
echo "${REGISTRY_PASSWORD}" | docker login ${REGISTRY_HOST} \
|
||||
--username "${REGISTRY_USER}" --password-stdin
|
||||
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--file Dockerfile \
|
||||
--tag ${IMAGE_REF} \
|
||||
--push \
|
||||
.
|
||||
|
||||
docker logout ${REGISTRY_HOST}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
sh 'docker image prune --force'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 interkollektives
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,56 +1,3 @@
|
||||
# Lichterei Web – Kirby Projekt
|
||||
# lichterei-web
|
||||
|
||||
Dieses Repository bündelt die Kirby-Installation sowie die Docker-Infrastruktur, damit du das Projekt lokal ausprobieren und im Server-Setup mit Traefik deployen kannst.
|
||||
|
||||
## Voraussetzungen
|
||||
- Docker Engine ≥ 20.10 und `docker compose`
|
||||
- Optional: Composer, falls du Abhängigkeiten aktualisieren möchtest
|
||||
- Passe vor dem ersten Start den Wert `USERID` in `id.env` an deinen lokalen Benutzer an – so vermeidest du Rechteprobleme beim Schreiben ins gemountete Volume.
|
||||
|
||||
## Lokale Ausführung
|
||||
1. `USERID` in `id.env` prüfen/anpassen (`id -u` liefert deinen Wert).
|
||||
2. Container starten:
|
||||
```bash
|
||||
docker compose up --build
|
||||
```
|
||||
3. Die Seite ist anschließend unter http://localhost:8080 erreichbar, das Kirby Panel unter http://localhost:8080/panel.
|
||||
|
||||
Mit `docker compose down` stoppst du die Umgebung wieder. Inhalte bleiben erhalten, da der Projektordner als Volume eingebunden ist.
|
||||
|
||||
## Deployment mit Traefik
|
||||
1. Domain, Router- und Zertifikatsnamen in `docker-compose.traefik.yml` anpassen.
|
||||
2. Sicherstellen, dass das externe Netzwerk `proxy` existiert (`docker network create proxy`).
|
||||
3. Deployment starten:
|
||||
```bash
|
||||
docker compose \
|
||||
-f docker-compose.yml \
|
||||
-f docker-compose.traefik.yml \
|
||||
up -d
|
||||
```
|
||||
Passe bei Bedarf den Volume-Eintrag in `docker-compose.yml` an (z. B. benanntes Volume oder separater Persistenzpfad).
|
||||
4. Für den Registry-Workflow steht `scripts/publish-image.sh` bereit. Das Skript baut das Image aus dem aktuellen Stand und pusht es zum konfigurierten Registry-Host.
|
||||
|
||||
## Nutzung eines Registry-Images
|
||||
- Setze vor dem Start die Umgebungsvariable `KIRBY_IMAGE` auf das exakte Image samt Tag oder Digest, z. B.:
|
||||
```bash
|
||||
export KIRBY_IMAGE=gitea.mindboost.team/interkollektives/lichterei-web:0.0.1
|
||||
```
|
||||
Mit `docker image ls gitea.mindboost.team/interkollektives/lichterei-web` siehst du, welche Tags lokal vorhanden sind. Fehlt der gewünschte Tag, kannst du ihn vergeben: `docker tag <IMAGE_ID> gitea.mindboost.team/...:<tag>`.
|
||||
- Container aus Registry starten:
|
||||
```bash
|
||||
docker compose -f docker-compose.registry.yml up -d
|
||||
```
|
||||
`--build` wird hier nicht benötigt, da keine lokale Build-Definition verwendet wird.
|
||||
- Falls du das Image aktualisierst, entferne das benannte Volume vorher (`docker compose down -v`), damit die neuen Dateien aus dem Image erneut in `/var/www/html` kopiert werden.
|
||||
- Kombination mit Traefik ist ebenfalls möglich:
|
||||
```bash
|
||||
docker compose -f docker-compose.registry.yml -f docker-compose.traefik.yml up -d
|
||||
```
|
||||
|
||||
## Contribution Guidelines
|
||||
- Forken oder Branch erstellen, bevor du Änderungen beginnst.
|
||||
- Lokal mit `docker compose up` arbeiten oder – falls du ohne Container entwickeln willst – `composer install` ausführen.
|
||||
- Bitte prüfe, ob deine Änderungen im Frontend sichtbar funktionieren und keine PHP-Fehler im Log landen.
|
||||
- Pull Request eröffnen und kurz beschreiben, was angepasst wurde und wie getestet wurde.
|
||||
|
||||
Vielen Dank fürs Mitmachen! Bei Fragen melde dich einfach per Issue oder direkt im Team-Chat.
|
||||
Dies ist die offizielle Webseite der Lichterei.
|
||||
@@ -1,340 +0,0 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap');
|
||||
|
||||
/* ===== CSS Variables ===== */
|
||||
:root {
|
||||
--padding: 1.5rem;
|
||||
--color-black: #000;
|
||||
--color-white: #fff;
|
||||
--color-grey: #777;
|
||||
--color-light: #efefef;
|
||||
--color-text: #e8f4ff;
|
||||
--color-text-grey: #cfd9e4;
|
||||
--color-background: var(--color-white);
|
||||
--color-code-light-grey: #cacbd1;
|
||||
--color-code-comment: #a9aaad;
|
||||
--color-code-white: #c5c9c6;
|
||||
--color-code-red: #d16464;
|
||||
--color-code-orange: #de935f;
|
||||
--color-code-yellow: #f0c674;
|
||||
--color-code-green: #a7bd68;
|
||||
--color-code-aqua: #8abeb7;
|
||||
--color-code-blue: #7e9abf;
|
||||
--color-code-purple: #b294bb;
|
||||
--font-family-sans: 'Poppins', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
--font-family-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
/* ===== Background overlay ===== */
|
||||
body {
|
||||
font-family: var(--font-family-sans);
|
||||
color: var(--color-text);
|
||||
background: none;
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
z-index: 0;
|
||||
}
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 320vmax;
|
||||
height: 320vmax;
|
||||
background: linear-gradient(135deg, #3f0e00, #a63b00, #ffbe6e);
|
||||
z-index: -1;
|
||||
animation: rotate-gradient 60s linear infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
.is-blackout body::before {
|
||||
animation: none;
|
||||
background: #000;
|
||||
}
|
||||
.blackout-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
color: #fff;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
z-index: 100;
|
||||
font-size: 2rem;
|
||||
letter-spacing: 0.2em;
|
||||
pointer-events: none;
|
||||
}
|
||||
.is-blackout .blackout-overlay {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* ===== Magnetic Menu (improved) ===== */
|
||||
.magnetic-menu {
|
||||
min-height: 70vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4rem var(--padding) 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
.magnetic-menu__inner {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 2.5rem;
|
||||
width: min(60rem, 100%);
|
||||
}
|
||||
.magnetic-menu__item {
|
||||
width: clamp(8rem, 18vw, 12rem);
|
||||
flex: 0 0 auto;
|
||||
aspect-ratio: 1 / 1;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
text-decoration: none;
|
||||
color: var(--color-text);
|
||||
transition: transform 200ms ease-out;
|
||||
will-change: transform;
|
||||
cursor: pointer;
|
||||
}
|
||||
.magnetic-menu__item:hover {
|
||||
transform: scale(1.1) rotate(5deg);
|
||||
}
|
||||
.magnetic-menu__image {
|
||||
width: 62%;
|
||||
aspect-ratio: 1 / 1;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.magnetic-menu__image img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
.magnetic-menu__circle {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
.magnetic-menu__circle text {
|
||||
font-size: clamp(0.55rem, 1.6vw, 0.75rem);
|
||||
letter-spacing: 0.4em;
|
||||
text-transform: uppercase;
|
||||
fill: var(--color-text);
|
||||
font-weight: 600;
|
||||
}
|
||||
.magnetic-menu__item.is-placeholder {
|
||||
pointer-events: none;
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
/* ===== NEW: Hover text on magnetic menu items ===== */
|
||||
.magnetic-menu__item::before {
|
||||
content: attr(data-lamp-desc);
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 200ms ease;
|
||||
pointer-events: none;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: var(--color-white);
|
||||
font-size: clamp(0.4rem, 1.2vw, 0.5rem);
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
z-index: 10;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.magnetic-menu__item:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* ===== Footer magnet ===== */
|
||||
.footer-magnet {
|
||||
display: inline-block;
|
||||
transition: transform 280ms cubic-bezier(.25, .8, .25, 1);
|
||||
will-change: transform;
|
||||
user-select: none;
|
||||
}
|
||||
.footer-dim-image {
|
||||
display: block;
|
||||
margin-top: 1rem;
|
||||
filter: brightness(1);
|
||||
transition: filter 250ms ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ===== Responsive ===== */
|
||||
@media (max-width: 800px) {
|
||||
.magnetic-menu {
|
||||
min-height: auto;
|
||||
padding: 3rem var(--padding) 1rem;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.magnetic-menu__inner {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
.magnetic-menu__item {
|
||||
flex: 1 1 calc((100% / 3) - 1rem);
|
||||
max-width: none;
|
||||
width: calc((100% / 3) - 1rem);
|
||||
}
|
||||
.has-top-menu .magnetic-menu__inner {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
@media (max-width: 520px) {
|
||||
.magnetic-menu {
|
||||
min-height: auto;
|
||||
padding: 1rem var(--padding) 0.5rem;
|
||||
}
|
||||
.magnetic-menu__inner {
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.magnetic-menu__item {
|
||||
flex: 1 1 calc((100% / 3) - 0.5rem);
|
||||
width: calc((100% / 3) - 0.5rem);
|
||||
}
|
||||
.magnetic-menu__circle text {
|
||||
font-size: clamp(0.45rem, 3vw, 0.6rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== Top menu mode ===== */
|
||||
.has-top-menu .magnetic-menu {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
min-height: auto;
|
||||
justify-content: center;
|
||||
padding: 1rem 0 0.5rem;
|
||||
}
|
||||
.has-top-menu .magnetic-menu__inner {
|
||||
justify-content: center;
|
||||
max-width: 70rem;
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--padding);
|
||||
}
|
||||
.has-top-menu .main {
|
||||
padding-top: calc(var(--padding) + 6rem);
|
||||
}
|
||||
|
||||
/* ===== Main layout ===== */
|
||||
.main {
|
||||
max-width: 70rem;
|
||||
margin: 0 auto;
|
||||
padding: var(--padding);
|
||||
padding-bottom: calc(8rem + var(--padding));
|
||||
}
|
||||
|
||||
/* ===== Base elements ===== */
|
||||
li { list-style: none; }
|
||||
a { color: currentColor; text-decoration: none; }
|
||||
button { font: inherit; background: none; border: 0; color: currentColor; cursor: pointer; }
|
||||
strong, b { font-weight: 600; }
|
||||
small { font-size: inherit; color: var(--color-text-grey); }
|
||||
|
||||
/* ===== Background helpers ===== */
|
||||
.bg-light { background-color: var(--color-light); }
|
||||
.color-grey { color: var(--color-text-grey); }
|
||||
|
||||
/* ===== Header ===== */
|
||||
.header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
margin-right: -1rem;
|
||||
margin-left: -1rem;
|
||||
margin-bottom: 6rem;
|
||||
}
|
||||
.logo {
|
||||
padding: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* ===== Menu ===== */
|
||||
.menu { display: flex; }
|
||||
.menu a { padding: 1rem; display: block; }
|
||||
.menu a[aria-current] { text-decoration: underline; }
|
||||
|
||||
/* ===== Social ===== */
|
||||
.social { display: flex; padding: 0 .5rem; }
|
||||
.social a { padding: 1rem .5rem; }
|
||||
|
||||
/* ===== Sections ===== */
|
||||
.section { padding: 3rem 0; }
|
||||
|
||||
/* ===== Grid ===== */
|
||||
.grid { --columns: 12; --gutter: 3rem; display: grid; grid-gap: var(--gutter); grid-template-columns: 1fr; }
|
||||
.grid > .column { margin-bottom: var(--gutter); }
|
||||
|
||||
/* ===== Auto-grid ===== */
|
||||
.autogrid { --gutter: 3rem; --min: 10rem; display: grid; grid-gap: var(--gutter); grid-template-columns: repeat(auto-fit, minmax(var(--min), 1fr)); grid-auto-flow: dense; }
|
||||
|
||||
/* ===== Headings ===== */
|
||||
h1, h2, h3, h4, h5, h6 { font-size: inherit; font-weight: inherit; line-height: inherit; }
|
||||
|
||||
/* ===== Text ===== */
|
||||
.text { line-height: 1.5em; }
|
||||
.text a { text-decoration: underline; }
|
||||
.text :first-child { margin-top: 0; }
|
||||
.text :last-child { margin-bottom: 0; }
|
||||
.text p, .text ul, .text ol { margin-bottom: 1.5rem; }
|
||||
.text ul, .text ol { margin-left: 1rem; }
|
||||
.text ul p, .text ol p { margin-bottom: 0; }
|
||||
.text ul > li { list-style: disc; }
|
||||
.text ol > li { list-style: decimal; }
|
||||
.text ul ol, .text ul ul, .text ol ul, .text ol ol { margin-bottom: 0; }
|
||||
.text h1, .h1, .intro { font-size: 2rem; margin-bottom: 3rem; line-height: 1.25em; }
|
||||
.text h2, .h2 { font-size: 1.25rem; font-weight: 600; margin-bottom: 1.25rem; }
|
||||
.text h3, .h3 { font-weight: 600; }
|
||||
.text .codeblock { display: grid; }
|
||||
.text code { font-family: var(--font-family-mono); font-size: 1em; background: var(--color-light); padding: 0 .5rem; display: inline-block; color: var(--color-black); }
|
||||
.text pre { margin: 3rem 0; background: var(--color-black); color: var(--color-white); padding: 1.5rem; overflow-x: scroll; overflow-y: hidden; line-height: 1.5rem; }
|
||||
.text pre code { padding: 0; background: none; color: inherit; }
|
||||
|
||||
/* ===== HR & Alignment ===== */
|
||||
hr { border: 0; background: currentColor; height: 2px; width: 1.5rem; margin: 3rem auto; }
|
||||
.align-center { text-align: center; }
|
||||
|
||||
/* ===== Intro ===== */
|
||||
.intro { max-width: 40rem; }
|
||||
.intro *:not(:last-child) { margin-bottom: 1em; }
|
||||
|
||||
/* ===== CTA ===== */
|
||||
.cta {
|
||||
background: var(--color-black);
|
||||
color: var(--color-white);
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
padding: .75rem 1.5rem;
|
||||
border: 4px solid var(--color-white);
|
||||
outline: 2px solid var(--color-black);
|
||||
}
|
||||
|
||||
/* ===== Box ===== */
|
||||
.box {
|
||||
background: var(--color-light);
|
||||
padding: 1.5rem;
|
||||
border: 4px solid var(--color-white);
|
||||
outline: 2px solid var(--color-light);
|
||||
}
|
||||
|
||||
/* ===== Video ===== */
|
||||
.video,
|
||||
@@ -1 +0,0 @@
|
||||
.basicLightbox{position:fixed;display:flex;justify-content:center;align-items:center;top:0;left:0;width:100%;height:100vh;background:rgba(0,0,0,.8);opacity:.01;transition:opacity .4s ease;z-index:1000;will-change:opacity}.basicLightbox--visible{opacity:1}.basicLightbox__placeholder{max-width:100%;-webkit-transform:scale(.9);transform:scale(.9);transition:-webkit-transform .4s ease;transition:transform .4s ease;transition:transform .4s ease,-webkit-transform .4s ease;z-index:1;will-change:transform}.basicLightbox__placeholder>iframe:first-child:last-child,.basicLightbox__placeholder>img:first-child:last-child,.basicLightbox__placeholder>video:first-child:last-child{display:block;position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;max-width:95%;max-height:95%}.basicLightbox__placeholder>iframe:first-child:last-child,.basicLightbox__placeholder>video:first-child:last-child{pointer-events:auto}.basicLightbox__placeholder>img:first-child:last-child,.basicLightbox__placeholder>video:first-child:last-child{width:auto;height:auto}.basicLightbox--iframe .basicLightbox__placeholder,.basicLightbox--img .basicLightbox__placeholder,.basicLightbox--video .basicLightbox__placeholder{width:100%;height:100%;pointer-events:none}.basicLightbox--visible .basicLightbox__placeholder{-webkit-transform:scale(1);transform:scale(1)}
|
||||
@@ -1,136 +0,0 @@
|
||||
/* PrismJS 1.19.0
|
||||
https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+json+markup-templating+php+yaml */
|
||||
/**
|
||||
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
|
||||
* Based on https://github.com/chriskempson/tomorrow-theme
|
||||
* @author Rose Pritchard
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: var(--color-code-white);
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1rem;
|
||||
margin: 0 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* ----- Syntax Highlighting (Prism.js) ------------------------------------ */
|
||||
|
||||
.token.punctuation {
|
||||
color: var(--color-code-light-grey);
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.doctype {
|
||||
color: var(--color-code-comment);
|
||||
}
|
||||
|
||||
.token.tag,
|
||||
.token.markup,
|
||||
.token.variable,
|
||||
.token.this,
|
||||
.token.selector,
|
||||
.token.key,
|
||||
.token.kirbytag-bracket,
|
||||
.token.prolog,
|
||||
.token.delimiter {
|
||||
color: var(--color-code-red);
|
||||
}
|
||||
|
||||
.token.constant,
|
||||
.token.number,
|
||||
.token.boolean,
|
||||
.token.boolean.important,
|
||||
.token.attr-name,
|
||||
.token.kirbytag-attr,
|
||||
.token.kirbytag-name,
|
||||
.token.entity,
|
||||
.token.bold,
|
||||
.token.bold > .punctuation {
|
||||
color: var(--color-code-orange);
|
||||
}
|
||||
|
||||
.token.keyword,
|
||||
.token.italic,
|
||||
.token.italic > .punctuation {
|
||||
color: var(--color-code-purple);
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: var(--color-code-blue);
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.title {
|
||||
color: var(--color-code-aqua);
|
||||
}
|
||||
|
||||
.token.string,
|
||||
.token.attr-value,
|
||||
.token.attr-value .punctuation,
|
||||
.token.list.punctuation {
|
||||
color: var(--color-code-green);
|
||||
}
|
||||
|
||||
.token.scope,
|
||||
.token.class-name,
|
||||
.token.property,
|
||||
.token.url {
|
||||
color: var(--color-code-yellow);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Markdown list bullet.
|
||||
*/
|
||||
.token.title,
|
||||
.token.kirbytag-bracket,
|
||||
.token.list.punctuation /* 1 */ {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.token.title .punctuation {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Markdown bold text
|
||||
*/
|
||||
.token.bold /* 1 */ {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.codeblock {
|
||||
background: var(--color-black);
|
||||
}
|
||||
.codeblock figcaption {
|
||||
color: var(--color-code-white);
|
||||
padding: .5rem 1rem;
|
||||
font-family: var(--font-family-mono);
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
.contact {
|
||||
padding: 3rem;
|
||||
border: 2px solid #000;
|
||||
}
|
||||
.contact .h1 {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
.album-gallery {
|
||||
line-height: 0;
|
||||
columns: 1;
|
||||
column-gap: 1.5rem;
|
||||
}
|
||||
.album-gallery li {
|
||||
display: block;
|
||||
margin-bottom: 1.5rem;
|
||||
break-inside: avoid;
|
||||
}
|
||||
@media screen and (min-width: 60rem) {
|
||||
.album-gallery {
|
||||
columns: 2;
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
.home-grid {
|
||||
display: grid;
|
||||
list-style: none;
|
||||
grid-gap: 1.5rem;
|
||||
line-height: 0;
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
grid-auto-flow: dense;
|
||||
}
|
||||
.home-grid li {
|
||||
position: relative;
|
||||
--cols: 1;
|
||||
--rows: 1;
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
line-height: 0;
|
||||
}
|
||||
.home-grid li:first-child {
|
||||
--cols: 2;
|
||||
--rows: 2;
|
||||
}
|
||||
.home-grid li:nth-child(5) {
|
||||
--cols: 2;
|
||||
}
|
||||
.home-grid li:nth-child(6) {
|
||||
--rows: 2;
|
||||
}
|
||||
.home-grid li:nth-child(7) {
|
||||
--cols: 2;
|
||||
}
|
||||
.home-grid a {
|
||||
display: block;
|
||||
height: 10rem;
|
||||
}
|
||||
.home-grid img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: all .3s;
|
||||
}
|
||||
.home-grid figcaption {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
background: rgba(0,0,0, .7);
|
||||
opacity: 0;
|
||||
transition: opacity .3s;
|
||||
}
|
||||
.home-grid li:hover figcaption {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Medium screens */
|
||||
@media screen and (min-width: 45em) {
|
||||
.home-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
.home-grid li {
|
||||
grid-column-start: span var(--cols);
|
||||
grid-row-start: span var(--rows);
|
||||
}
|
||||
.home-grid a {
|
||||
padding-bottom: 52.65%;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
.note {
|
||||
max-width: 35rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.note-header {
|
||||
padding-top: 3rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
.note-footer {
|
||||
padding: 6rem 0;
|
||||
}
|
||||
.note-date {
|
||||
color: var(--color-text-grey);
|
||||
}
|
||||
.note-tags {
|
||||
display: flex;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
.note-tags li {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
.note-tags a {
|
||||
padding: .5rem 1rem;
|
||||
display: block;
|
||||
background: var(--color-light);
|
||||
}
|
||||
.note-tags a:hover {
|
||||
background: var(--color-black);
|
||||
color: var(--color-white);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><title>Discord</title><path d="M6.552,6.712a.891.891,0,0,0,0,1.776A.852.852,0,0,0,7.368,7.6.847.847,0,0,0,6.552,6.712Zm2.92,0a.891.891,0,1,0,.816.888A.852.852,0,0,0,9.472,6.712Z"/><path d="M13.36,0H2.64A1.644,1.644,0,0,0,1,1.648V12.464a1.644,1.644,0,0,0,1.64,1.648h9.072l-.424-1.48,1.024.952.968.9L15,16V1.648A1.644,1.644,0,0,0,13.36,0ZM10.272,10.448S9.984,10.1,9.744,9.8a2.524,2.524,0,0,0,1.448-.952,4.578,4.578,0,0,1-.92.472,5.265,5.265,0,0,1-1.16.344A5.6,5.6,0,0,1,7.04,9.656a6.716,6.716,0,0,1-1.176-.344,4.683,4.683,0,0,1-.912-.472,2.488,2.488,0,0,0,1.4.944c-.24.3-.536.664-.536.664a2.9,2.9,0,0,1-2.44-1.216A10.713,10.713,0,0,1,4.528,4.568a3.956,3.956,0,0,1,2.248-.84l.08.1a5.4,5.4,0,0,0-2.1,1.048s.176-.1.472-.232a6.008,6.008,0,0,1,1.816-.5.788.788,0,0,1,.136-.016A6.769,6.769,0,0,1,8.792,4.1a6.521,6.521,0,0,1,2.408.768A5.324,5.324,0,0,0,9.208,3.856l.112-.128a3.956,3.956,0,0,1,2.248.84A10.713,10.713,0,0,1,12.72,9.232,2.924,2.924,0,0,1,10.272,10.448Z" /></svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><title>Instagram</title><circle cx="12.145" cy="3.892" r="0.96"/><path d="M8,12c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4S10.206,12,8,12z M8,6C6.897,6,6,6.897,6,8 s0.897,2,2,2s2-0.897,2-2S9.103,6,8,6z"/><path d="M12,16H4c-2.056,0-4-1.944-4-4V4c0-2.056,1.944-4,4-4h8c2.056,0,4,1.944,4,4v8C16,14.056,14.056,16,12,16z M4,2C3.065,2,2,3.065,2,4v8c0,0.953,1.047,2,2,2h8c0.935,0,2-1.065,2-2V4c0-0.935-1.065-2-2-2H4z"/></svg>
|
||||
|
Before Width: | Height: | Size: 524 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><title>Mastodon</title><path d="M14.943 3.935c-.215-1.591-1.612-2.845-3.268-3.088-.28-.041-1.338-.19-3.79-.19h-.019c-2.453 0-2.979.148-3.258.19-1.61.236-3.08 1.363-3.437 2.973-.172.793-.19 1.672-.158 2.478.045 1.157.054 2.311.16 3.463.073.765.2 1.524.382 2.27.339 1.38 1.711 2.53 3.056 2.998 1.44.488 2.988.57 4.472.234.163-.038.325-.081.484-.131.36-.114.783-.241 1.093-.465a.036.036 0 0 0 .015-.027v-1.116a.033.033 0 0 0-.041-.031c-.951.225-1.925.338-2.902.336-1.682 0-2.134-.792-2.264-1.122a3.463 3.463 0 0 1-.196-.884.032.032 0 0 1 .04-.033c.935.224 1.893.337 2.855.336.231 0 .461 0 .693-.006.967-.027 1.986-.076 2.938-.26l.067-.015c1.501-.286 2.93-1.184 3.075-3.458.005-.09.018-.938.018-1.03.001-.316.103-2.24-.015-3.422Zm-2.31 5.674h-1.578V5.772c0-.808-.339-1.22-1.028-1.22-.758 0-1.138.488-1.138 1.45v2.1H7.32v-2.1c0-.962-.38-1.45-1.138-1.45-.686 0-1.029.412-1.03 1.22v3.837H3.577V5.656c0-.808.208-1.45.623-1.926.429-.474.991-.718 1.689-.718.808 0 1.418.308 1.825.924l.393.655.393-.655c.407-.616 1.017-.924 1.823-.924.698 0 1.26.244 1.69.718.415.475.623 1.117.623 1.926l-.002 3.953Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><title>YouTube</title><path d="M15.8 4.8c-.2-1.3-.8-2.2-2.2-2.4C11.4 2 8 2 8 2s-3.4 0-5.6.4C1 2.6.3 3.5.2 4.8 0 6.1 0 8 0 8s0 1.9.2 3.2c.2 1.3.8 2.2 2.2 2.4C4.6 14 8 14 8 14s3.4 0 5.6-.4c1.4-.3 2-1.1 2.2-2.4C16 9.9 16 8 16 8s0-1.9-.2-3.2zM6 11V5l5 3-5 3z"/></svg>
|
||||
|
Before Width: | Height: | Size: 367 B |
@@ -1,154 +0,0 @@
|
||||
// Lightbox
|
||||
Array.from(document.querySelectorAll("[data-lightbox]")).forEach(element => {
|
||||
element.onclick = (e) => {
|
||||
e.preventDefault();
|
||||
basicLightbox.create(`<img src="${element.href}">`).show();
|
||||
};
|
||||
});
|
||||
|
||||
let lastPointerType = "mouse";
|
||||
window.addEventListener("pointerdown", event => {
|
||||
lastPointerType = event.pointerType || "mouse";
|
||||
});
|
||||
|
||||
// Central magnetic menu
|
||||
const menuContainer = document.querySelector("[data-magnetic-menu]");
|
||||
if (menuContainer) {
|
||||
const menuItems = Array.from(menuContainer.querySelectorAll(".magnetic-menu__item"));
|
||||
const hoverRadius = 240;
|
||||
const shiftStrength = 45;
|
||||
const spread = 18;
|
||||
const isHome = document.body.classList.contains("is-home");
|
||||
|
||||
const applySpreadOnly = () => {
|
||||
menuItems.forEach((item, index) => {
|
||||
const neighborSpread = (index - (menuItems.length - 1) / 2) * spread;
|
||||
item.style.transform = `translate(${neighborSpread}px, 0px)`;
|
||||
});
|
||||
};
|
||||
|
||||
const handleMenuPointer = event => {
|
||||
const pointerX = event?.clientX ?? null;
|
||||
const pointerY = event?.clientY ?? null;
|
||||
|
||||
menuItems.forEach((item, index) => {
|
||||
const rect = item.getBoundingClientRect();
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
let offsetX = 0;
|
||||
let offsetY = 0;
|
||||
|
||||
if (pointerX !== null) {
|
||||
const dx = pointerX - centerX;
|
||||
const dy = pointerY - centerY;
|
||||
const distance = Math.hypot(dx, dy);
|
||||
|
||||
if (distance < hoverRadius && distance > 0.001) {
|
||||
const force = 1 - distance / hoverRadius;
|
||||
offsetX = -(dx / distance) * force * shiftStrength;
|
||||
offsetY = -(dy / distance) * force * shiftStrength;
|
||||
}
|
||||
}
|
||||
|
||||
const neighborSpread = (index - (menuItems.length - 1) / 2) * spread;
|
||||
item.style.transform = `translate(${offsetX + neighborSpread}px, ${offsetY}px)`;
|
||||
});
|
||||
};
|
||||
|
||||
menuContainer.addEventListener("pointermove", handleMenuPointer);
|
||||
menuContainer.addEventListener("pointerleave", applySpreadOnly);
|
||||
applySpreadOnly();
|
||||
|
||||
if (isHome) {
|
||||
const pinMenu = () => {
|
||||
document.body.classList.add("has-top-menu");
|
||||
};
|
||||
menuItems.forEach(item => {
|
||||
item.addEventListener("pointerdown", pinMenu, { once: true });
|
||||
item.addEventListener("click", pinMenu, { once: true });
|
||||
item.addEventListener("touchstart", pinMenu, { once: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Footer magnet hover
|
||||
const footer = document.querySelector(".footer");
|
||||
const footerMagnets = footer ? Array.from(footer.querySelectorAll("[data-footer-magnet]")) : [];
|
||||
if (footer && footerMagnets.length) {
|
||||
const radius = 240;
|
||||
const maxOffset = 60;
|
||||
let pointerX = null;
|
||||
let pointerY = null;
|
||||
let rafId = null;
|
||||
|
||||
const updateFooterMagnets = () => {
|
||||
footerMagnets.forEach(item => {
|
||||
if (pointerX === null || pointerY === null) {
|
||||
item.style.transform = "";
|
||||
return;
|
||||
}
|
||||
const rect = item.getBoundingClientRect();
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
const dx = centerX - pointerX;
|
||||
const dy = centerY - pointerY;
|
||||
const distance = Math.hypot(dx, dy);
|
||||
|
||||
if (distance < radius && distance > 0.001) {
|
||||
const force = 1 - distance / radius;
|
||||
const offsetX = (dx / distance) * force * maxOffset;
|
||||
const offsetY = (dy / distance) * force * maxOffset;
|
||||
item.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
|
||||
} else {
|
||||
item.style.transform = "";
|
||||
}
|
||||
});
|
||||
rafId = null;
|
||||
};
|
||||
|
||||
const requestFooterUpdate = () => {
|
||||
if (rafId === null) {
|
||||
rafId = requestAnimationFrame(updateFooterMagnets);
|
||||
}
|
||||
};
|
||||
|
||||
footer.addEventListener("pointermove", event => {
|
||||
pointerX = event.clientX;
|
||||
pointerY = event.clientY;
|
||||
requestFooterUpdate();
|
||||
});
|
||||
|
||||
footer.addEventListener("pointerleave", () => {
|
||||
pointerX = null;
|
||||
pointerY = null;
|
||||
footerMagnets.forEach(item => {
|
||||
item.style.transform = "";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Footer image brightness cycle
|
||||
const footerDimImage = document.querySelector(".footer-dim-image");
|
||||
if (footerDimImage) {
|
||||
const brightnessSteps = [1, 0.75, 0.5, 0.25];
|
||||
let brightnessIndex = Number(footerDimImage.dataset.brightnessIndex || 0);
|
||||
footerDimImage.style.filter = `brightness(${brightnessSteps[brightnessIndex]})`;
|
||||
|
||||
footerDimImage.addEventListener("click", () => {
|
||||
brightnessIndex = (brightnessIndex + 1) % brightnessSteps.length;
|
||||
footerDimImage.dataset.brightnessIndex = String(brightnessIndex);
|
||||
footerDimImage.style.filter = `brightness(${brightnessSteps[brightnessIndex]})`;
|
||||
|
||||
if (!document.body.classList.contains("is-blackout") && Math.random() < 0.15) {
|
||||
document.body.classList.add("is-blackout");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Blackout toggle based on click
|
||||
const blackoutOverlay = document.querySelector("[data-blackout-overlay]");
|
||||
document.addEventListener("pointerdown", () => {
|
||||
if (document.body.classList.contains("is-blackout")) {
|
||||
document.body.classList.remove("is-blackout");
|
||||
}
|
||||
}, true);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).basicLightbox=e()}}(function(){return function i(c,u,a){function s(n,e){if(!u[n]){if(!c[n]){var t="function"==typeof require&&require;if(!e&&t)return t(n,!0);if(l)return l(n,!0);var o=new Error("Cannot find module '"+n+"'");throw o.code="MODULE_NOT_FOUND",o}var r=u[n]={exports:{}};c[n][0].call(r.exports,function(e){return s(c[n][1][e]||e)},r,r.exports,i,c,u,a)}return u[n].exports}for(var l="function"==typeof require&&require,e=0;e<a.length;e++)s(a[e]);return s}({1:[function(e,n,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.create=t.visible=void 0;var u=function(e){var n=1<arguments.length&&void 0!==arguments[1]&&arguments[1],t=document.createElement("div");return t.innerHTML=e.trim(),!0===n?t.children:t.firstChild},a=function(e,n){var t=e.children;return 1===t.length&&t[0].tagName===n},c=function(e){return null!=(e=e||document.querySelector(".basicLightbox"))&&!0===e.ownerDocument.body.contains(e)};t.visible=c;t.create=function(e,o){var r=function(e,n){var t=u('\n\t\t<div class="basicLightbox '.concat(n.className,'">\n\t\t\t<div class="basicLightbox__placeholder" role="dialog"></div>\n\t\t</div>\n\t')),o=t.querySelector(".basicLightbox__placeholder");e.forEach(function(e){return o.appendChild(e)});var r=a(o,"IMG"),i=a(o,"VIDEO"),c=a(o,"IFRAME");return!0===r&&t.classList.add("basicLightbox--img"),!0===i&&t.classList.add("basicLightbox--video"),!0===c&&t.classList.add("basicLightbox--iframe"),t}(e=function(e){var n="string"==typeof e,t=e instanceof HTMLElement==1;if(!1===n&&!1===t)throw new Error("Content must be a DOM element/node or string");return!0===n?Array.from(u(e,!0)):"TEMPLATE"===e.tagName?[e.content.cloneNode(!0)]:Array.from(e.children)}(e),o=function(){var e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};if(null==(e=Object.assign({},e)).closable&&(e.closable=!0),null==e.className&&(e.className=""),null==e.onShow&&(e.onShow=function(){}),null==e.onClose&&(e.onClose=function(){}),"boolean"!=typeof e.closable)throw new Error("Property `closable` must be a boolean");if("string"!=typeof e.className)throw new Error("Property `className` must be a string");if("function"!=typeof e.onShow)throw new Error("Property `onShow` must be a function");if("function"!=typeof e.onClose)throw new Error("Property `onClose` must be a function");return e}(o)),n=function(e){return!1!==o.onClose(i)&&(t=function(){if("function"==typeof e)return e(i)},(n=r).classList.remove("basicLightbox--visible"),setTimeout(function(){return!1===c(n)||n.parentElement.removeChild(n),t()},410),!0);var n,t};!0===o.closable&&r.addEventListener("click",function(e){e.target===r&&n()});var i={element:function(){return r},visible:function(){return c(r)},show:function(e){return!1!==o.onShow(i)&&(n=r,t=function(){if("function"==typeof e)return e(i)},document.body.appendChild(n),setTimeout(function(){requestAnimationFrame(function(){return n.classList.add("basicLightbox--visible"),t()})},10),!0);var n,t},close:n};return i}},{}]},{},[1])(1)});
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"name": "getkirby/starterkit",
|
||||
"description": "Kirby Starterkit",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"kirby",
|
||||
"cms",
|
||||
"starterkit"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Bastian Allgeier",
|
||||
"email": "bastian@getkirby.com",
|
||||
"homepage": "https://getkirby.com"
|
||||
}
|
||||
],
|
||||
"homepage": "https://getkirby.com",
|
||||
"support": {
|
||||
"email": "support@getkirby.com",
|
||||
"issues": "https://github.com/getkirby/starterkit/issues",
|
||||
"forum": "https://forum.getkirby.com",
|
||||
"source": "https://github.com/getkirby/starterkit"
|
||||
},
|
||||
"require": {
|
||||
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
|
||||
"getkirby/cms": "^4.0"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"getkirby/composer-installer": true
|
||||
},
|
||||
"optimize-autoloader": true
|
||||
},
|
||||
"scripts": {
|
||||
"start": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"@php -S localhost:8000 kirby/router.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
Title: Aurora Weave Pendant
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://Jc0l1BA0i5z0QjRf
|
||||
|
||||
----
|
||||
|
||||
Headline: Sculpted orbit for evening rituals
|
||||
|
||||
----
|
||||
|
||||
Subheadline: Hand-braided rattan halo for golden evenings
|
||||
|
||||
----
|
||||
|
||||
Text: <p>Aurora Weave gathers slender rattan strands around a linen core, diffusing light into a gentle dusk that favours story corners and shared tables alike. The woven silhouette casts soft, organic shadows that dance along the walls.</p><p>Each pendant is finished with brushed brass detailing and dim-to-warm LEDs, balancing artisanal tactility with understated technology for living rooms that double as sanctuaries.</p>
|
||||
|
||||
----
|
||||
|
||||
Tags: pendant, woven, living room
|
||||
|
||||
----
|
||||
|
||||
Uuid: v59sIVPYM141Uotu
|
||||
|
Before Width: | Height: | Size: 208 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Aurora Weave pendant scattering honeyed light across oak panels.
|
||||
|
||||
----
|
||||
|
||||
Alt: Aurora Weave pendant lamp in a reading nook
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 2
|
||||
|
||||
----
|
||||
|
||||
Uuid: p6ClztZrkCB1KfLF
|
||||
|
Before Width: | Height: | Size: 130 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Brass canopy detail of Aurora Weave hovering over linen upholstery.
|
||||
|
||||
----
|
||||
|
||||
Alt: Close view of Aurora Weave pendant with layered rattan bands
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 1
|
||||
|
||||
----
|
||||
|
||||
Uuid: mX73tq8jwu6bLxBt
|
||||
|
Before Width: | Height: | Size: 161 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Aurora Weave casting layered shadows that drift like morning mist.
|
||||
|
||||
----
|
||||
|
||||
Alt: Aurora Weave pendant diffusing light through hand-braided rattan
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 3
|
||||
|
||||
----
|
||||
|
||||
Uuid: Jc0l1BA0i5z0QjRf
|
||||
|
Before Width: | Height: | Size: 211 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Evening vignette of Aurora Weave guiding guests toward a lounge alcove.
|
||||
|
||||
----
|
||||
|
||||
Alt: Ambient view of Aurora Weave pendant illuminating a walkway
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 4
|
||||
|
||||
----
|
||||
|
||||
Uuid: 4J6JHoVhngADKZ93
|
||||
|
Before Width: | Height: | Size: 238 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Aurora Weave guiding a late-night return with a mellow amber glow.
|
||||
|
||||
----
|
||||
|
||||
Alt: Aurora Weave pendant shimmering through twilight tones
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 5
|
||||
|
||||
----
|
||||
|
||||
Uuid: Qb0tGC63X1pU3qH1
|
||||
@@ -1,25 +0,0 @@
|
||||
Title: Skylark Halo Pendant
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://9APZDUNsDTbHMMTZ
|
||||
|
||||
----
|
||||
|
||||
Headline: Circular glow that floats like dawn
|
||||
|
||||
----
|
||||
|
||||
Subheadline: Brushed aluminium ring layered with opal diffusers
|
||||
|
||||
----
|
||||
|
||||
Text: <p>Skylark Halo levitates on near-invisible suspension, its twin opal diffusers projecting a soft horizon line. Adjustable co-axial LEDs let you move from sunrise to starlight with a single gesture.</p><p>The pendant thrives above lounge sofas and dining tables, pairing architectural clarity with a weightless presence that keeps conversations in the spotlight.</p>
|
||||
|
||||
----
|
||||
|
||||
Tags: pendant, halo, dimmable
|
||||
|
||||
----
|
||||
|
||||
Uuid: EWQEPJBB2Xyrrrj6
|
||||
|
Before Width: | Height: | Size: 94 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Skylark Halo suspended above a lounge, glowing like a rising moon.
|
||||
|
||||
----
|
||||
|
||||
Alt: Skylark Halo pendant floating with amber outer ring
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 1
|
||||
|
||||
----
|
||||
|
||||
Uuid: kUpBxXRb6As5AI4Q
|
||||
|
Before Width: | Height: | Size: 199 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Diffused inner glow of Skylark Halo reflecting off matte plaster.
|
||||
|
||||
----
|
||||
|
||||
Alt: Close-up of Skylark Halo pendant with dual diffusion rings
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: qQdp74eJyZtSsN04
|
||||
|
Before Width: | Height: | Size: 194 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Skylark Halo washing a vaulted ceiling with soft starlight hues.
|
||||
|
||||
----
|
||||
|
||||
Alt: Skylark Halo pendant illuminating a vaulted ceiling
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 4
|
||||
|
||||
----
|
||||
|
||||
Uuid: 9APZDUNsDTbHMMTZ
|
||||
|
Before Width: | Height: | Size: 210 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Skylark Halo echoing twilight across an open-layout living room.
|
||||
|
||||
----
|
||||
|
||||
Alt: Skylark Halo pendant emitting a gradient of warm and cool light
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 3
|
||||
|
||||
----
|
||||
|
||||
Uuid: QpaDWZ8W1hy2JAsd
|
||||
|
Before Width: | Height: | Size: 251 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Skylark Halo dimmed low to frame a fireside gathering.
|
||||
|
||||
----
|
||||
|
||||
Alt: Skylark Halo pendant glowing softly above lounge seating
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: ofXkD4gdgBOkHBAb
|
||||
@@ -1,25 +0,0 @@
|
||||
Title: Tidefall Floor Lamp
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://Kxk9ITpo07vV6u3e
|
||||
|
||||
----
|
||||
|
||||
Headline: Cascading linen for atmosphere seekers
|
||||
|
||||
----
|
||||
|
||||
Subheadline: Tiered textile shade with ripple dimming
|
||||
|
||||
----
|
||||
|
||||
Text: <p>Tidefall is a sculpted column of cascading linen, layered to echo the movement of falling water. Its integrated dimming ribbon washes the seams in luminous gradients, perfect for softening corners and anchoring lounge seating.</p><p>The base is turned from reclaimed ash, grounding the lamp with a tactile warmth that invites barefoot evenings and long playlists.</p>
|
||||
|
||||
----
|
||||
|
||||
Tags: floor lamp, textile, ambient
|
||||
|
||||
----
|
||||
|
||||
Uuid: D4DuOwcJk0fL0twA
|
||||
|
Before Width: | Height: | Size: 230 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Tidefall Floor Lamp pouring layered light beside a velvet sofa.
|
||||
|
||||
----
|
||||
|
||||
Alt: Tidefall floor lamp casting ripples of warm light
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: 0pQGdoX7b4QuEqhl
|
||||
|
Before Width: | Height: | Size: 201 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Tidefall's layered linen shade viewed from above.
|
||||
|
||||
----
|
||||
|
||||
Alt: Top view of Tidefall floor lamp with concentric textile tiers
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 1
|
||||
|
||||
----
|
||||
|
||||
Uuid: Kxk9ITpo07vV6u3e
|
||||
|
Before Width: | Height: | Size: 99 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Tidefall's cascading linen evokes bioluminescent drifts at sea.
|
||||
|
||||
----
|
||||
|
||||
Alt: Tidefall floor lamp with translucent linen layers aglow
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 3
|
||||
|
||||
----
|
||||
|
||||
Uuid: bUbLFbPgBpL51DSp
|
||||
|
Before Width: | Height: | Size: 266 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Tidefall dimmed low to frame a stone fireplace vignette.
|
||||
|
||||
----
|
||||
|
||||
Alt: Tidefall floor lamp beside textured stone wall
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 2
|
||||
|
||||
----
|
||||
|
||||
Uuid: GPuhd1glEC35U9k1
|
||||
|
Before Width: | Height: | Size: 206 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Tidefall embracing the curve of an arched reading niche.
|
||||
|
||||
----
|
||||
|
||||
Alt: Tidefall floor lamp glowing through layered textile shade
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 4
|
||||
|
||||
----
|
||||
|
||||
Uuid: 9n3HLGrBUs8MZUnB
|
||||
|
Before Width: | Height: | Size: 231 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Tidefall greeting guests with a gentle welcome wash.
|
||||
|
||||
----
|
||||
|
||||
Alt: Tidefall floor lamp illuminating an entryway bench
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: o3d9HlDINEzeJvp8
|
||||
@@ -1,25 +0,0 @@
|
||||
Title: Dune Loom Lantern
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://TcCivi92OPvsiwka
|
||||
|
||||
----
|
||||
|
||||
Headline: Sculptural wall light with woven depth
|
||||
|
||||
----
|
||||
|
||||
Subheadline: Clay-toned lattice cradling opal glass
|
||||
|
||||
----
|
||||
|
||||
Text: <p>Dune Loom wraps hand-dyed jute around a frosted opal core, melding artisanal craft with a gentle, architectural presence. The lantern throws a crescent of light upward and down, perfect for layering ambience in living rooms and hallways.</p><p>Each piece is sealed with breathable clay pigment, giving the fixture a sun-baked warmth that feels both grounded and indulgent.</p>
|
||||
|
||||
----
|
||||
|
||||
Tags: wall light, woven, accent
|
||||
|
||||
----
|
||||
|
||||
Uuid: w8ymxqAzqTvYkHJ4
|
||||
|
Before Width: | Height: | Size: 82 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Dune Loom Lantern tracing soft halos across clay plaster.
|
||||
|
||||
----
|
||||
|
||||
Alt: Dune Loom wall lamp glowing against textured clay
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 1
|
||||
|
||||
----
|
||||
|
||||
Uuid: oe7VNInWgLwgKYOZ
|
||||
|
Before Width: | Height: | Size: 76 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Dune Loom's wrapped fibres reveal their hand-braided origins.
|
||||
|
||||
----
|
||||
|
||||
Alt: Close detail of Dune Loom Lantern's jute lattice
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 5
|
||||
|
||||
----
|
||||
|
||||
Uuid: 1R9Haswet76cNlUB
|
||||
|
Before Width: | Height: | Size: 130 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Dune Loom glowing softly along a textured hallway curve.
|
||||
|
||||
----
|
||||
|
||||
Alt: Dune Loom Lantern illuminating an arched corridor
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 2
|
||||
|
||||
----
|
||||
|
||||
Uuid: i8yimrGbe132VGr5
|
||||
|
Before Width: | Height: | Size: 128 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Light spilling from Dune Loom paints the wall like desert sunlight.
|
||||
|
||||
----
|
||||
|
||||
Alt: Dune Loom Lantern sending warm beams across a wall
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 3
|
||||
|
||||
----
|
||||
|
||||
Uuid: TcCivi92OPvsiwka
|
||||
|
Before Width: | Height: | Size: 98 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Night scene with Dune Loom guiding guests with a soft glow.
|
||||
|
||||
----
|
||||
|
||||
Alt: Dune Loom Lantern casting crescent light during evening
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 4
|
||||
|
||||
----
|
||||
|
||||
Uuid: 6rSAbkLtovvdhS2E
|
||||
@@ -1,25 +0,0 @@
|
||||
Title: Summit Ember Chandelier
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://PHRV0Y0YkDOf7Cdc
|
||||
|
||||
----
|
||||
|
||||
Headline: Layered tiers sculpted for social heights
|
||||
|
||||
----
|
||||
|
||||
Subheadline: Forged steel arms with smoked glass globes
|
||||
|
||||
----
|
||||
|
||||
Text: <p>Summit Ember anchors rooms with a sculptural canopy of forged steel, offset by smoked glass globes that glow like embers. Its multi-tiered composition spreads light evenly, ideal for lofted living rooms and dining stages.</p><p>Dim-to-amber modules soften the atmosphere for late-night conversations while keeping the chandelier's silhouette crisp and architectural.</p>
|
||||
|
||||
----
|
||||
|
||||
Tags: chandelier, statement, living room
|
||||
|
||||
----
|
||||
|
||||
Uuid: XqbutgSsL5ibgjxP
|
||||
|
Before Width: | Height: | Size: 126 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Summit Ember chandelier staged above a stone coffee table.
|
||||
|
||||
----
|
||||
|
||||
Alt: Summit Ember chandelier illuminating sculpted stone furniture
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 1
|
||||
|
||||
----
|
||||
|
||||
Uuid: G8fDPmaJBTPAYPX6
|
||||
|
Before Width: | Height: | Size: 179 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Summit Ember's warm cascade mirrored in a glass partition.
|
||||
|
||||
----
|
||||
|
||||
Alt: Summit Ember chandelier reflecting in a dark glass wall
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 2
|
||||
|
||||
----
|
||||
|
||||
Uuid: VI8RHCHCnTx1ygYK
|
||||
|
Before Width: | Height: | Size: 102 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Summit Ember sketched against a twilight-toned ceiling.
|
||||
|
||||
----
|
||||
|
||||
Alt: Summit Ember chandelier silhouetted against moody ceiling
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 3
|
||||
|
||||
----
|
||||
|
||||
Uuid: PHRV0Y0YkDOf7Cdc
|
||||
|
Before Width: | Height: | Size: 151 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Summit Ember's globes emitting ember-like highlights.
|
||||
|
||||
----
|
||||
|
||||
Alt: Detail of Summit Ember chandelier's smoked glass sphere
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 4
|
||||
|
||||
----
|
||||
|
||||
Uuid: fWxKEZqZZp27Zmsb
|
||||
|
Before Width: | Height: | Size: 162 KiB |
@@ -1,29 +0,0 @@
|
||||
Caption: Summit Ember anchoring a double-height living room vignette.
|
||||
|
||||
----
|
||||
|
||||
Alt: Summit Ember chandelier hanging in a tall living room
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Sort: 5
|
||||
|
||||
----
|
||||
|
||||
Uuid: p8iAVxYBqkjR8eAA
|
||||
@@ -1,25 +0,0 @@
|
||||
Title: Cascade Veil Column
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://KwkXlLQwSJP3JhYI
|
||||
|
||||
----
|
||||
|
||||
Headline: Vertical ribbons of luminescence
|
||||
|
||||
----
|
||||
|
||||
Subheadline: Etched glass fins with programmable warmth
|
||||
|
||||
----
|
||||
|
||||
Text: <p>Cascade Veil rises as a slender column of etched glass fins, each one channeling light into a gentle shimmer. The programmable warm-to-neutral spectrum lets you match the lamp to the mood of your music or evening ritual.</p><p>The base remains discreet, allowing the illuminated ribbons to take centre stage beside sofas, in entry halls, or tucked between bookshelves.</p>
|
||||
|
||||
----
|
||||
|
||||
Tags: column, floor lamp, programmable
|
||||
|
||||
----
|
||||
|
||||
Uuid: Ne4eXh9gk3SPWsxu
|
||||
|
Before Width: | Height: | Size: 146 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Cascade Veil Column anchoring a lounge with vertical shimmer.
|
||||
|
||||
----
|
||||
|
||||
Alt: Cascade Veil column lamp beside a lounge chair
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: zCSNdxdxQLv7v90m
|
||||
|
Before Width: | Height: | Size: 155 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Cascade Veil catching light across overlapping glass fins.
|
||||
|
||||
----
|
||||
|
||||
Alt: Detail of Cascade Veil column lamp's layered glass
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: ypnar0L4JLSOhyzI
|
||||
|
Before Width: | Height: | Size: 86 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Cascade Veil diffusing a misty glow throughout a music lounge.
|
||||
|
||||
----
|
||||
|
||||
Alt: Cascade Veil column lamp illuminating a music lounge
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: EL2AU2LNatipeWPl
|
||||
|
Before Width: | Height: | Size: 179 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Cascade Veil reflecting soft gradients across stone surfaces.
|
||||
|
||||
----
|
||||
|
||||
Alt: Cascade Veil column lamp beside textured stone
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: ywQvOO1zShxtHb0k
|
||||
|
Before Width: | Height: | Size: 162 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Cascade Veil turned to ember mode for late-night ambience.
|
||||
|
||||
----
|
||||
|
||||
Alt: Cascade Veil column lamp glowing with ember-toned gradients
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: KwkXlLQwSJP3JhYI
|
||||
|
Before Width: | Height: | Size: 148 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Cascade Veil standing beside twin lounge chairs.
|
||||
|
||||
----
|
||||
|
||||
Alt: Cascade Veil column lamp illuminating paired lounge chairs
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: SbAezZovkgdEbopo
|
||||
@@ -1,25 +0,0 @@
|
||||
Title: Botanika Glow Table Lamp
|
||||
|
||||
----
|
||||
|
||||
Cover: - file://ta7NGtnZzvMSzTEF
|
||||
|
||||
----
|
||||
|
||||
Headline: Botanical light for intimate corners
|
||||
|
||||
----
|
||||
|
||||
Subheadline: Mouth-blown glass dome with terracotta base
|
||||
|
||||
----
|
||||
|
||||
Text: <p>Botanika Glow brings the garden indoors with a gentle dome of mouth-blown glass perched on a terracotta base. The nested LED tray allows foliage-inspired patterns to diffuse across nearby walls.</p><p>Its modest footprint makes it ideal for side tables, consoles, and window sills, inviting calm while accenting curated objects.</p>
|
||||
|
||||
----
|
||||
|
||||
Tags: table lamp, glass, cosy
|
||||
|
||||
----
|
||||
|
||||
Uuid: wAgKEa9FhpZ5mTMG
|
||||
|
Before Width: | Height: | Size: 139 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Botanika Glow casting botanical silhouettes across nearby walls.
|
||||
|
||||
----
|
||||
|
||||
Alt: Botanika Glow table lamp highlighting fern silhouettes
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: JfJDhAS8XTPgtAaf
|
||||
|
Before Width: | Height: | Size: 162 KiB |
@@ -1,25 +0,0 @@
|
||||
Caption: Botanika Glow revealing tinted glass gradients inspired by foliage.
|
||||
|
||||
----
|
||||
|
||||
Alt: Detail of Botanika Glow lamp's tinted glass dome
|
||||
|
||||
----
|
||||
|
||||
Photographer: Lichterei Studio
|
||||
|
||||
----
|
||||
|
||||
License: Courtesy of Lichterei
|
||||
|
||||
----
|
||||
|
||||
Link:
|
||||
|
||||
----
|
||||
|
||||
Template: image
|
||||
|
||||
----
|
||||
|
||||
Uuid: rireqNIOuBwm0JP9
|
||||
|
Before Width: | Height: | Size: 75 KiB |