mirror of
https://github.com/Kugelschieber/schnittfest.git
synced 2026-11-12 09:02:01 +01:00
Compare commits
2
Commits
047adf7b92
...
4d1362c257
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d1362c257 | ||
|
|
6e60f1c117 |
@@ -1 +1,3 @@
|
||||
config.json
|
||||
.secrets.env
|
||||
shifu.db
|
||||
|
||||
@@ -0,0 +1,764 @@
|
||||
# AGENTS.md — Building and editing websites with Shifu
|
||||
|
||||
This file tells an AI agent how to create and maintain a website built with
|
||||
[Shifu](https://github.com/emvi/shifu), a Git/file-based CMS that renders Go
|
||||
`html/template` files from JSON content. Read it fully before generating or
|
||||
changing anything. When the rules here conflict with habits from other
|
||||
frameworks (React, Hugo, Next.js, Tailwind build pipelines, …), the rules here win.
|
||||
|
||||
The goal of every change: **a site that renders correctly AND stays fully editable
|
||||
in Shifu's admin UI** (on-page editor at `/admin`). Code that renders but cannot be
|
||||
edited in the admin is considered broken.
|
||||
|
||||
---
|
||||
|
||||
## 1. Mental model
|
||||
|
||||
| Concept | Where it lives | What it is |
|
||||
|---|---|---|
|
||||
| **Template** | `tpl/**/<name>.html` | Go `html/template` for one element type (section, component, layout part). |
|
||||
| **Admin config** | `admin/tpl/**/<name>.json` | Makes the template editable: label, editable fields, child content areas. |
|
||||
| **Page** | `content/pages/**/<file>.json` | JSON with `path` (routes per language) and a tree of elements. |
|
||||
| **Reference** ("ref") | `content/refs/<name>.json` | A standalone, reusable element (header, footer, head, …) shared by many pages. |
|
||||
| **Sass** | `assets/scss/` | Compiled by Shifu (`sass` CLI) into `static/`. |
|
||||
| **JS/TS** | `assets/js/` | Bundled + minified by Shifu (embedded esbuild) into `static/`. |
|
||||
| **Static files** | `static/` | Served as-is under `/static/`. Admin uploads go to `static/media/`. |
|
||||
| **Config** | `config.json` (+ `.secrets.env`) | Server, Sass/JS build, admin UI, etc. |
|
||||
|
||||
Rendering: a request matches a page `path` → Shifu walks `content.content` (the
|
||||
root list of elements) in order → each element renders `tpl/.../<tpl>.html` with
|
||||
`.CMS`, `.Args`, `.Page`, `.Content` → elements render their own children via
|
||||
`.CMS.Render`.
|
||||
|
||||
### The "one element type = matching files" rule
|
||||
|
||||
Every editable element type `<name>` consists of files that share the same base name:
|
||||
|
||||
```
|
||||
tpl/sections/hero.html # required — markup
|
||||
admin/tpl/sections/hero.json # required — makes it editable/addable in the admin
|
||||
assets/scss/_hero.scss # optional — styles, scoped to .hero
|
||||
assets/js/hero.js # optional — behaviour, bound via data-component="hero"
|
||||
```
|
||||
|
||||
Names: lowercase `snake_case`, **globally unique across all subdirectories** (Shifu
|
||||
identifies templates by file base name only, folders are just for humans).
|
||||
|
||||
---
|
||||
|
||||
## 2. Project structure
|
||||
|
||||
Use this layout for new sites (it matches `shifu init` and the admin UI's own paths):
|
||||
|
||||
```
|
||||
.
|
||||
├── config.json
|
||||
├── .secrets.env # secrets, never commit (add to .gitignore)
|
||||
├── .gitignore
|
||||
├── admin/
|
||||
│ └── tpl/
|
||||
│ ├── layout/ # head.json, end.json, header.json, footer.json
|
||||
│ ├── sections/ # hero.json, text.json, cards.json, …
|
||||
│ └── components/ # card.json, button.json, nav_item.json, …
|
||||
├── assets/
|
||||
│ ├── scss/
|
||||
│ │ ├── main.scss # Sass entrypoint (only file referenced in config)
|
||||
│ │ ├── _variables.scss
|
||||
│ │ ├── _base.scss
|
||||
│ │ └── _hero.scss … # one partial per element type, FLAT (no subfolders)
|
||||
│ └── js/
|
||||
│ ├── main.js # JS entrypoint
|
||||
│ └── hero.js … # one module per interactive element type, FLAT
|
||||
├── content/
|
||||
│ ├── pages/ # pages (admin creates pages here)
|
||||
│ │ ├── home.json
|
||||
│ │ └── not-found.json
|
||||
│ └── refs/ # references (admin creates refs here)
|
||||
│ ├── head.json
|
||||
│ └── end.json
|
||||
├── static/ # served under /static/
|
||||
│ ├── media/ # admin media library (uploads)
|
||||
│ ├── main.css # GENERATED by Shifu — never write by hand
|
||||
│ └── main.js # GENERATED by Shifu — never write by hand
|
||||
└── tpl/
|
||||
├── layout/ # head.html, end.html, header.html, footer.html
|
||||
├── sections/
|
||||
├── components/
|
||||
└── partials/ # non-editable helpers used via {{ template }}
|
||||
```
|
||||
|
||||
If you are editing an **existing** site, keep its structure, naming and file
|
||||
locations (check `config.json` for the real `sass`/`js` dirs, entrypoints and output
|
||||
paths) instead of migrating it to this layout.
|
||||
|
||||
`shifu.db` (SQLite, created at runtime when the admin UI is enabled) stores admin
|
||||
users, sessions and the list of references. Don't commit it.
|
||||
|
||||
---
|
||||
|
||||
## 3. config.json
|
||||
|
||||
Minimal configuration for local development:
|
||||
|
||||
```json
|
||||
{
|
||||
"dev": true,
|
||||
"log_level": "info",
|
||||
"server": {
|
||||
"host": "localhost",
|
||||
"port": 8080,
|
||||
"hostname": "http://localhost:8080"
|
||||
},
|
||||
"content": {
|
||||
"provider": "fs",
|
||||
"not_found": {
|
||||
"en": "/not-found",
|
||||
"de": "/de/nicht-gefunden"
|
||||
}
|
||||
},
|
||||
"sass": {
|
||||
"dir": "assets/scss",
|
||||
"entrypoint": "main.scss",
|
||||
"out": "static/main.css",
|
||||
"out_source_map": "static/main.css.map",
|
||||
"watch": true
|
||||
},
|
||||
"js": {
|
||||
"dir": "assets/js",
|
||||
"entrypoint": "main.js",
|
||||
"out": "static/main.js",
|
||||
"source_map": true,
|
||||
"watch": true
|
||||
},
|
||||
"ui": {
|
||||
"path": "/admin",
|
||||
"admin_password": "${ADMIN_PASSWORD}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`.secrets.env` (one `KEY=value` per line, referenced as `${KEY}` in `config.json`):
|
||||
|
||||
```env
|
||||
ADMIN_PASSWORD=admin
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* `dev: true` reloads templates and content on every request (local only). For
|
||||
production set `dev: false`, set `server.host` to `""`, `server.hostname` to the
|
||||
public origin (e.g. `https://example.com`, used for canonical links/sitemap), and
|
||||
`secure_cookies: true`.
|
||||
* Keys starting with `_` are treated as comments by convention (they are ignored).
|
||||
* Optional sections (`api`, `remote`, `git`, `analytics`, `cors`) are documented in
|
||||
the Shifu README — only add them when asked.
|
||||
* Run with `shifu run .` (requires the `sass` CLI: `npm i -g sass`). JS needs no
|
||||
Node.js, esbuild is built in.
|
||||
|
||||
---
|
||||
|
||||
## 4. Templates (`tpl/`)
|
||||
|
||||
Go `html/template` syntax plus Shifu functions and all
|
||||
[Sprig](https://masterminds.github.io/sprig/) functions.
|
||||
|
||||
### 4.1 Variables available in every template
|
||||
|
||||
| Variable | Meaning |
|
||||
|---|---|
|
||||
| `.CMS` | CMS instance. `.CMS.Render`, `.CMS.LastUpdate` (cache-busting string). |
|
||||
| `.Args` | `map[string]string` of route variables, e.g. `{{ index .Args "slug" }}`. |
|
||||
| `.Page` | The page: `.Page.Language`, `.Page.Path` (map lang → path), `.Page.CanonicalLink`, `.Page.File`. |
|
||||
| `.Content` | The element being rendered: `.Content.Position`, `.Content.Data`, `.Content.Copy`, `.Content.Content`. |
|
||||
|
||||
### 4.2 Shifu template functions
|
||||
|
||||
| Function | Use |
|
||||
|---|---|
|
||||
| `copy .Page .Content "key"` | Translated text for the page language; falls back to `en`. Returns `nil` if missing. |
|
||||
| `get .Content "key"` | Language-independent value from `data`. Returns `nil` if missing. |
|
||||
| `html <string>` | Output trusted HTML (needed for `html` type fields). |
|
||||
| `htmlAttr <string>` | Output a trusted attribute. |
|
||||
| `fmt "%s/%s" a b` | `fmt.Sprintf`. |
|
||||
| `dict "k" v "k2" v2` | Build a map, e.g. to pass to partials. |
|
||||
| `default a b c` | **Shifu's version**: returns the first non-nil argument (NOT Sprig's `default "fallback" .x`). |
|
||||
| `int "12"`, `uint64`, `formatInt`, `formatFloat`, `formatDate`, `gtFloat`, `ltFloat`, `shuffle`, `year` | Helpers. |
|
||||
| `markdown "static/x.md" .`, `markdownBlock "static/x.md" "block" .` | Render a Markdown file (path relative to project root). |
|
||||
| `hostname`, `config` | `server.hostname`, full config. |
|
||||
| `adminHead .Page`, `adminBody .Page`, `loggedIn .Page` | Admin UI hooks (see §4.4). |
|
||||
|
||||
### 4.3 Element template contract (REQUIRED for admin editing)
|
||||
|
||||
Every editable element template must:
|
||||
|
||||
1. Have **exactly one top-level HTML element** carrying
|
||||
`data-shifu-element="{{ .Content.Position }}"`.
|
||||
2. For each child content area `<area>` declared in its admin config, render the
|
||||
children **and** place a slot directly after them:
|
||||
```gotemplate
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.<area>" .Content.Position) (index .Content.Content "<area>") }}
|
||||
<slot name="{{ .Content.Position }}/<area>"></slot>
|
||||
```
|
||||
The `<area>` string must be identical in all three places (position suffix,
|
||||
`index` key, slot name) and in the admin config's `content` keys.
|
||||
3. Read every editable value through `copy` (translatable text) or `get` (data), and
|
||||
handle missing values — new elements added in the admin start **empty**.
|
||||
|
||||
Canonical section template — `tpl/sections/text.html`:
|
||||
|
||||
```gotemplate
|
||||
{{- $headline := copy .Page .Content "headline" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
{{- $background := get .Content "background" -}}
|
||||
|
||||
<section class="text{{ with $background }} text--{{ . }}{{ end }}" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="text__inner">
|
||||
{{ with $headline }}<h2 class="text__headline">{{ . }}</h2>{{ end }}
|
||||
{{ with $text }}<div class="text__body">{{ html . }}</div>{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
```
|
||||
|
||||
Container with child elements — `tpl/sections/cards.html`:
|
||||
|
||||
```gotemplate
|
||||
{{- $headline := copy .Page .Content "headline" -}}
|
||||
|
||||
<section class="cards" data-shifu-element="{{ .Content.Position }}">
|
||||
{{ with $headline }}<h2 class="cards__headline">{{ . }}</h2>{{ end }}
|
||||
<div class="cards__grid">
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.items" .Content.Position) (index .Content.Content "items") }}
|
||||
<slot name="{{ .Content.Position }}/items"></slot>
|
||||
</div>
|
||||
</section>
|
||||
```
|
||||
|
||||
Child element — `tpl/components/card.html`:
|
||||
|
||||
```gotemplate
|
||||
{{- $title := copy .Page .Content "title" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
{{- $href := copy .Page .Content "href" -}}
|
||||
{{- $image := get .Content "image" -}}
|
||||
|
||||
<article class="card" data-shifu-element="{{ .Content.Position }}">
|
||||
{{ with $image }}<img class="card__image" src="{{ . }}" alt="{{ copy $.Page $.Content "image_alt" }}" loading="lazy" />{{ end }}
|
||||
{{ with $title }}<h3 class="card__title">{{ . }}</h3>{{ end }}
|
||||
{{ with $text }}<div class="card__text">{{ html . }}</div>{{ end }}
|
||||
{{ with $href }}<a class="card__link" href="{{ . }}">{{ default (copy $.Page $.Content "link_label") "Read more" }}</a>{{ end }}
|
||||
</article>
|
||||
```
|
||||
|
||||
Multiple content areas (e.g. two columns) — `tpl/sections/columns.html`:
|
||||
|
||||
```gotemplate
|
||||
<section class="columns" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="columns__col">
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.left" .Content.Position) (index .Content.Content "left") }}
|
||||
<slot name="{{ .Content.Position }}/left"></slot>
|
||||
</div>
|
||||
<div class="columns__col">
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.right" .Content.Position) (index .Content.Content "right") }}
|
||||
<slot name="{{ .Content.Position }}/right"></slot>
|
||||
</div>
|
||||
</section>
|
||||
```
|
||||
|
||||
Pitfalls:
|
||||
|
||||
* Inside `with`/`range`, `.` changes — use `$.Page` / `$.Content`.
|
||||
* `{{ html $x }}` with a missing value prints the literal text `<nil>`. Always wrap
|
||||
it: `{{ with $x }}{{ html . }}{{ end }}`.
|
||||
* Never hard-code visible text in element templates — put it in `copy` so it is
|
||||
editable and translatable. (Fallback labels via `default` are fine.)
|
||||
* Don't use Go's `{{ block }}`/`{{ define }}` inheritance for page layouts. Layout
|
||||
in Shifu is composition: pages are lists of elements (`head`, `header`, sections,
|
||||
`footer`, `end`).
|
||||
* Template file base names must be unique across all of `tpl/`; `tpl/a/card.html`
|
||||
and `tpl/b/card.html` would clash.
|
||||
|
||||
### 4.4 Layout templates (head / end)
|
||||
|
||||
Every page starts with a `head` element and ends with an `end` element (normally
|
||||
used as references, see §6). They split the HTML document. The admin UI needs
|
||||
`adminHead` inside `<head>` and `adminBody` before `</body>`. They output nothing for
|
||||
regular visitors.
|
||||
|
||||
`tpl/layout/head.html`:
|
||||
|
||||
```gotemplate
|
||||
{{- $title := copy .Page .Content "title" -}}
|
||||
{{- $description := copy .Page .Content "meta_description" -}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ .Page.Language }}">
|
||||
<head>
|
||||
<base href="/" />
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{{ $title }}</title>
|
||||
<meta name="description" content="{{ $description }}" />
|
||||
<link rel="canonical" href="{{ .Page.CanonicalLink }}" />
|
||||
{{- range $language, $path := .Page.Path }}
|
||||
<link rel="alternate" hreflang="{{ $language }}" href="{{ hostname }}{{ $path }}" />
|
||||
{{- end }}
|
||||
<link rel="stylesheet" href="/static/main.css?v={{ .CMS.LastUpdate }}" />
|
||||
<script defer src="/static/main.js?v={{ .CMS.LastUpdate }}"></script>
|
||||
{{ adminHead .Page }}
|
||||
</head>
|
||||
<body>
|
||||
```
|
||||
|
||||
`tpl/layout/end.html`:
|
||||
|
||||
```gotemplate
|
||||
{{ adminBody .Page }}
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The `/static/...` file names must match `sass.out` and `js.out` in `config.json`.
|
||||
|
||||
The head is a *layout* element and is not wrapped in `data-shifu-element`
|
||||
(`<head>` content cannot be edited on-page; its fields are editable from the
|
||||
admin's page tree). For per-page titles, override the head reference's copy on
|
||||
each page (§6).
|
||||
|
||||
### 4.5 Partials (non-editable helpers)
|
||||
|
||||
Put reusable markup that is *not* an admin element in `tpl/partials/` and call it
|
||||
by file name. Do **not** create an admin config for partials.
|
||||
|
||||
```gotemplate
|
||||
{{/* tpl/partials/button.html */}}
|
||||
<a class="button button--{{ default .Variant "primary" }}" href="{{ .Href }}">{{ .Label }}</a>
|
||||
```
|
||||
|
||||
```gotemplate
|
||||
{{ with copy .Page .Content "cta_label" }}
|
||||
{{ template "button.html" (dict "Label" . "Href" (copy $.Page $.Content "cta_href") "Variant" (get $.Content "cta_variant")) }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Admin configuration (`admin/tpl/`)
|
||||
|
||||
One JSON file per element type, **same base name as the template**. Without it the
|
||||
element renders but cannot be edited, and it cannot be added from the admin.
|
||||
|
||||
```json
|
||||
{
|
||||
"label": "Cards",
|
||||
"layout": false,
|
||||
"content": {
|
||||
"items": {
|
||||
"label": "Cards",
|
||||
"tpl_filter": ["card"]
|
||||
}
|
||||
},
|
||||
"copy": {
|
||||
"headline": { "label": "Headline" }
|
||||
},
|
||||
"data": {
|
||||
"background": {
|
||||
"label": "Background",
|
||||
"type": "select",
|
||||
"options": {
|
||||
"": "Default",
|
||||
"light": "Light",
|
||||
"dark": "Dark"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Key | Meaning |
|
||||
|---|---|
|
||||
| `label` | Display name in the admin's element picker. |
|
||||
| `layout` | `true` for structural elements (head, end, header, footer). Disables some actions; new elements are inserted *before* a trailing layout element. |
|
||||
| `content` | Child content areas: key = area name used in the template, `label`, optional `tpl_filter` (list of template names allowed in that area; omit to allow all). |
|
||||
| `copy` | Translatable fields (stored per language under `copy.<lang>`). |
|
||||
| `data` | Language-independent fields (stored under `data`). |
|
||||
|
||||
Field `type` (for `copy` and `data`):
|
||||
|
||||
| Type | Editor | Template usage |
|
||||
|---|---|---|
|
||||
| *(omitted)* / `text` | single-line input | `{{ $x }}` |
|
||||
| `html` | rich-text editor (Trix) | `{{ with $x }}{{ html . }}{{ end }}` |
|
||||
| `img` | media library picker, stores a path like `/static/media/photo.jpg` | `<img src="{{ $x }}">` |
|
||||
| `file` | media library picker, stores a path | `<a href="{{ $x }}">` |
|
||||
| `boolean` | checkbox, stores `"on"` when checked, key removed when unchecked | `{{ if $x }}` |
|
||||
| `select` | dropdown from `options` (`value: label`) | compare as string: `{{ if eq $x "dark" }}` |
|
||||
| `color` | color picker, stores `#rrggbb` | `style="--accent: {{ $x }}"` |
|
||||
|
||||
Rules derived from how the admin saves (important):
|
||||
|
||||
* **When an editor saves an element, its `copy` and `data` are replaced by exactly
|
||||
the configured fields.** Any key the template reads but the admin config does not
|
||||
declare is deleted on the first save. ⇒ Declare *every* `copy`/`data` key the
|
||||
template uses. Don't store arrays/objects in `data` — they cannot be edited and
|
||||
are lost. Model repeatable things (cards, slides, nav items, FAQ entries, team
|
||||
members) as **child elements** in a content area instead.
|
||||
* All saved values are **strings**. Write data values as strings in JSON too
|
||||
(`"columns": "3"`, not `3`), otherwise `select` comparisons fail. Use
|
||||
`{{ int (get .Content "columns") }}` when you need a number.
|
||||
* Copy is edited for the languages present in the page's `path`.
|
||||
* Use `copy` for anything a translator would change (text, alt text, link URLs that
|
||||
differ by language, button labels); use `data` for design choices (variant, color,
|
||||
image, alignment, size).
|
||||
* Choose `select` over free text for design options and keep option keys stable —
|
||||
they are referenced by CSS modifier classes.
|
||||
* Prefixing a `label` with `_` (e.g. `"_HTML Head"`) sorts it first in the picker;
|
||||
the demo uses this for layout elements.
|
||||
|
||||
Layout configs:
|
||||
|
||||
```json
|
||||
{ "label": "_HTML Head", "layout": true, "copy": { "title": { "label": "Title" }, "meta_description": { "label": "Meta Description" } } }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "label": "_HTML End", "layout": true }
|
||||
```
|
||||
|
||||
Admin config changes are picked up automatically for files directly inside
|
||||
`admin/tpl/`; restart Shifu after adding files in its subdirectories.
|
||||
|
||||
---
|
||||
|
||||
## 6. Content (`content/`)
|
||||
|
||||
### 6.1 Pages — `content/pages/<name>.json`
|
||||
|
||||
A file with `path` and **no top-level `tpl`** is a page.
|
||||
|
||||
```json
|
||||
{
|
||||
"display_name": "Home",
|
||||
"path": {
|
||||
"en": "/",
|
||||
"de": "/de"
|
||||
},
|
||||
"sitemap": { "priority": "1.0" },
|
||||
"content": {
|
||||
"content": [
|
||||
{
|
||||
"ref": "head",
|
||||
"copy": {
|
||||
"en": { "title": "Acme — Home", "meta_description": "Acme builds things." },
|
||||
"de": { "title": "Acme — Start", "meta_description": "Acme baut Dinge." }
|
||||
}
|
||||
},
|
||||
{ "ref": "header" },
|
||||
{
|
||||
"tpl": "hero",
|
||||
"copy": {
|
||||
"en": { "headline": "We build things", "text": "<div>Fast and reliable.</div>" },
|
||||
"de": { "headline": "Wir bauen Dinge", "text": "<div>Schnell und zuverlässig.</div>" }
|
||||
},
|
||||
"data": { "image": "/static/media/hero.jpg", "align": "center" }
|
||||
},
|
||||
{
|
||||
"tpl": "cards",
|
||||
"copy": { "en": { "headline": "Services" }, "de": { "headline": "Leistungen" } },
|
||||
"content": {
|
||||
"items": [
|
||||
{
|
||||
"tpl": "card",
|
||||
"copy": {
|
||||
"en": { "title": "Design", "text": "<div>…</div>" },
|
||||
"de": { "title": "Design", "text": "<div>…</div>" }
|
||||
},
|
||||
"content": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{ "ref": "footer" },
|
||||
{ "ref": "end" }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
* The page root must use a **single** content area named `content`
|
||||
(`"content": { "content": [ … ] }`). Elements are rendered in array order.
|
||||
* Each element has either `tpl` (template name, lowercase, no extension) **or**
|
||||
`ref` (reference name), plus optional `copy`, `data`, `content`, `display_name`.
|
||||
* Every content area declared in an element's admin config should exist in the JSON
|
||||
(use `[]` when empty), e.g. `"content": { "items": [] }`.
|
||||
* `path` keys are language codes; the value is the exact route (no trailing slash,
|
||||
must start with `/`). Every language in `path` should have `copy` for every
|
||||
element; missing languages fall back to `en`.
|
||||
* Dynamic routes: always give the variable a regular expression, e.g.
|
||||
`"/blog/{slug:[a-z0-9-]+}"` or `"/p/{id:[0-9]+}"` (a bare `{slug}` does not match
|
||||
in the current version). Each `{…}` matches exactly one path segment; read it with
|
||||
`{{ index .Args "slug" }}`. Longer paths are matched first.
|
||||
* 404: create a page whose path matches `content.not_found` in `config.json`
|
||||
(default `/404`).
|
||||
* Optional page keys: `disable_cache`, `header` (HTTP headers map), `handler` (Go
|
||||
custom handler, only if the backend defines it), `analytics` (Pirsch tags / A/B
|
||||
experiments — see the Shifu README).
|
||||
* Rich-text (`html`) values are HTML strings. The Trix editor produces `<div>`,
|
||||
`<br>`, `<strong>`, `<em>`, `<a>`, `<ul>/<ol>/<li>`, `<h1>`, `<blockquote>`,
|
||||
`<pre>`. Stick to these tags so content stays editable.
|
||||
* Image paths should point to `static/media/…` (the admin media library), e.g.
|
||||
`/static/media/hero.jpg`, and the file must exist there.
|
||||
* Media files go in `static/media/` only; don't put site assets (logos used by
|
||||
templates, icons, fonts) there — use `static/img/`, `static/fonts/` instead.
|
||||
|
||||
### 6.2 References — `content/refs/<name>.json`
|
||||
|
||||
A content file with a **top-level `tpl`** is a reference (a standalone element).
|
||||
Its name is the lowercase file name without `.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"tpl": "head",
|
||||
"copy": {
|
||||
"en": { "title": "Acme", "meta_description": "Acme builds things." },
|
||||
"de": { "title": "Acme", "meta_description": "Acme baut Dinge." }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"tpl": "header",
|
||||
"data": { "logo": "/static/media/logo.svg" },
|
||||
"copy": { "en": { "home_label": "Acme" }, "de": { "home_label": "Acme" } },
|
||||
"content": {
|
||||
"nav": [
|
||||
{ "tpl": "nav_item", "copy": { "en": { "label": "About", "href": "/about" }, "de": { "label": "Über uns", "href": "/de/ueber-uns" } }, "content": {} }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* Use refs for anything shared across pages: `head`, `header`, `footer`, `end`,
|
||||
newsletter box, CTA banners.
|
||||
* Pages use them with `{ "ref": "<name>" }`. Non-empty `copy`/`data` on the page
|
||||
element override the ref's values for that page only (typical: page title).
|
||||
* Ref names must be unique across **all** files in `content/` — never give a page
|
||||
file the same name as a ref (e.g. no `content/pages/header.json`).
|
||||
* The admin's "add reference" picker lists refs from `shifu.db`, not from disk. Refs
|
||||
created by hand still render and are editable where used, but to make them
|
||||
insertable from the admin register them (with Shifu stopped, after it has run
|
||||
once so `shifu.db` exists; needs the `sqlite3` CLI):
|
||||
```sh
|
||||
sqlite3 shifu.db "INSERT OR IGNORE INTO reference (name) VALUES ('head'), ('header'), ('footer'), ('end');"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Styles (`assets/scss/`)
|
||||
|
||||
Shifu compiles the Sass entrypoint itself (`sass --style=compressed`) on start and
|
||||
on every save. **Never** pre-compile, never write or edit `static/main.css` by hand,
|
||||
never add PostCSS/Tailwind/Vite/webpack or npm build scripts, never inline large
|
||||
`<style>` blocks in templates.
|
||||
|
||||
`assets/scss/main.scss`:
|
||||
|
||||
```scss
|
||||
@use "variables";
|
||||
@use "base";
|
||||
@use "layout";
|
||||
|
||||
// one partial per element type, same name as the template
|
||||
@use "head";
|
||||
@use "header";
|
||||
@use "footer";
|
||||
@use "hero";
|
||||
@use "text";
|
||||
@use "cards";
|
||||
@use "card";
|
||||
```
|
||||
|
||||
`assets/scss/_variables.scss`:
|
||||
|
||||
```scss
|
||||
$color-text: #1d1d1f;
|
||||
$color-accent: #0a64d6;
|
||||
$max-width: 1120px;
|
||||
$radius: 12px;
|
||||
$breakpoint-md: 768px;
|
||||
|
||||
@mixin md {
|
||||
@media (min-width: $breakpoint-md) { @content; }
|
||||
}
|
||||
```
|
||||
|
||||
`assets/scss/_card.scss`:
|
||||
|
||||
```scss
|
||||
@use "variables" as *;
|
||||
|
||||
.card {
|
||||
border-radius: $radius;
|
||||
overflow: hidden;
|
||||
|
||||
&__image { display: block; width: 100%; height: auto; }
|
||||
&__title { margin: 16px 0 8px; }
|
||||
&__link { color: $color-accent; }
|
||||
}
|
||||
```
|
||||
|
||||
Conventions:
|
||||
|
||||
* Use the module system (`@use`/`@forward`), not deprecated `@import`.
|
||||
* Scope styles to the element's root class (BEM: `.card`, `.card__title`,
|
||||
`.card--dark`). Modifier names come from `select` option keys.
|
||||
* Style rich-text output by element (`.text__body p, .text__body ul …`) since editors
|
||||
can't add classes.
|
||||
* Expose admin `color` fields as CSS custom properties
|
||||
(`style="--accent: {{ $color }}"` + `color: var(--accent, #{$color-accent})`).
|
||||
* Keep partials flat inside the Sass dir: Shifu only watches that directory itself
|
||||
(not subfolders) for changes. Every subfolder is also a Sass load path, so names
|
||||
must be unique.
|
||||
* Fonts/images referenced from CSS go in `static/` and use absolute URLs
|
||||
(`url("/static/fonts/inter.woff2")`).
|
||||
* Requires the Dart Sass CLI (`sass`) on the machine running Shifu.
|
||||
|
||||
---
|
||||
|
||||
## 8. JavaScript (`assets/js/`)
|
||||
|
||||
Shifu bundles and minifies the JS entrypoint with esbuild on start and on save (ES
|
||||
modules, TypeScript `.ts` also works). **Never** pre-bundle, never edit
|
||||
`static/main.js`, never add a separate bundler. `import` between files in
|
||||
`assets/js/` is fine. Avoid npm dependencies unless the user asks; if one is needed,
|
||||
prefer copying a small ES-module library into `assets/js/` (e.g. `vendor_glide.js`).
|
||||
Keep JS files flat in that directory: like Sass, only the directory itself is
|
||||
watched for changes, not its subfolders.
|
||||
|
||||
Pattern: progressive enhancement, components bound by `data-component`, idempotent
|
||||
initialisation that also handles elements the admin inserts or re-renders on the fly.
|
||||
|
||||
`assets/js/main.js`:
|
||||
|
||||
```js
|
||||
import { initNav } from "./nav.js";
|
||||
import { initSlider } from "./slider.js";
|
||||
|
||||
const components = {
|
||||
nav: initNav,
|
||||
slider: initSlider,
|
||||
};
|
||||
|
||||
function init(root = document) {
|
||||
root.querySelectorAll("[data-component]").forEach((el) => {
|
||||
if (el.dataset.componentReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fn = components[el.dataset.component];
|
||||
|
||||
if (fn) {
|
||||
fn(el);
|
||||
el.dataset.componentReady = "true";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
init();
|
||||
// the admin UI swaps element HTML in place after edits
|
||||
new MutationObserver(() => init()).observe(document.body, { childList: true, subtree: true });
|
||||
});
|
||||
```
|
||||
|
||||
`assets/js/nav.js`:
|
||||
|
||||
```js
|
||||
export function initNav(el) {
|
||||
const toggle = el.querySelector(".header__toggle");
|
||||
|
||||
if (!toggle) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggle.addEventListener("click", () => {
|
||||
const open = el.classList.toggle("header--open");
|
||||
toggle.setAttribute("aria-expanded", String(open));
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
Template side: `<header class="header" data-component="nav" data-shifu-element="{{ .Content.Position }}">`.
|
||||
|
||||
Rules:
|
||||
|
||||
* The site must be usable without JS; JS enhances.
|
||||
* No inline `<script>` in element templates; no `onclick=` attributes.
|
||||
* Pass configuration via `data-*` attributes rendered from `copy`/`data`.
|
||||
* Don't rely on the DOM being static — the admin replaces element markup when
|
||||
editors save. Never store state outside the element or bind listeners in a way
|
||||
that breaks if an element is replaced.
|
||||
* Load the bundle once, in `head.html`, with `defer`.
|
||||
|
||||
---
|
||||
|
||||
## 9. Workflows
|
||||
|
||||
### 9.1 Create a whole new site
|
||||
|
||||
1. Write `config.json`, `.secrets.env`, `.gitignore`
|
||||
(`.secrets.env`, `shifu.db`, `static/main.css*`, `static/main.js*`).
|
||||
2. Plan the element inventory from the design: layout parts (head, header, footer,
|
||||
end), sections (hero, text, image, cards, columns, cta, faq, contact, …),
|
||||
components (card, nav_item, faq_item, button…). Prefer a small set of flexible
|
||||
sections with `select` options over many near-duplicates.
|
||||
3. For each element type create: template, admin config, Sass partial (+ `@use` in
|
||||
`main.scss`), and JS module (+ register in `main.js`) when interactive.
|
||||
4. Create refs: `content/refs/head.json`, `header.json`, `footer.json`, `end.json`.
|
||||
5. Create pages in `content/pages/`, each starting with `head` and ending with `end`,
|
||||
with `copy` for every language in its `path`. Include a 404 page.
|
||||
6. Put referenced images in `static/media/`.
|
||||
7. Run `shifu run .`, open every page, check the log for errors.
|
||||
|
||||
### 9.2 Edit an existing site
|
||||
|
||||
1. Read `config.json`, list `tpl/`, `admin/tpl/`, `content/` and the Sass/JS
|
||||
entrypoints first to learn the existing element inventory and conventions.
|
||||
2. Reuse existing element types before creating new ones.
|
||||
3. Edit content JSON surgically; keep keys you don't touch (`display_name`,
|
||||
`analytics`, `header`, …). The admin writes compact single-line JSON — that's fine,
|
||||
keep it valid; reformatting is allowed but not required.
|
||||
4. Renaming a `copy`/`data` key or content area → update the template, the admin
|
||||
config **and every page/ref JSON** that uses it (search all of `content/`).
|
||||
5. Removing an element type → first remove all its uses from `content/`.
|
||||
6. Adding a field → add it to template *and* admin config; existing content may lack
|
||||
it, so templates must handle the missing value.
|
||||
|
||||
### 9.3 Add a new page
|
||||
|
||||
Create `content/pages/<slug>.json` (unique file name, not equal to any ref name),
|
||||
copy the head/header/footer/end refs from an existing page, set `path` for all site
|
||||
languages, override the head `title`/`meta_description`, and add nav entries in the
|
||||
header ref if the page should be linked.
|
||||
|
||||
---
|
||||
|
||||
## 10. Verification checklist
|
||||
|
||||
Before finishing, confirm:
|
||||
|
||||
- [ ] Every element type has `tpl/**/<name>.html` and `admin/tpl/**/<name>.json` with the same unique base name (partials excepted).
|
||||
- [ ] Every element template has one root element with `data-shifu-element="{{ .Content.Position }}"`.
|
||||
- [ ] Every content area appears identically in the template (`fmt "%s.<area>"`, `index … "<area>"`, `<slot name=".../<area>">`), the admin config `content`, and the JSON.
|
||||
- [ ] Every `copy`/`data` key read in a template is declared in the admin config with the right `type`.
|
||||
- [ ] No arrays/objects in `data`; all `copy`/`data` values are strings.
|
||||
- [ ] `html` values are wrapped in `{{ with }}`; no `<nil>` can appear.
|
||||
- [ ] `head.html` contains `{{ adminHead .Page }}`, `end.html` contains `{{ adminBody .Page }}`, and the CSS/JS URLs match `sass.out`/`js.out`.
|
||||
- [ ] Pages: root area named `content`, start with `head`, end with `end`, `copy` for all languages in `path`, paths unique and starting with `/`.
|
||||
- [ ] Refs live in `content/refs/`, names don't collide with any other file name in `content/`.
|
||||
- [ ] No hand-written files in `static/` for CSS/JS output; no extra build tooling.
|
||||
- [ ] Every Sass partial is `@use`d by the entrypoint; every JS module is imported by the entrypoint.
|
||||
- [ ] JSON files are valid (e.g. `python3 -m json.tool file.json`).
|
||||
- [ ] `shifu run .` starts without "Error compiling sass", "Error compiling js", "Error rendering template" or "Error parsing website content file" in the log; no page shows `Reference "…" not found!` or `<nil>`.
|
||||
- [ ] Logged in at `/admin`, each element can be selected, edited, and new children can be added to every content area.
|
||||
@@ -0,0 +1 @@
|
||||
{ "label": "_HTML End", "layout": true }
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "FAQ",
|
||||
"content": {
|
||||
"items": { "label": "Fragen", "tpl_filter": ["faq_item"] }
|
||||
},
|
||||
"copy": {
|
||||
"headline": { "label": "Überschrift" },
|
||||
"text": { "label": "Text", "type": "html" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "FAQ-Frage",
|
||||
"copy": {
|
||||
"question": { "label": "Frage" },
|
||||
"answer": { "label": "Antwort", "type": "html" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"label": "_Footer",
|
||||
"layout": true,
|
||||
"copy": {
|
||||
"headline": { "label": "Überschrift" },
|
||||
"text": { "label": "Text" },
|
||||
"copyright": { "label": "Copyright" }
|
||||
},
|
||||
"data": {
|
||||
"email": { "label": "E-Mail" },
|
||||
"phone": { "label": "Telefon" },
|
||||
"instagram": { "label": "Instagram URL" },
|
||||
"vimeo": { "label": "Vimeo URL" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"label": "_HTML Head",
|
||||
"layout": true,
|
||||
"copy": {
|
||||
"title": { "label": "Title (max. ~60 Zeichen)" },
|
||||
"meta_description": { "label": "Meta Description (max. ~155 Zeichen)" }
|
||||
},
|
||||
"data": {
|
||||
"robots": {
|
||||
"label": "Suchmaschinen",
|
||||
"type": "select",
|
||||
"options": {
|
||||
"index,follow": "Indexieren",
|
||||
"noindex,follow": "Nicht indexieren"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "Instagram",
|
||||
"copy": {
|
||||
"headline": { "label": "Überschrift" }
|
||||
},
|
||||
"data": {
|
||||
"widget": { "label": "LightWidget URL" },
|
||||
"profile": { "label": "Profil URL" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"label": "Intro (Hero-Video)",
|
||||
"copy": {
|
||||
"kicker": { "label": "Dachzeile" },
|
||||
"headline": { "label": "Überschrift (H1)" },
|
||||
"text": { "label": "Einleitungstext", "type": "html" },
|
||||
"video_label": { "label": "Video-Beschreibung (Barrierefreiheit)" },
|
||||
"cta_label": { "label": "Button-Text" },
|
||||
"cta_href": { "label": "Button-Link" },
|
||||
"ticker": { "label": "Laufband-Text" }
|
||||
},
|
||||
"data": {
|
||||
"video": { "label": "Video", "type": "file" },
|
||||
"poster": { "label": "Vorschaubild", "type": "img" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{ "label": "Impressum & Datenschutz" }
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"label": "_Navigation",
|
||||
"layout": true,
|
||||
"copy": {
|
||||
"service_label": { "label": "Link: Leistungen" },
|
||||
"faq_label": { "label": "Link: FAQ" },
|
||||
"work_label": { "label": "Link: Referenzen" },
|
||||
"contact_label": { "label": "Link: Kontakt" }
|
||||
},
|
||||
"data": {
|
||||
"full": { "label": "Volle Navigation anzeigen", "type": "boolean" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "Ablauf",
|
||||
"content": {
|
||||
"steps": { "label": "Schritte", "tpl_filter": ["process_step"] }
|
||||
},
|
||||
"copy": {
|
||||
"headline": { "label": "Überschrift" },
|
||||
"text": { "label": "Text", "type": "html" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"label": "Ablauf-Schritt",
|
||||
"copy": {
|
||||
"title": { "label": "Titel" },
|
||||
"text": { "label": "Text" }
|
||||
},
|
||||
"data": {
|
||||
"color": {
|
||||
"label": "Farbe",
|
||||
"type": "select",
|
||||
"options": { "yellow": "Gelb", "orange": "Orange", "red": "Rot", "pink": "Pink", "purple": "Lila" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"label": "Gewerke",
|
||||
"content": {
|
||||
"items": { "label": "Gewerke", "tpl_filter": ["service_item"] }
|
||||
},
|
||||
"copy": {
|
||||
"headline": { "label": "Überschrift" },
|
||||
"text": { "label": "Text", "type": "html" },
|
||||
"image_caption": { "label": "Bildunterschrift" }
|
||||
},
|
||||
"data": {
|
||||
"image": { "label": "Bild", "type": "img" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"label": "Gewerk (Klappe)",
|
||||
"copy": {
|
||||
"title": { "label": "Titel" },
|
||||
"text": { "label": "Text" }
|
||||
},
|
||||
"data": {
|
||||
"color": {
|
||||
"label": "Farbe",
|
||||
"type": "select",
|
||||
"options": {
|
||||
"red": "Rot",
|
||||
"orange": "Orange",
|
||||
"yellow": "Gelb",
|
||||
"pink": "Pink",
|
||||
"purple": "Lila"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{ "label": "AGB" }
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "Referenzen",
|
||||
"content": {
|
||||
"content": { "label": "Referenzen", "tpl_filter": ["work_entry"] }
|
||||
},
|
||||
"copy": {
|
||||
"headline": { "label": "Überschrift" },
|
||||
"text": { "label": "Text", "type": "html" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"label": "Referenz (Video)",
|
||||
"copy": {
|
||||
"h2": { "label": "Titel" },
|
||||
"text": { "label": "Text" }
|
||||
},
|
||||
"data": {
|
||||
"video": { "label": "Embed-URL (YouTube/Vimeo)" }
|
||||
}
|
||||
}
|
||||
+38
-1
@@ -1 +1,38 @@
|
||||
console.log("Hi!");
|
||||
import { initNav } from "./nav.js";
|
||||
import { initReveal } from "./reveal.js";
|
||||
import { initTimecode } from "./timecode.js";
|
||||
|
||||
document.documentElement.classList.add("js");
|
||||
|
||||
const components = {
|
||||
nav: initNav,
|
||||
reveal: initReveal,
|
||||
timecode: initTimecode,
|
||||
};
|
||||
|
||||
function init(root = document) {
|
||||
root.querySelectorAll("[data-component]").forEach((el) => {
|
||||
if (el.dataset.componentReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fn = components[el.dataset.component];
|
||||
|
||||
if (fn) {
|
||||
fn(el);
|
||||
el.dataset.componentReady = "true";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", start);
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
|
||||
function start() {
|
||||
init();
|
||||
// the admin UI swaps element HTML in place after edits
|
||||
new MutationObserver(() => init()).observe(document.body, { childList: true, subtree: true });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
export function initNav(el) {
|
||||
const toggle = el.querySelector(".nav__toggle");
|
||||
|
||||
if (!toggle) {
|
||||
return;
|
||||
}
|
||||
|
||||
const setOpen = (open) => {
|
||||
el.classList.toggle("nav--open", open);
|
||||
toggle.setAttribute("aria-expanded", String(open));
|
||||
};
|
||||
|
||||
toggle.addEventListener("click", () => setOpen(!el.classList.contains("nav--open")));
|
||||
el.querySelectorAll(".nav__link").forEach((link) => link.addEventListener("click", () => setOpen(false)));
|
||||
el.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") {
|
||||
setOpen(false);
|
||||
toggle.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
let observer = null;
|
||||
|
||||
function getObserver() {
|
||||
if (!observer) {
|
||||
observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add("is-visible");
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { rootMargin: "0px 0px -8% 0px", threshold: 0.05 });
|
||||
}
|
||||
|
||||
return observer;
|
||||
}
|
||||
|
||||
export function initReveal(el) {
|
||||
if (!("IntersectionObserver" in window)) {
|
||||
el.classList.add("is-visible");
|
||||
return;
|
||||
}
|
||||
|
||||
getObserver().observe(el);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
const FPS = 25;
|
||||
|
||||
function pad(n) {
|
||||
return String(n).padStart(2, "0");
|
||||
}
|
||||
|
||||
export function initTimecode(el) {
|
||||
const start = performance.now();
|
||||
|
||||
const tick = (now) => {
|
||||
if (!el.isConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
const frames = Math.floor(((now - start) / 1000) * FPS);
|
||||
const f = frames % FPS;
|
||||
const s = Math.floor(frames / FPS) % 60;
|
||||
const m = Math.floor(frames / (FPS * 60)) % 60;
|
||||
const h = Math.floor(frames / (FPS * 3600));
|
||||
el.textContent = `${pad(h)}:${pad(m)}:${pad(s)}:${pad(f)}`;
|
||||
requestAnimationFrame(tick);
|
||||
};
|
||||
|
||||
requestAnimationFrame(tick);
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
@use "variables" as *;
|
||||
|
||||
:root {
|
||||
--beige: #{$beige};
|
||||
--yellow: #{$yellow};
|
||||
--orange: #{$orange};
|
||||
--red: #{$red};
|
||||
--pink: #{$pink};
|
||||
--purple: #{$purple};
|
||||
--ink: #{$ink};
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
scroll-padding-top: 88px;
|
||||
}
|
||||
|
||||
body {
|
||||
counter-reset: section;
|
||||
min-height: 100vh;
|
||||
color: $ink;
|
||||
background: $beige;
|
||||
font-family: "Manrope", -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||
font-size: 18px;
|
||||
line-height: 1.6;
|
||||
font-weight: 500;
|
||||
overflow-x: hidden;
|
||||
overflow-x: clip;
|
||||
|
||||
// film grain
|
||||
&::after {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: -50%;
|
||||
z-index: 9999;
|
||||
pointer-events: none;
|
||||
opacity: 0.07;
|
||||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
|
||||
animation: grain 0.8s steps(4) infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes grain {
|
||||
0% { transform: translate(0, 0); }
|
||||
25% { transform: translate(-3%, 2%); }
|
||||
50% { transform: translate(2%, -3%); }
|
||||
75% { transform: translate(-2%, -1%); }
|
||||
100% { transform: translate(1%, 3%); }
|
||||
}
|
||||
|
||||
img,
|
||||
video,
|
||||
iframe {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
strong, b { font-weight: 700; }
|
||||
em, i { font-style: italic; }
|
||||
|
||||
::selection {
|
||||
background: $yellow;
|
||||
color: $ink;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 3px solid $orange;
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// shared section title: "01 Gewerke"
|
||||
.section-title {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
font-size: clamp(36px, 6vw, 76px);
|
||||
line-height: 1;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
|
||||
counter-increment: section;
|
||||
|
||||
&__nr {
|
||||
flex: none;
|
||||
margin-top: 0.35em;
|
||||
padding: 4px 10px;
|
||||
border: 2px solid currentColor;
|
||||
border-radius: 999px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
font-variant-numeric: tabular-nums;
|
||||
|
||||
&::before {
|
||||
content: counter(section, decimal-leading-zero);
|
||||
}
|
||||
}
|
||||
|
||||
&--light {
|
||||
color: $beige;
|
||||
}
|
||||
}
|
||||
|
||||
// buttons
|
||||
.button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px 28px 16px 18px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 999px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
box-shadow: 4px 4px 0 $ink;
|
||||
transition: transform 0.25s $ease, box-shadow 0.25s $ease;
|
||||
|
||||
&:hover {
|
||||
transform: translate(-2px, -2px) rotate(-1.5deg);
|
||||
box-shadow: 7px 7px 0 $ink;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translate(3px, 3px);
|
||||
box-shadow: 0 0 0 $ink;
|
||||
}
|
||||
|
||||
&--yellow {
|
||||
background: $yellow;
|
||||
color: $ink;
|
||||
}
|
||||
|
||||
&--outline {
|
||||
background: transparent;
|
||||
padding: 12px 22px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&__play {
|
||||
position: relative;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
flex: none;
|
||||
border-radius: 50%;
|
||||
background: $ink;
|
||||
transition: transform 0.4s $ease;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 55%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-style: solid;
|
||||
border-width: 6px 0 6px 10px;
|
||||
border-color: transparent transparent transparent $yellow;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &__play {
|
||||
transform: rotate(360deg) scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
// scroll reveal (only hidden once JS is running)
|
||||
.js [data-component~="reveal"] {
|
||||
opacity: 0;
|
||||
transform: translateY(40px) rotate(1deg);
|
||||
transition: opacity 0.8s $ease-out, transform 0.9s $ease-out;
|
||||
|
||||
&.is-visible {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
|
||||
.js [data-component~="reveal"] {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.faq {
|
||||
padding: 120px 0 0;
|
||||
|
||||
@include md {
|
||||
padding-top: 160px;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
display: grid;
|
||||
gap: 48px;
|
||||
|
||||
@include md {
|
||||
grid-template-columns: 5fr 7fr;
|
||||
gap: 64px;
|
||||
align-items: start;
|
||||
}
|
||||
}
|
||||
|
||||
&__head {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
|
||||
@include md {
|
||||
position: sticky;
|
||||
top: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
&__text {
|
||||
max-width: 40ch;
|
||||
font-size: 20px;
|
||||
|
||||
a {
|
||||
font-weight: 700;
|
||||
text-decoration: underline wavy $red;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&__list {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.faq-item {
|
||||
border: 3px solid $ink;
|
||||
border-radius: $radius;
|
||||
background: $cream;
|
||||
box-shadow: 5px 5px 0 $ink;
|
||||
transition: box-shadow 0.3s $ease, translate 0.3s $ease;
|
||||
|
||||
&:hover {
|
||||
translate: -2px -2px;
|
||||
box-shadow: 8px 8px 0 $ink;
|
||||
}
|
||||
|
||||
&[open] {
|
||||
background: $yellow;
|
||||
}
|
||||
|
||||
&__question {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 20px 24px;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: clamp(18px, 2vw, 22px);
|
||||
line-height: 1.3;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
position: relative;
|
||||
flex: none;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 50%;
|
||||
background: $cream;
|
||||
transition: rotate 0.4s $ease;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 14px;
|
||||
height: 3px;
|
||||
background: $ink;
|
||||
translate: -50% -50%;
|
||||
}
|
||||
|
||||
&::after {
|
||||
rotate: 90deg;
|
||||
}
|
||||
}
|
||||
|
||||
&[open] &__icon {
|
||||
rotate: 135deg;
|
||||
}
|
||||
|
||||
&__answer {
|
||||
padding: 0 24px 24px;
|
||||
font-size: 17px;
|
||||
|
||||
ul, ol {
|
||||
margin: 8px 0 0 20px;
|
||||
}
|
||||
|
||||
ul { list-style: disc; }
|
||||
ol { list-style: decimal; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.footer {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: 120px 0 32px;
|
||||
background: $red;
|
||||
color: $cream;
|
||||
border-top: 3px solid $ink;
|
||||
|
||||
@include md {
|
||||
padding-top: 160px;
|
||||
}
|
||||
|
||||
// big rotating "film reel" decoration
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -160px;
|
||||
top: -160px;
|
||||
width: 480px;
|
||||
height: 480px;
|
||||
border-radius: 50%;
|
||||
background:
|
||||
radial-gradient(circle at 50% 50%, $red 0 34px, transparent 35px),
|
||||
radial-gradient(circle at 50% 22%, $red 0 46px, transparent 47px),
|
||||
radial-gradient(circle at 50% 78%, $red 0 46px, transparent 47px),
|
||||
radial-gradient(circle at 22% 50%, $red 0 46px, transparent 47px),
|
||||
radial-gradient(circle at 78% 50%, $red 0 46px, transparent 47px),
|
||||
$ink;
|
||||
opacity: 0.25;
|
||||
animation: reel 18s linear infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__headline {
|
||||
font-size: clamp(56px, 12vw, 180px);
|
||||
line-height: 0.9;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.05em;
|
||||
color: $cream;
|
||||
}
|
||||
|
||||
&__text {
|
||||
max-width: 32ch;
|
||||
margin-top: 24px;
|
||||
font-size: clamp(20px, 2.4vw, 28px);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__mail {
|
||||
margin-top: 40px;
|
||||
font-size: clamp(16px, 2vw, 22px);
|
||||
}
|
||||
|
||||
&__bottom {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
margin-top: 96px;
|
||||
padding-top: 24px;
|
||||
border-top: 2px solid rgba($cream, 0.35);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
&__legal {
|
||||
display: flex;
|
||||
gap: 24px;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline wavy;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end-credits style contact list
|
||||
.credits {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
max-width: 640px;
|
||||
margin: 96px 0 0;
|
||||
|
||||
&__row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 12px;
|
||||
font-size: clamp(18px, 2vw, 22px);
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
order: 1;
|
||||
flex: 1;
|
||||
border-bottom: 2px dotted rgba($cream, 0.5);
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
dt {
|
||||
order: 0;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
dd {
|
||||
order: 2;
|
||||
margin: 0;
|
||||
font-weight: 700;
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
background: linear-gradient($yellow, $yellow) 0 100% / 0 3px no-repeat;
|
||||
transition: background-size 0.3s $ease-out;
|
||||
|
||||
&:hover {
|
||||
background-size: 100% 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes reel {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
@@ -1,966 +0,0 @@
|
||||
.container {
|
||||
max-width: 1600px;
|
||||
width: 100%;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.row {
|
||||
box-sizing: border-box;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 1 auto;
|
||||
flex: 0 1 auto;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.row.reverse {
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: reverse;
|
||||
-ms-flex-direction: row-reverse;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.col.reverse {
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: reverse;
|
||||
-ms-flex-direction: column-reverse;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.col-xs,
|
||||
.col-xs-1,
|
||||
.col-xs-2,
|
||||
.col-xs-3,
|
||||
.col-xs-4,
|
||||
.col-xs-5,
|
||||
.col-xs-6,
|
||||
.col-xs-7,
|
||||
.col-xs-8,
|
||||
.col-xs-9,
|
||||
.col-xs-10,
|
||||
.col-xs-11,
|
||||
.col-xs-12,
|
||||
.col-xs-offset-0,
|
||||
.col-xs-offset-1,
|
||||
.col-xs-offset-2,
|
||||
.col-xs-offset-3,
|
||||
.col-xs-offset-4,
|
||||
.col-xs-offset-5,
|
||||
.col-xs-offset-6,
|
||||
.col-xs-offset-7,
|
||||
.col-xs-offset-8,
|
||||
.col-xs-offset-9,
|
||||
.col-xs-offset-10,
|
||||
.col-xs-offset-11,
|
||||
.col-xs-offset-12 {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.col-xs {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
-ms-flex-preferred-size: 0;
|
||||
flex-basis: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-xs-1 {
|
||||
-ms-flex-preferred-size: 8.33333333%;
|
||||
flex-basis: 8.33333333%;
|
||||
max-width: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-2 {
|
||||
-ms-flex-preferred-size: 16.66666667%;
|
||||
flex-basis: 16.66666667%;
|
||||
max-width: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-xs-3 {
|
||||
-ms-flex-preferred-size: 25%;
|
||||
flex-basis: 25%;
|
||||
max-width: 25%;
|
||||
}
|
||||
|
||||
.col-xs-4 {
|
||||
-ms-flex-preferred-size: 33.33333333%;
|
||||
flex-basis: 33.33333333%;
|
||||
max-width: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-5 {
|
||||
-ms-flex-preferred-size: 41.66666667%;
|
||||
flex-basis: 41.66666667%;
|
||||
max-width: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-xs-6 {
|
||||
-ms-flex-preferred-size: 50%;
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.col-xs-7 {
|
||||
-ms-flex-preferred-size: 58.33333333%;
|
||||
flex-basis: 58.33333333%;
|
||||
max-width: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-8 {
|
||||
-ms-flex-preferred-size: 66.66666667%;
|
||||
flex-basis: 66.66666667%;
|
||||
max-width: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-xs-9 {
|
||||
-ms-flex-preferred-size: 75%;
|
||||
flex-basis: 75%;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
.col-xs-10 {
|
||||
-ms-flex-preferred-size: 83.33333333%;
|
||||
flex-basis: 83.33333333%;
|
||||
max-width: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-11 {
|
||||
-ms-flex-preferred-size: 91.66666667%;
|
||||
flex-basis: 91.66666667%;
|
||||
max-width: 91.66666667%;
|
||||
}
|
||||
|
||||
.col-xs-12 {
|
||||
-ms-flex-preferred-size: 100%;
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-xs-offset-0 {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.col-xs-offset-1 {
|
||||
margin-left: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-offset-2 {
|
||||
margin-left: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-xs-offset-3 {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
.col-xs-offset-4 {
|
||||
margin-left: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-offset-5 {
|
||||
margin-left: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-xs-offset-6 {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
.col-xs-offset-7 {
|
||||
margin-left: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-offset-8 {
|
||||
margin-left: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-xs-offset-9 {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
.col-xs-offset-10 {
|
||||
margin-left: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-xs-offset-11 {
|
||||
margin-left: 91.66666667%;
|
||||
}
|
||||
|
||||
.start-xs {
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
justify-content: flex-start;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.center-xs {
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.end-xs {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.top-xs {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.middle-xs {
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bottom-xs {
|
||||
-webkit-box-align: end;
|
||||
-ms-flex-align: end;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.around-xs {
|
||||
-ms-flex-pack: distribute;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.between-xs {
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.first-xs {
|
||||
-webkit-box-ordinal-group: 0;
|
||||
-ms-flex-order: -1;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.last-xs {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-ms-flex-order: 1;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 511px) {
|
||||
.hide-xs {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 512px) {
|
||||
.col-sm,
|
||||
.col-sm-1,
|
||||
.col-sm-2,
|
||||
.col-sm-3,
|
||||
.col-sm-4,
|
||||
.col-sm-5,
|
||||
.col-sm-6,
|
||||
.col-sm-7,
|
||||
.col-sm-8,
|
||||
.col-sm-9,
|
||||
.col-sm-10,
|
||||
.col-sm-11,
|
||||
.col-sm-12,
|
||||
.col-sm-offset-0,
|
||||
.col-sm-offset-1,
|
||||
.col-sm-offset-2,
|
||||
.col-sm-offset-3,
|
||||
.col-sm-offset-4,
|
||||
.col-sm-offset-5,
|
||||
.col-sm-offset-6,
|
||||
.col-sm-offset-7,
|
||||
.col-sm-offset-8,
|
||||
.col-sm-offset-9,
|
||||
.col-sm-offset-10,
|
||||
.col-sm-offset-11,
|
||||
.col-sm-offset-12 {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.col-sm {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
-ms-flex-preferred-size: 0;
|
||||
flex-basis: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-sm-1 {
|
||||
-ms-flex-preferred-size: 8.33333333%;
|
||||
flex-basis: 8.33333333%;
|
||||
max-width: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-2 {
|
||||
-ms-flex-preferred-size: 16.66666667%;
|
||||
flex-basis: 16.66666667%;
|
||||
max-width: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-sm-3 {
|
||||
-ms-flex-preferred-size: 25%;
|
||||
flex-basis: 25%;
|
||||
max-width: 25%;
|
||||
}
|
||||
|
||||
.col-sm-4 {
|
||||
-ms-flex-preferred-size: 33.33333333%;
|
||||
flex-basis: 33.33333333%;
|
||||
max-width: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-5 {
|
||||
-ms-flex-preferred-size: 41.66666667%;
|
||||
flex-basis: 41.66666667%;
|
||||
max-width: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-sm-6 {
|
||||
-ms-flex-preferred-size: 50%;
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.col-sm-7 {
|
||||
-ms-flex-preferred-size: 58.33333333%;
|
||||
flex-basis: 58.33333333%;
|
||||
max-width: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-8 {
|
||||
-ms-flex-preferred-size: 66.66666667%;
|
||||
flex-basis: 66.66666667%;
|
||||
max-width: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-sm-9 {
|
||||
-ms-flex-preferred-size: 75%;
|
||||
flex-basis: 75%;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
.col-sm-10 {
|
||||
-ms-flex-preferred-size: 83.33333333%;
|
||||
flex-basis: 83.33333333%;
|
||||
max-width: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-11 {
|
||||
-ms-flex-preferred-size: 91.66666667%;
|
||||
flex-basis: 91.66666667%;
|
||||
max-width: 91.66666667%;
|
||||
}
|
||||
|
||||
.col-sm-12 {
|
||||
-ms-flex-preferred-size: 100%;
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-sm-offset-0 {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.col-sm-offset-1 {
|
||||
margin-left: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-offset-2 {
|
||||
margin-left: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-sm-offset-3 {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
.col-sm-offset-4 {
|
||||
margin-left: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-offset-5 {
|
||||
margin-left: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-sm-offset-6 {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
.col-sm-offset-7 {
|
||||
margin-left: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-offset-8 {
|
||||
margin-left: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-sm-offset-9 {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
.col-sm-offset-10 {
|
||||
margin-left: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-sm-offset-11 {
|
||||
margin-left: 91.66666667%;
|
||||
}
|
||||
|
||||
.start-sm {
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
justify-content: flex-start;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.center-sm {
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.end-sm {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.top-sm {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.middle-sm {
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bottom-sm {
|
||||
-webkit-box-align: end;
|
||||
-ms-flex-align: end;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.around-sm {
|
||||
-ms-flex-pack: distribute;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.between-sm {
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.first-sm {
|
||||
-webkit-box-ordinal-group: 0;
|
||||
-ms-flex-order: -1;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.last-sm {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-ms-flex-order: 1;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.show-xs {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.hide-sm {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 768px) {
|
||||
.col-md,
|
||||
.col-md-1,
|
||||
.col-md-2,
|
||||
.col-md-3,
|
||||
.col-md-4,
|
||||
.col-md-5,
|
||||
.col-md-6,
|
||||
.col-md-7,
|
||||
.col-md-8,
|
||||
.col-md-9,
|
||||
.col-md-10,
|
||||
.col-md-11,
|
||||
.col-md-12,
|
||||
.col-md-offset-0,
|
||||
.col-md-offset-1,
|
||||
.col-md-offset-2,
|
||||
.col-md-offset-3,
|
||||
.col-md-offset-4,
|
||||
.col-md-offset-5,
|
||||
.col-md-offset-6,
|
||||
.col-md-offset-7,
|
||||
.col-md-offset-8,
|
||||
.col-md-offset-9,
|
||||
.col-md-offset-10,
|
||||
.col-md-offset-11,
|
||||
.col-md-offset-12 {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.col-md {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
-ms-flex-preferred-size: 0;
|
||||
flex-basis: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-md-1 {
|
||||
-ms-flex-preferred-size: 8.33333333%;
|
||||
flex-basis: 8.33333333%;
|
||||
max-width: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-md-2 {
|
||||
-ms-flex-preferred-size: 16.66666667%;
|
||||
flex-basis: 16.66666667%;
|
||||
max-width: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-md-3 {
|
||||
-ms-flex-preferred-size: 25%;
|
||||
flex-basis: 25%;
|
||||
max-width: 25%;
|
||||
}
|
||||
|
||||
.col-md-4 {
|
||||
-ms-flex-preferred-size: 33.33333333%;
|
||||
flex-basis: 33.33333333%;
|
||||
max-width: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-md-5 {
|
||||
-ms-flex-preferred-size: 41.66666667%;
|
||||
flex-basis: 41.66666667%;
|
||||
max-width: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-md-6 {
|
||||
-ms-flex-preferred-size: 50%;
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.col-md-7 {
|
||||
-ms-flex-preferred-size: 58.33333333%;
|
||||
flex-basis: 58.33333333%;
|
||||
max-width: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-md-8 {
|
||||
-ms-flex-preferred-size: 66.66666667%;
|
||||
flex-basis: 66.66666667%;
|
||||
max-width: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-md-9 {
|
||||
-ms-flex-preferred-size: 75%;
|
||||
flex-basis: 75%;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
.col-md-10 {
|
||||
-ms-flex-preferred-size: 83.33333333%;
|
||||
flex-basis: 83.33333333%;
|
||||
max-width: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-md-11 {
|
||||
-ms-flex-preferred-size: 91.66666667%;
|
||||
flex-basis: 91.66666667%;
|
||||
max-width: 91.66666667%;
|
||||
}
|
||||
|
||||
.col-md-12 {
|
||||
-ms-flex-preferred-size: 100%;
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-md-offset-0 {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.col-md-offset-1 {
|
||||
margin-left: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-md-offset-2 {
|
||||
margin-left: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-md-offset-3 {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
.col-md-offset-4 {
|
||||
margin-left: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-md-offset-5 {
|
||||
margin-left: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-md-offset-6 {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
.col-md-offset-7 {
|
||||
margin-left: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-md-offset-8 {
|
||||
margin-left: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-md-offset-9 {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
.col-md-offset-10 {
|
||||
margin-left: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-md-offset-11 {
|
||||
margin-left: 91.66666667%;
|
||||
}
|
||||
|
||||
.start-md {
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
justify-content: flex-start;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.center-md {
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.end-md {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.top-md {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.middle-md {
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bottom-md {
|
||||
-webkit-box-align: end;
|
||||
-ms-flex-align: end;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.around-md {
|
||||
-ms-flex-pack: distribute;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.between-md {
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.first-md {
|
||||
-webkit-box-ordinal-group: 0;
|
||||
-ms-flex-order: -1;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.last-md {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-ms-flex-order: 1;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.show-sm {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1023px) {
|
||||
.hide-md {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1024px) {
|
||||
.col-lg,
|
||||
.col-lg-1,
|
||||
.col-lg-2,
|
||||
.col-lg-3,
|
||||
.col-lg-4,
|
||||
.col-lg-5,
|
||||
.col-lg-6,
|
||||
.col-lg-7,
|
||||
.col-lg-8,
|
||||
.col-lg-9,
|
||||
.col-lg-10,
|
||||
.col-lg-11,
|
||||
.col-lg-12,
|
||||
.col-lg-offset-0,
|
||||
.col-lg-offset-1,
|
||||
.col-lg-offset-2,
|
||||
.col-lg-offset-3,
|
||||
.col-lg-offset-4,
|
||||
.col-lg-offset-5,
|
||||
.col-lg-offset-6,
|
||||
.col-lg-offset-7,
|
||||
.col-lg-offset-8,
|
||||
.col-lg-offset-9,
|
||||
.col-lg-offset-10,
|
||||
.col-lg-offset-11,
|
||||
.col-lg-offset-12 {
|
||||
box-sizing: border-box;
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.col-lg {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
-ms-flex-preferred-size: 0;
|
||||
flex-basis: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-lg-1 {
|
||||
-ms-flex-preferred-size: 8.33333333%;
|
||||
flex-basis: 8.33333333%;
|
||||
max-width: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-2 {
|
||||
-ms-flex-preferred-size: 16.66666667%;
|
||||
flex-basis: 16.66666667%;
|
||||
max-width: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-lg-3 {
|
||||
-ms-flex-preferred-size: 25%;
|
||||
flex-basis: 25%;
|
||||
max-width: 25%;
|
||||
}
|
||||
|
||||
.col-lg-4 {
|
||||
-ms-flex-preferred-size: 33.33333333%;
|
||||
flex-basis: 33.33333333%;
|
||||
max-width: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-5 {
|
||||
-ms-flex-preferred-size: 41.66666667%;
|
||||
flex-basis: 41.66666667%;
|
||||
max-width: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-lg-6 {
|
||||
-ms-flex-preferred-size: 50%;
|
||||
flex-basis: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.col-lg-7 {
|
||||
-ms-flex-preferred-size: 58.33333333%;
|
||||
flex-basis: 58.33333333%;
|
||||
max-width: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-8 {
|
||||
-ms-flex-preferred-size: 66.66666667%;
|
||||
flex-basis: 66.66666667%;
|
||||
max-width: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-lg-9 {
|
||||
-ms-flex-preferred-size: 75%;
|
||||
flex-basis: 75%;
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
.col-lg-10 {
|
||||
-ms-flex-preferred-size: 83.33333333%;
|
||||
flex-basis: 83.33333333%;
|
||||
max-width: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-11 {
|
||||
-ms-flex-preferred-size: 91.66666667%;
|
||||
flex-basis: 91.66666667%;
|
||||
max-width: 91.66666667%;
|
||||
}
|
||||
|
||||
.col-lg-12 {
|
||||
-ms-flex-preferred-size: 100%;
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.col-lg-offset-0 {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.col-lg-offset-1 {
|
||||
margin-left: 8.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-offset-2 {
|
||||
margin-left: 16.66666667%;
|
||||
}
|
||||
|
||||
.col-lg-offset-3 {
|
||||
margin-left: 25%;
|
||||
}
|
||||
|
||||
.col-lg-offset-4 {
|
||||
margin-left: 33.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-offset-5 {
|
||||
margin-left: 41.66666667%;
|
||||
}
|
||||
|
||||
.col-lg-offset-6 {
|
||||
margin-left: 50%;
|
||||
}
|
||||
|
||||
.col-lg-offset-7 {
|
||||
margin-left: 58.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-offset-8 {
|
||||
margin-left: 66.66666667%;
|
||||
}
|
||||
|
||||
.col-lg-offset-9 {
|
||||
margin-left: 75%;
|
||||
}
|
||||
|
||||
.col-lg-offset-10 {
|
||||
margin-left: 83.33333333%;
|
||||
}
|
||||
|
||||
.col-lg-offset-11 {
|
||||
margin-left: 91.66666667%;
|
||||
}
|
||||
|
||||
.start-lg {
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
justify-content: flex-start;
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.center-lg {
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.end-lg {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.top-lg {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.middle-lg {
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bottom-lg {
|
||||
-webkit-box-align: end;
|
||||
-ms-flex-align: end;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.around-lg {
|
||||
-ms-flex-pack: distribute;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.between-lg {
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.first-lg {
|
||||
-webkit-box-ordinal-group: 0;
|
||||
-ms-flex-order: -1;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.last-lg {
|
||||
-webkit-box-ordinal-group: 2;
|
||||
-ms-flex-order: 1;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.show-md {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.insta {
|
||||
padding: 120px 0;
|
||||
|
||||
@include md {
|
||||
padding: 160px 0;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
}
|
||||
|
||||
&__head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
margin-bottom: 56px;
|
||||
}
|
||||
|
||||
&__frame {
|
||||
padding: 16px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: $radius-lg;
|
||||
background: $cream;
|
||||
box-shadow: 10px 10px 0 $pink;
|
||||
transform: rotate(-0.75deg);
|
||||
}
|
||||
|
||||
&__widget {
|
||||
width: 100%;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
border-radius: $radius - 6px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.intro {
|
||||
position: relative;
|
||||
// the rotated, wider-than-viewport ticker must not create horizontal scrolling
|
||||
overflow-x: clip;
|
||||
padding: 48px 0 0;
|
||||
|
||||
@include md {
|
||||
padding-top: 72px;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__kicker {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
padding: 6px 14px;
|
||||
border-radius: 999px;
|
||||
background: $ink;
|
||||
color: $beige;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
rotate: -2deg;
|
||||
}
|
||||
|
||||
&__kicker-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: $red;
|
||||
animation: blink 1s steps(1) infinite;
|
||||
}
|
||||
|
||||
&__headline {
|
||||
max-width: 16ch;
|
||||
font-size: clamp(34px, 8.6vw, 150px);
|
||||
hyphens: auto;
|
||||
line-height: 0.92;
|
||||
// background-clip: text only paints inside the box; keep descenders (g, p, …) visible
|
||||
padding-bottom: 0.3em;
|
||||
margin-bottom: -0.3em;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.045em;
|
||||
background: linear-gradient(100deg, $ink 0 48%, $red 68%, $orange 88%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
&__text {
|
||||
max-width: 52ch;
|
||||
margin-top: 28px;
|
||||
font-size: clamp(18px, 1.6vw, 22px);
|
||||
line-height: 1.55;
|
||||
|
||||
strong { font-weight: 800; }
|
||||
}
|
||||
|
||||
&__cta {
|
||||
margin-top: 32px;
|
||||
|
||||
@include md {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 48px;
|
||||
margin: 0;
|
||||
rotate: 4deg;
|
||||
transition: rotate 0.4s $ease, opacity 0.8s $ease-out, transform 0.9s $ease-out;
|
||||
|
||||
&:hover {
|
||||
rotate: -2deg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes blink {
|
||||
50% { opacity: 0; }
|
||||
}
|
||||
|
||||
.viewfinder {
|
||||
position: relative;
|
||||
margin-top: 48px;
|
||||
overflow: hidden;
|
||||
border: 3px solid $ink;
|
||||
border-radius: $radius-lg;
|
||||
background: $ink;
|
||||
box-shadow: 10px 10px 0 $orange;
|
||||
// no min-height here: with aspect-ratio it is transferred to a min-width and overflows on small screens
|
||||
width: 100%;
|
||||
aspect-ratio: 4 / 3;
|
||||
|
||||
@include sm {
|
||||
aspect-ratio: 16 / 9;
|
||||
}
|
||||
|
||||
@include md {
|
||||
margin-top: 64px;
|
||||
box-shadow: 16px 16px 0 $orange;
|
||||
}
|
||||
|
||||
&__video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
&__overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
color: #fff;
|
||||
font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.08em;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
|
||||
|
||||
@include md {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&__corner {
|
||||
position: absolute;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border: 0 solid rgba(#fff, 0.9);
|
||||
|
||||
&--tl { top: 20px; left: 20px; border-top-width: 3px; border-left-width: 3px; }
|
||||
&--tr { top: 20px; right: 20px; border-top-width: 3px; border-right-width: 3px; }
|
||||
&--bl { bottom: 20px; left: 20px; border-bottom-width: 3px; border-left-width: 3px; }
|
||||
&--br { bottom: 20px; right: 20px; border-bottom-width: 3px; border-right-width: 3px; }
|
||||
}
|
||||
|
||||
&__rec {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 70px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: $red;
|
||||
animation: blink 1s steps(1) infinite;
|
||||
}
|
||||
}
|
||||
|
||||
&__timecode {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 70px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
&__meta {
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
left: 70px;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
&__battery {
|
||||
position: absolute;
|
||||
right: 74px;
|
||||
bottom: 32px;
|
||||
width: 30px;
|
||||
height: 14px;
|
||||
border: 2px solid #fff;
|
||||
border-radius: 3px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 2px 30% 2px 2px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: -5px;
|
||||
width: 3px;
|
||||
height: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&__focus {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
transform: translate(-50%, -50%);
|
||||
border: 2px solid rgba($yellow, 0.9);
|
||||
animation: focus-hunt 5s $ease infinite;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: rgba($yellow, 0.9);
|
||||
}
|
||||
|
||||
&::before { top: 50%; left: 50%; width: 12px; height: 2px; transform: translate(-50%, -50%); }
|
||||
&::after { top: 50%; left: 50%; width: 2px; height: 12px; transform: translate(-50%, -50%); }
|
||||
}
|
||||
|
||||
@media (max-width: 639px) {
|
||||
&__meta,
|
||||
&__battery {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__rec { left: 32px; top: 28px; }
|
||||
&__timecode { right: 32px; top: 28px; }
|
||||
&__corner { width: 22px; height: 22px; }
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes focus-hunt {
|
||||
0%, 100% { transform: translate(-50%, -50%) scale(1); }
|
||||
10% { transform: translate(-50%, -50%) scale(1.25); }
|
||||
18% { transform: translate(-50%, -50%) scale(0.9); }
|
||||
24% { transform: translate(-50%, -50%) scale(1); }
|
||||
60% { transform: translate(-30%, -60%) scale(1); }
|
||||
70% { transform: translate(-30%, -60%) scale(1.2); }
|
||||
76% { transform: translate(-30%, -60%) scale(1); }
|
||||
}
|
||||
|
||||
.ticker {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
margin: 72px -5vw 0;
|
||||
padding: 18px 0;
|
||||
overflow: hidden;
|
||||
border-block: 3px solid $ink;
|
||||
background: $yellow;
|
||||
transform: rotate(-2deg);
|
||||
|
||||
@include md {
|
||||
margin-top: 96px;
|
||||
}
|
||||
|
||||
&__track {
|
||||
display: flex;
|
||||
width: max-content;
|
||||
animation: ticker 40s linear infinite;
|
||||
|
||||
span {
|
||||
padding-right: 0.5em;
|
||||
white-space: nowrap;
|
||||
font-size: clamp(24px, 4vw, 44px);
|
||||
line-height: 1;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.02em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &__track {
|
||||
animation-play-state: paused;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ticker {
|
||||
to { transform: translateX(-50%); }
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
padding: 12px 0;
|
||||
transition: padding 0.3s $ease-out;
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
&__brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 18px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 999px;
|
||||
background: $cream;
|
||||
box-shadow: 4px 4px 0 $ink;
|
||||
text-decoration: none;
|
||||
font-size: 22px;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.02em;
|
||||
transition: transform 0.3s $ease;
|
||||
|
||||
&:hover {
|
||||
transform: rotate(-3deg) scale(1.04);
|
||||
}
|
||||
}
|
||||
|
||||
&__rec {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: $red;
|
||||
box-shadow: 0 0 0 0 rgba($red, 0.6);
|
||||
animation: rec-pulse 1.6s infinite;
|
||||
}
|
||||
|
||||
&__word {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__cut {
|
||||
display: inline-block;
|
||||
margin: 0 1px;
|
||||
color: $orange;
|
||||
font-size: 0.75em;
|
||||
transform: rotate(-90deg);
|
||||
transition: transform 0.5s $ease;
|
||||
}
|
||||
|
||||
&__brand:hover &__cut {
|
||||
transform: rotate(-90deg) translateY(-3px) scaleX(0.6);
|
||||
}
|
||||
|
||||
&__toggle {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
padding: 0 14px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 50%;
|
||||
background: $yellow;
|
||||
box-shadow: 4px 4px 0 $ink;
|
||||
cursor: pointer;
|
||||
|
||||
@include md {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__toggle-bar {
|
||||
display: block;
|
||||
height: 3px;
|
||||
border-radius: 3px;
|
||||
background: $ink;
|
||||
transition: transform 0.3s $ease;
|
||||
}
|
||||
|
||||
&--open &__toggle-bar:first-child { transform: translateY(4.5px) rotate(45deg); }
|
||||
&--open &__toggle-bar:nth-child(2) { transform: translateY(-4.5px) rotate(-45deg); }
|
||||
|
||||
&__links {
|
||||
display: none;
|
||||
gap: 8px;
|
||||
padding: 6px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 999px;
|
||||
background: $cream;
|
||||
box-shadow: 4px 4px 0 $ink;
|
||||
|
||||
@include md {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
&__link {
|
||||
position: relative;
|
||||
padding: 8px 18px;
|
||||
border-radius: 999px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
transition: background 0.2s, transform 0.3s $ease;
|
||||
|
||||
&:hover {
|
||||
background: $ink;
|
||||
color: $beige;
|
||||
transform: rotate(-2deg);
|
||||
}
|
||||
|
||||
&--cta {
|
||||
background: $red;
|
||||
color: $cream;
|
||||
}
|
||||
}
|
||||
|
||||
// mobile overlay menu
|
||||
&--open &__links {
|
||||
position: fixed;
|
||||
inset: 84px 16px auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
padding: 16px;
|
||||
border-radius: $radius-lg;
|
||||
animation: menu-pop 0.4s $ease;
|
||||
|
||||
.nav__link {
|
||||
padding: 16px 20px;
|
||||
font-size: 28px;
|
||||
font-weight: 800;
|
||||
|
||||
&::before {
|
||||
content: attr(data-nr);
|
||||
margin-right: 12px;
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rec-pulse {
|
||||
0% { box-shadow: 0 0 0 0 rgba($red, 0.6); opacity: 1; }
|
||||
50% { opacity: 0.35; }
|
||||
70% { box-shadow: 0 0 0 10px rgba($red, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba($red, 0); opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes menu-pop {
|
||||
from { opacity: 0; transform: scale(0.9) rotate(-2deg); }
|
||||
to { opacity: 1; transform: none; }
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.process {
|
||||
padding: 0 0 120px;
|
||||
|
||||
@include md {
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
}
|
||||
|
||||
&__head {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
margin-bottom: 64px;
|
||||
|
||||
@include md {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: end;
|
||||
}
|
||||
}
|
||||
|
||||
&__text {
|
||||
max-width: 46ch;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
&__steps {
|
||||
counter-reset: frame;
|
||||
display: grid;
|
||||
gap: 28px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
@include sm {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@include lg {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// storyboard frame
|
||||
.frame {
|
||||
--frame-color: #{$yellow};
|
||||
counter-increment: frame;
|
||||
position: relative;
|
||||
padding: 28px 24px 32px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: $radius;
|
||||
background: $cream;
|
||||
box-shadow: 8px 8px 0 var(--frame-color);
|
||||
transition: rotate 0.4s $ease, translate 0.4s $ease;
|
||||
|
||||
@each $name, $color in $colors {
|
||||
&--#{$name} {
|
||||
--frame-color: #{$color};
|
||||
}
|
||||
}
|
||||
|
||||
&:nth-child(odd) { rotate: -1.2deg; }
|
||||
&:nth-child(even) { rotate: 1.2deg; }
|
||||
|
||||
&:hover {
|
||||
rotate: 0deg;
|
||||
translate: 0 -6px;
|
||||
}
|
||||
|
||||
// dashed arrow to the next frame
|
||||
@include lg {
|
||||
&:not(:last-child)::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: -26px;
|
||||
width: 22px;
|
||||
border-top: 3px dashed $ink;
|
||||
}
|
||||
}
|
||||
|
||||
&__nr {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-bottom: 20px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 50%;
|
||||
background: var(--frame-color);
|
||||
font-size: 22px;
|
||||
font-weight: 800;
|
||||
|
||||
&::before {
|
||||
content: counter(frame);
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 24px;
|
||||
line-height: 1.2;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
&__text {
|
||||
margin-top: 10px;
|
||||
font-size: 17px;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: none;
|
||||
font: inherit;
|
||||
text-decoration: none;
|
||||
vertical-align: baseline;
|
||||
@@ -54,5 +53,4 @@ table {
|
||||
}
|
||||
|
||||
textarea:focus, input:focus, button:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.service {
|
||||
padding: 120px 0;
|
||||
|
||||
@include md {
|
||||
padding: 160px 0;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
}
|
||||
|
||||
&__head {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
margin-bottom: 64px;
|
||||
|
||||
@include md {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: end;
|
||||
}
|
||||
}
|
||||
|
||||
&__text {
|
||||
max-width: 46ch;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
&__grid {
|
||||
display: grid;
|
||||
gap: 56px;
|
||||
|
||||
@include md {
|
||||
grid-template-columns: 5fr 7fr;
|
||||
align-items: start;
|
||||
gap: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
&__items {
|
||||
display: grid;
|
||||
gap: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.polaroid {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 16px 16px 72px;
|
||||
border: 3px solid $ink;
|
||||
background: $cream;
|
||||
box-shadow: 10px 10px 0 $ink;
|
||||
rotate: 2.5deg;
|
||||
transition: rotate 0.5s $ease, scale 0.5s $ease, opacity 0.8s $ease-out, transform 0.9s $ease-out;
|
||||
|
||||
@include md {
|
||||
position: sticky;
|
||||
top: 120px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
rotate: -1deg;
|
||||
scale: 1.02;
|
||||
}
|
||||
|
||||
// tape
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
left: 50%;
|
||||
width: 140px;
|
||||
height: 36px;
|
||||
transform: translateX(-50%) rotate(-4deg);
|
||||
background: rgba($yellow, 0.85);
|
||||
border: 2px dashed rgba($ink, 0.25);
|
||||
}
|
||||
|
||||
&__image {
|
||||
width: 100%;
|
||||
aspect-ratio: 4 / 3;
|
||||
object-fit: cover;
|
||||
object-position: center 33%;
|
||||
border: 3px solid $ink;
|
||||
}
|
||||
|
||||
&__caption {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 18px;
|
||||
left: 16px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
transform: rotate(-1deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.slate {
|
||||
--slate-color: #{$red};
|
||||
position: relative;
|
||||
counter-increment: slate;
|
||||
padding-top: 30px;
|
||||
|
||||
@each $name, $color in $colors {
|
||||
&--#{$name} {
|
||||
--slate-color: #{$color};
|
||||
}
|
||||
}
|
||||
|
||||
&__clapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 34px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 10px 10px 0 0;
|
||||
background: repeating-linear-gradient(
|
||||
-55deg,
|
||||
var(--slate-color) 0 20px,
|
||||
$ink 20px 40px
|
||||
);
|
||||
transform-origin: 6px 100%;
|
||||
transform: rotate(-9deg);
|
||||
transition: transform 0.35s $ease;
|
||||
|
||||
// hinge
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
bottom: -9px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 50%;
|
||||
background: $cream;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &__clapper {
|
||||
animation: clap 0.45s $ease;
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
&__body {
|
||||
position: relative;
|
||||
padding: 28px 28px 28px;
|
||||
border: 3px solid $ink;
|
||||
border-radius: 0 0 $radius $radius;
|
||||
background: $ink;
|
||||
color: $beige;
|
||||
box-shadow: 8px 8px 0 var(--slate-color);
|
||||
transition: transform 0.35s $ease, box-shadow 0.35s $ease;
|
||||
|
||||
// top stripe bar of the slate body
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 14px;
|
||||
background: repeating-linear-gradient(
|
||||
-55deg,
|
||||
var(--slate-color) 0 20px,
|
||||
$ink 20px 40px
|
||||
);
|
||||
border-bottom: 3px solid $ink;
|
||||
}
|
||||
|
||||
// "SCENE 01"
|
||||
&::after {
|
||||
content: "Szene 0" counter(slate);
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 24px;
|
||||
font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &__body {
|
||||
transform: translate(-3px, -3px);
|
||||
box-shadow: 12px 12px 0 var(--slate-color);
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin-top: 12px;
|
||||
font-size: clamp(32px, 4vw, 48px);
|
||||
line-height: 1.1;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
color: var(--slate-color);
|
||||
}
|
||||
|
||||
&__text {
|
||||
margin-top: 8px;
|
||||
font-size: 18px;
|
||||
color: rgba($beige, 0.85);
|
||||
}
|
||||
|
||||
// playful alternating tilt
|
||||
&:nth-child(odd) { rotate: -1deg; }
|
||||
&:nth-child(even) { rotate: 1deg; }
|
||||
}
|
||||
|
||||
.service__items {
|
||||
counter-reset: slate;
|
||||
}
|
||||
|
||||
@keyframes clap {
|
||||
0% { transform: rotate(-9deg); }
|
||||
40% { transform: rotate(-22deg); }
|
||||
70% { transform: rotate(1deg); }
|
||||
100% { transform: rotate(0); }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.text {
|
||||
padding: 72px 0 120px;
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
max-width: 880px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 40px;
|
||||
font-size: clamp(40px, 6vw, 72px);
|
||||
line-height: 1;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
display: inline-block;
|
||||
margin: 40px 0 12px;
|
||||
padding: 4px 12px;
|
||||
background: $yellow;
|
||||
border: 2px solid $ink;
|
||||
border-radius: 8px;
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
transform: rotate(-1deg);
|
||||
}
|
||||
|
||||
.text__date {
|
||||
margin-top: 40px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 16px;
|
||||
font-size: 17px;
|
||||
line-height: 1.7;
|
||||
hyphens: auto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
$beige: #f7eee0;
|
||||
$cream: #fff8ec;
|
||||
$yellow: #febb28;
|
||||
$orange: #fe6732;
|
||||
$red: #f5303c;
|
||||
$pink: #ce2867;
|
||||
$purple: #571b47;
|
||||
$ink: #0e0c0b;
|
||||
$grey: #3d3d3d;
|
||||
|
||||
$max-width: 1440px;
|
||||
$radius: 20px;
|
||||
$radius-lg: 32px;
|
||||
$ease: cubic-bezier(0.34, 1.56, 0.64, 1); // springy
|
||||
$ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
||||
$shadow: 6px 6px 0 $ink;
|
||||
|
||||
$colors: (
|
||||
"red": $red,
|
||||
"orange": $orange,
|
||||
"yellow": $yellow,
|
||||
"pink": $pink,
|
||||
"purple": $purple
|
||||
);
|
||||
|
||||
@mixin sm {
|
||||
@media (min-width: 640px) { @content; }
|
||||
}
|
||||
|
||||
@mixin md {
|
||||
@media (min-width: 900px) { @content; }
|
||||
}
|
||||
|
||||
@mixin lg {
|
||||
@media (min-width: 1200px) { @content; }
|
||||
}
|
||||
|
||||
@mixin inner {
|
||||
width: 100%;
|
||||
max-width: $max-width;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
|
||||
@include md {
|
||||
padding: 0 48px;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin stripes($color, $size: 22px) {
|
||||
background: repeating-linear-gradient(
|
||||
-45deg,
|
||||
$color 0 $size,
|
||||
$ink $size ($size * 2)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.work {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
background: $ink;
|
||||
color: $beige;
|
||||
counter-reset: take;
|
||||
|
||||
&__inner {
|
||||
@include inner;
|
||||
padding-top: 120px;
|
||||
padding-bottom: 120px;
|
||||
|
||||
@include md {
|
||||
padding-top: 160px;
|
||||
padding-bottom: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
&__head {
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
margin-bottom: 80px;
|
||||
|
||||
@include md {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: end;
|
||||
}
|
||||
}
|
||||
|
||||
&__text {
|
||||
max-width: 46ch;
|
||||
font-size: 20px;
|
||||
color: rgba($beige, 0.8);
|
||||
}
|
||||
|
||||
&__list {
|
||||
display: grid;
|
||||
gap: 96px;
|
||||
|
||||
@include md {
|
||||
gap: 140px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sprocket holes
|
||||
.filmstrip {
|
||||
height: 44px;
|
||||
background-color: $ink;
|
||||
background-image: radial-gradient(ellipse 9px 8px at center, $beige 96%, transparent 100%);
|
||||
background-size: 40px 20px;
|
||||
background-position: 0 12px;
|
||||
background-repeat: repeat-x;
|
||||
animation: filmstrip 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes filmstrip {
|
||||
to { background-position: 40px 12px; }
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
@use "variables" as *;
|
||||
|
||||
.take {
|
||||
counter-increment: take;
|
||||
display: grid;
|
||||
gap: 32px;
|
||||
align-items: center;
|
||||
|
||||
@include md {
|
||||
grid-template-columns: 4fr 8fr;
|
||||
gap: 64px;
|
||||
|
||||
&:nth-child(even) {
|
||||
grid-template-columns: 8fr 4fr;
|
||||
|
||||
.take__info { order: 2; }
|
||||
.take__screen { order: 1; transform: rotate(1.5deg); }
|
||||
}
|
||||
}
|
||||
|
||||
&__info {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 14px;
|
||||
border: 2px solid $beige;
|
||||
border-radius: 8px;
|
||||
font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
|
||||
&::after {
|
||||
content: counter(take, decimal-leading-zero);
|
||||
padding-left: 8px;
|
||||
border-left: 2px solid $beige;
|
||||
color: $yellow;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin-top: 20px;
|
||||
font-size: clamp(32px, 4.5vw, 56px);
|
||||
line-height: 1.05;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
&__text {
|
||||
margin-top: 16px;
|
||||
color: rgba($beige, 0.75);
|
||||
}
|
||||
|
||||
&__screen {
|
||||
position: relative;
|
||||
aspect-ratio: 16 / 9;
|
||||
border: 3px solid $beige;
|
||||
border-radius: $radius;
|
||||
overflow: hidden;
|
||||
background: #000;
|
||||
transform: rotate(-1.5deg);
|
||||
transition: transform 0.5s $ease, box-shadow 0.5s $ease;
|
||||
box-shadow: 10px 10px 0 var(--take-color, #{$red});
|
||||
}
|
||||
|
||||
&:hover &__screen {
|
||||
transform: rotate(0) scale(1.02);
|
||||
box-shadow: 16px 16px 0 var(--take-color, #{$red});
|
||||
}
|
||||
|
||||
&:nth-child(4n+1) { --take-color: #{$pink}; }
|
||||
&:nth-child(4n+2) { --take-color: #{$red}; }
|
||||
&:nth-child(4n+3) { --take-color: #{$orange}; }
|
||||
&:nth-child(4n+4) { --take-color: #{$yellow}; }
|
||||
|
||||
&:hover &__title {
|
||||
color: var(--take-color);
|
||||
}
|
||||
|
||||
&__title {
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
&__video {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
+13
-833
@@ -1,833 +1,13 @@
|
||||
@import "_reset.scss";
|
||||
@import "_grid.scss";
|
||||
|
||||
* {
|
||||
color: var(--black);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
color: var(--black);
|
||||
font-family: "Manrope", -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
|
||||
--white: #fff;
|
||||
--beige: #f7eee0;
|
||||
--yellow: #febb28;
|
||||
--orange: #fe6732;
|
||||
--red: #f5303c;
|
||||
--pink: #ce2867;
|
||||
--purple: #571b47;
|
||||
--grey: #3d3d3d;
|
||||
--black: #000;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--beige);
|
||||
padding: 0 16px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
section {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, p {
|
||||
margin-block-start: 0;
|
||||
margin-block-end: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 96px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
|
||||
a {
|
||||
color: var(--red);
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button, a.button {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
padding: 16px 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
[data-aos="fade-in"] {
|
||||
opacity: 0;
|
||||
transition-property: opacity;
|
||||
|
||||
&.aos-animate {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 64px;
|
||||
width: 100%;
|
||||
background-color: var(--beige);
|
||||
z-index: 100;
|
||||
-webkit-backface-visibility: hidden; /* Correct fixed positioning on mobile */
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.wordmark {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
text-align: right;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
margin-left: 48px;
|
||||
font-size: 18px;
|
||||
line-height: 1.5;
|
||||
font-weight: 500;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
|
||||
&:nth-of-type(1):hover::before {
|
||||
background-color: var(--pink);
|
||||
}
|
||||
|
||||
&:nth-of-type(2):hover::before {
|
||||
background-color: var(--red);
|
||||
}
|
||||
|
||||
&:nth-of-type(3):hover::before {
|
||||
background-color: var(--orange);
|
||||
}
|
||||
|
||||
&:nth-of-type(4):hover::before {
|
||||
background-color: var(--yellow);
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 2px;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-menu {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
z-index: 1000;
|
||||
animation: fade-in 0.2s ease-in-out;
|
||||
-webkit-backface-visibility: hidden; /* Correct fixed positioning on mobile */
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
line-height: 64px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.section-start {
|
||||
padding: 128px 0;
|
||||
|
||||
.headline {
|
||||
display: flex;
|
||||
margin-bottom: 96px;
|
||||
|
||||
h1 {
|
||||
flex: 1;
|
||||
|
||||
a {
|
||||
color: var(--red);
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.hero {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
|
||||
video {
|
||||
height: 100%;
|
||||
min-height: 512px;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
transform: scale(1.004);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-service {
|
||||
padding: 128px 0;
|
||||
|
||||
h2 {
|
||||
margin: 0 64px 24px 0;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 8px solid;
|
||||
|
||||
&:nth-of-type(1) {
|
||||
border-color: var(--red);
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
border-color: var(--orange);
|
||||
}
|
||||
|
||||
&:nth-of-type(3) {
|
||||
border-color: var(--yellow);
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 64px 64px 0;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
min-height: 512px;
|
||||
background-image: url("1.jpg");
|
||||
background-position: center 33%;
|
||||
background-size: cover;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.section-work {
|
||||
padding: 128px 0;
|
||||
|
||||
.video {
|
||||
margin-bottom: 128px;
|
||||
|
||||
&:nth-of-type(4n+1) h2 {
|
||||
border-color: var(--pink);
|
||||
}
|
||||
|
||||
&:nth-of-type(4n+2) h2 {
|
||||
border-color: var(--red);
|
||||
}
|
||||
|
||||
&:nth-of-type(4n+3) h2 {
|
||||
border-color: var(--orange);
|
||||
}
|
||||
|
||||
&:nth-of-type(4n+4) h2 {
|
||||
border-color: var(--yellow);
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0 0 24px 64px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 8px solid;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-left: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-rental {
|
||||
padding: 128px 0;
|
||||
|
||||
.square {
|
||||
position: sticky;
|
||||
top: 128px;
|
||||
padding: 32px 0;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 8px solid var(--red);
|
||||
}
|
||||
|
||||
button, a.button {
|
||||
display: inline-flex;
|
||||
color: var(--black);
|
||||
margin: 48px 12px 0 0;
|
||||
|
||||
&:hover {
|
||||
box-shadow: inset 0 0 0 2px var(--black);
|
||||
}
|
||||
|
||||
&.primary {
|
||||
background-color: var(--yellow);
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
background-color: var(--orange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.parts {
|
||||
position: relative;
|
||||
max-width: 720px;
|
||||
min-height: 256px;
|
||||
margin: 0 auto;
|
||||
|
||||
img:not(#part0) {
|
||||
position: absolute;
|
||||
filter: contrast(1.3) saturate(0.6);
|
||||
}
|
||||
|
||||
#part0 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#part1 {
|
||||
width: 29%;
|
||||
left: 34%;
|
||||
}
|
||||
|
||||
#part2 {
|
||||
width: 8.5%;
|
||||
left: 24%;
|
||||
margin-top: 2%;
|
||||
}
|
||||
|
||||
#part3 {
|
||||
width: 19%;
|
||||
left: 0;
|
||||
margin-top: 2%;
|
||||
}
|
||||
|
||||
#part4 {
|
||||
width: 17%;
|
||||
left: 2%;
|
||||
margin-top: 15%;
|
||||
}
|
||||
|
||||
#part5 {
|
||||
width: 5.5%;
|
||||
left: 70%;
|
||||
margin-top: 9%;
|
||||
}
|
||||
|
||||
#part6 {
|
||||
width: 22%;
|
||||
left: 64%;
|
||||
margin-top: 1%;
|
||||
}
|
||||
|
||||
#part7 {
|
||||
width: 12.5%;
|
||||
left: 87.5%;
|
||||
margin-top: 1%;
|
||||
}
|
||||
|
||||
#part8 {
|
||||
width: 37%;
|
||||
left: 30%;
|
||||
margin-top: 28%;
|
||||
}
|
||||
|
||||
#part9 {
|
||||
width: 22.5%;
|
||||
left: 0;
|
||||
margin-top: 28%;
|
||||
}
|
||||
|
||||
#part10 {
|
||||
width: 49%;
|
||||
left: 20%;
|
||||
margin-top: 40%;
|
||||
}
|
||||
|
||||
#part11 {
|
||||
width: 14%;
|
||||
left: 2%;
|
||||
margin-top: 36%;
|
||||
}
|
||||
|
||||
#part12 {
|
||||
width: 27%;
|
||||
left: 72%;
|
||||
margin-top: 31%;
|
||||
}
|
||||
|
||||
#part13 {
|
||||
width: 24%;
|
||||
left: 48%;
|
||||
margin-top: 48%;
|
||||
}
|
||||
|
||||
#part14 {
|
||||
width: 19%;
|
||||
left: 24%;
|
||||
margin-top: 48%;
|
||||
}
|
||||
|
||||
#part15 {
|
||||
width: 4.5%;
|
||||
left: 15%;
|
||||
margin-top: 47%;
|
||||
}
|
||||
|
||||
#part16 {
|
||||
width: 24%;
|
||||
left: 75%;
|
||||
margin-top: 48%;
|
||||
}
|
||||
|
||||
#part17 {
|
||||
width: 7.5%;
|
||||
left: 2%;
|
||||
margin-top: 44%;
|
||||
}
|
||||
|
||||
#part18-1 {
|
||||
width: 14%;
|
||||
left: 46%;
|
||||
margin-top: 72%;
|
||||
}
|
||||
|
||||
#part18-2 {
|
||||
width: 14%;
|
||||
left: 46%;
|
||||
margin-top: 86%;
|
||||
}
|
||||
|
||||
#part19-1 {
|
||||
width: 17%;
|
||||
left: 22%;
|
||||
margin-top: 70%;
|
||||
}
|
||||
|
||||
#part19-2 {
|
||||
width: 17%;
|
||||
left: 22%;
|
||||
margin-top: 84%;
|
||||
}
|
||||
|
||||
#part20 {
|
||||
width: 13.5%;
|
||||
left: 66%;
|
||||
margin-top: 73%;
|
||||
}
|
||||
|
||||
#part21 {
|
||||
width: 11.5%;
|
||||
left: 6%;
|
||||
margin-top: 73%;
|
||||
}
|
||||
|
||||
#part22 {
|
||||
width: 13.5%;
|
||||
left: 84%;
|
||||
margin-top: 73%;
|
||||
}
|
||||
|
||||
#part23 {
|
||||
width: 28%;
|
||||
left: 22%;
|
||||
margin-top: 102%;
|
||||
}
|
||||
|
||||
#part24 {
|
||||
width: 37.5%;
|
||||
left: 60%;
|
||||
margin-top: 100%;
|
||||
}
|
||||
|
||||
#part25 {
|
||||
width: 20%;
|
||||
left: 14%;
|
||||
margin-top: 105%;
|
||||
}
|
||||
|
||||
#part26 {
|
||||
width: 40%;
|
||||
left: 43%;
|
||||
margin-top: 106%;
|
||||
}
|
||||
|
||||
#part27 {
|
||||
width: 22.5%;
|
||||
left: 20%;
|
||||
margin-top: 115%;
|
||||
}
|
||||
|
||||
#part28 {
|
||||
width: 22%;
|
||||
left: 47%;
|
||||
margin-top: 130%;
|
||||
}
|
||||
|
||||
#part29-1 {
|
||||
width: 3%;
|
||||
left: 4%;
|
||||
margin-top: 106%;
|
||||
}
|
||||
|
||||
#part29-2 {
|
||||
width: 3%;
|
||||
left: 8%;
|
||||
margin-top: 106%;
|
||||
}
|
||||
|
||||
#part30 {
|
||||
width: 19%;
|
||||
left: 70%;
|
||||
margin-top: 116%;
|
||||
}
|
||||
|
||||
#part31-1 {
|
||||
width: 2.5%;
|
||||
left: 13%;
|
||||
margin-top: 125.5%;
|
||||
}
|
||||
|
||||
#part31-2 {
|
||||
width: 2.5%;
|
||||
left: 16%;
|
||||
margin-top: 125.5%;
|
||||
}
|
||||
|
||||
#part32-1 {
|
||||
width: 2.75%;
|
||||
left: 20%;
|
||||
margin-top: 126%;
|
||||
}
|
||||
|
||||
#part32-2 {
|
||||
width: 2.75%;
|
||||
left: 24%;
|
||||
margin-top: 126%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-instagram {
|
||||
padding: 128px 0;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
padding: 128px 0;
|
||||
|
||||
h3 {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 16px 0 12px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 128px 0;
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
li {
|
||||
font-size: 18px;
|
||||
line-height: 1.5;
|
||||
font-weight: 500;
|
||||
|
||||
&:first-of-type {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&:not(:first-of-type) {
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
&:nth-of-type(4n+1):hover a::before {
|
||||
background-color: var(--pink);
|
||||
}
|
||||
|
||||
&:nth-of-type(4n+2):hover a::before {
|
||||
background-color: var(--red);
|
||||
}
|
||||
|
||||
&:nth-of-type(4n+3):hover a::before {
|
||||
background-color: var(--orange);
|
||||
}
|
||||
|
||||
&:nth-of-type(4n+4):hover a::before {
|
||||
background-color: var(--yellow);
|
||||
}
|
||||
|
||||
a {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 2px;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1023px) {
|
||||
h1 {
|
||||
font-size: 64px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.section-start {
|
||||
padding: 64px 0;
|
||||
|
||||
.headline {
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-service {
|
||||
padding: 64px 0;
|
||||
|
||||
h2 {
|
||||
margin: 0 32px 24px 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 32px 32px 0;
|
||||
}
|
||||
|
||||
.img {
|
||||
margin-top: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-work {
|
||||
padding: 64px 0;
|
||||
|
||||
h2 {
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 32px 0;
|
||||
}
|
||||
|
||||
.video {
|
||||
margin-bottom: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-rental {
|
||||
padding: 64px 0;
|
||||
overflow-x: hidden;
|
||||
|
||||
.square {
|
||||
padding: 0;
|
||||
|
||||
h2 {
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.parts {
|
||||
margin: 64px 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.section-instagram {
|
||||
padding: 64px 0;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
padding: 64px 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 64px 0;
|
||||
|
||||
ul {
|
||||
display: block;
|
||||
|
||||
li {
|
||||
margin: 12px 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
.section-service {
|
||||
h2 {
|
||||
margin: 0 0 16px 0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-work {
|
||||
h2 {
|
||||
margin: 0 0 16px 0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-rental {
|
||||
.square h2 {
|
||||
margin: 0 0 16px 0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 511px) {
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.section-start {
|
||||
padding: 32px 0 0;
|
||||
|
||||
.headline {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-service {
|
||||
padding: 64px 0 0;
|
||||
|
||||
h2 {
|
||||
border-bottom: 4px solid;
|
||||
}
|
||||
|
||||
.img {
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.section-work {
|
||||
padding: 64px 0 0;
|
||||
|
||||
.video {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-bottom: 4px solid;
|
||||
}
|
||||
}
|
||||
|
||||
.section-rental {
|
||||
padding: 64px 0 0;
|
||||
|
||||
.square h2 {
|
||||
border-bottom: 4px solid var(--red);
|
||||
}
|
||||
}
|
||||
|
||||
.section-instagram {
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
.section-text {
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 32px 0;
|
||||
}
|
||||
}
|
||||
@use "reset";
|
||||
@use "base";
|
||||
@use "nav";
|
||||
@use "intro";
|
||||
@use "service";
|
||||
@use "service_item";
|
||||
@use "process";
|
||||
@use "work";
|
||||
@use "work_entry";
|
||||
@use "faq";
|
||||
@use "insta";
|
||||
@use "footer";
|
||||
@use "text";
|
||||
|
||||
+24
-6
@@ -7,11 +7,29 @@
|
||||
},
|
||||
"content": {
|
||||
"content": [
|
||||
{"ref": "head"},
|
||||
{"ref": "nav"},
|
||||
{"tpl": "terms"},
|
||||
{"ref": "footer"},
|
||||
{"ref": "end"}
|
||||
{
|
||||
"ref": "head",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "AGB | Schnittfest GmbH – Videoproduktion & Verleih",
|
||||
"meta_description": "Allgemeine Geschäftsbedingungen der Schnittfest GmbH für Videoproduktion und Geräteverleih (Rentalfest)."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ref": "nav"
|
||||
},
|
||||
{
|
||||
"tpl": "terms",
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"ref": "footer"
|
||||
},
|
||||
{
|
||||
"ref": "end"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"display_name": "AGB"
|
||||
}
|
||||
+319
-89
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"display_name": "Startseite",
|
||||
"path": {
|
||||
"de": "/"
|
||||
},
|
||||
@@ -7,127 +8,356 @@
|
||||
},
|
||||
"content": {
|
||||
"content": [
|
||||
{"ref": "head"},
|
||||
{
|
||||
"ref": "nav",
|
||||
"data": {
|
||||
"full": true
|
||||
"ref": "head",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "Videoproduktion in OWL | Imagefilm & Animation | Schnittfest",
|
||||
"meta_description": "Schnittfest ist eure Videoproduktion aus Rheda-Wiedenbrück bei Bielefeld: Imagefilme, Recruiting-Videos, Werbefilme, Animation und Sounddesign – vom Konzept bis zum fertigen Film."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "intro"
|
||||
"ref": "nav",
|
||||
"data": {
|
||||
"full": "on"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "service"
|
||||
"tpl": "intro",
|
||||
"copy": {
|
||||
"de": {
|
||||
"kicker": "Videoproduktion aus Ostwestfalen",
|
||||
"headline": "Videoproduktion, auf den Frame genau.",
|
||||
"text": "<div>Wir sind <strong>Schnittfest</strong> – eine Filmproduktion aus Rheda-Wiedenbrück bei Bielefeld. Wir produzieren <strong>Imagefilme, Werbefilme, Recruiting-Videos und Animationen</strong> für Unternehmen in OWL und ganz Deutschland.</div>",
|
||||
"cta_label": "Projekt anfragen",
|
||||
"cta_href": "mailto:hi@schnittfest.gmbh",
|
||||
"ticker": "Imagefilm ✦ Werbefilm ✦ Recruiting-Video ✦ Animation ✦ Sounddesign ✦ Schnitt ✦ Color Grading ✦ Eventfilm ✦",
|
||||
"video_label": "Showreel der Videoproduktion Schnittfest"
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "/static/hero.mp4",
|
||||
"poster": "/static/1.jpg"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work",
|
||||
"tpl": "service",
|
||||
"copy": {
|
||||
"de": {
|
||||
"headline": "Film, Animation & Sound",
|
||||
"text": "<div>Von der ersten Idee bis zum finalen Frame: Wir konzipieren, drehen, animieren und vertonen – alles aus einer Hand. So entsteht ein Video, das deine Marke, deine Produkte oder dein Team genau richtig in Szene setzt.</div>",
|
||||
"image_caption": "Am Set, irgendwo zwischen Take 7 und 8."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"image": "/static/1.jpg"
|
||||
},
|
||||
"content": {
|
||||
"content": [
|
||||
"items": [
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/6z9AUO9lqBs"
|
||||
},
|
||||
"tpl": "service_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Imagefilm",
|
||||
"text": "Schüco Stories auf den schwedischen Inseln in der Nähe von Stockholm. Bei diesem Bauprojekt wurde das komplette vorhaben von der Entstehung bis zum fertigen Objekt filmisch begleitet."
|
||||
"title": "Film",
|
||||
"text": "sleep.shoot.eat.repeat. Imagefilme, Unternehmensfilme, Werbespots und Eventfilme – mit Kamera, Licht und Crew, die wissen, was sie tun."
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"color": "red"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/AnKUnt_qr0I"
|
||||
},
|
||||
"tpl": "service_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Artwork Film",
|
||||
"text": "Seit 25 Jahren bringt DansArt Tanz und Kultur nach Bielefeld. In vier Tanzstudios und einem eigenen Theater finden regelmäßig Tanzkurse, Ausbildungen für angehende Profitänzer *innen, Festivals, Workshops, Performances und Konzerte statt."
|
||||
"title": "Animation",
|
||||
"text": "Herausstechen und Welten erschaffen: Motion Design, 2D/3D-Animation und Erklärvideos, die Komplexes einfach machen."
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"color": "orange"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/ZlRCoYe9G20"
|
||||
},
|
||||
"tpl": "service_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Imagefilm",
|
||||
"text": "Neubau, Erweiterung und Renovation – das sind die Geschäftsfelder von H.O. Schlüter. Die H.O. Schlüter GmbH arbeitet als Partner zusammen mit Schüco International KG. Der Metallbau Lübz stellt sich in diesem Unternehmensfilm vor."
|
||||
"title": "Sound",
|
||||
"text": "Keine Musik wäre wie Butter ohne Brot. Sounddesign, Musik, Sprachaufnahmen und Mischung für den perfekten Ton."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/nCNS4veOjBY"
|
||||
},
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Commercial",
|
||||
"text": "Umbauten von Verbrennern zu Elektrofahrzeugen. ESDI EV Technologies ist eine Firma, die sich auf dem Schwerpunkt Elektroumbauten fokussiert hat. Mit Tesla-Technik, Nissan Leaf oder vielen weiteren baut ESDI EV VW Käfer, Porsche, Mini Cooper und mehr zu Elektrofahrzeugen."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/sFjOfG-5cIE"
|
||||
"color": "yellow"
|
||||
},
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Imagefilm",
|
||||
"text": "GOLDBECK und Schüco, das Fenstersystem AWE80 in der Entwicklung und Produktion in Bielefeld."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/ktjlpv6j-Fw"
|
||||
},
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Porträtfilm",
|
||||
"text": "Digitalisierung im Metallbau - Die berühmt-berüchtigte Industrie 4.0."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/ji1ux1Y4Y_U"
|
||||
},
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Kampagne",
|
||||
"text": "Azubi Recruiting Film für die Berufe Metallbauer, Metalltechnik, Technischer Systemplaner, Büromanagement."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/b8ASQboLCO8"
|
||||
},
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Eventfilm",
|
||||
"text": "50 führende Familienunternehmen aus ganz Deutschland zum Karrieretag Familienunternehmen in Bielefeld bei Schüco - Miele, Hilti, Haribo und viele mehr."
|
||||
}
|
||||
}
|
||||
"content": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "insta"
|
||||
"tpl": "process",
|
||||
"copy": {
|
||||
"de": {
|
||||
"headline": "So entsteht dein Film",
|
||||
"text": "<div>Klarer Ablauf, feste Ansprechpartner, keine Überraschungen – in vier Schritten zur fertigen Videoproduktion.</div>"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"steps": [
|
||||
{
|
||||
"tpl": "process_step",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "Idee & Konzept",
|
||||
"text": "Wir hören zu, entwickeln die Story und planen Drehbuch, Storyboard und Budget – damit dein Video ein klares Ziel hat."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"color": "yellow"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "process_step",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "Dreh & Produktion",
|
||||
"text": "Kamera, Licht, Ton und Crew: Wir drehen im Studio, im Unternehmen oder on location – in OWL und überall sonst."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"color": "orange"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "process_step",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "Postproduktion",
|
||||
"text": "Schnitt, Color Grading, Motion Design und Sounddesign machen aus dem Material einen Film, der hängen bleibt."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"color": "red"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "process_step",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "Auslieferung",
|
||||
"text": "Du bekommst deinen Film in allen Formaten, die du brauchst – für Website, Social Media, Messe oder Kino."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"color": "pink"
|
||||
},
|
||||
"content": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{"ref": "footer"},
|
||||
{"ref": "end"}
|
||||
{
|
||||
"tpl": "work",
|
||||
"copy": {
|
||||
"de": {
|
||||
"headline": "Referenzen",
|
||||
"text": "<div>Popcorn bereit? Eine Auswahl unserer Imagefilme, Commercials und Recruiting-Videos für Kunden wie Schüco, GOLDBECK und DansArt.</div>"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"content": [
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Imagefilm für Schüco: Bauprojekt in Schweden",
|
||||
"text": "Für die Reihe „Schüco Stories“ haben wir ein Bauprojekt auf den Schären vor Stockholm filmisch begleitet – von der ersten Planung bis zum fertigen Gebäude. Eine Langzeit-Dokumentation als Imagefilm."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/6z9AUO9lqBs"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Kulturfilm für DansArt Bielefeld",
|
||||
"text": "Seit 25 Jahren bringt DansArt Tanz und Kultur nach Bielefeld: vier Tanzstudios, ein eigenes Theater, Ausbildung, Festivals und Konzerte. Unser Artwork-Film fängt Bewegung, Musik und Atmosphäre ein."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/AnKUnt_qr0I"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Unternehmensfilm für H.O. Schlüter Metallbau",
|
||||
"text": "Neubau, Erweiterung und Renovation: Im Unternehmensfilm stellt sich der Metallbau H.O. Schlüter aus Lübz vor – Partner der Schüco International KG."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/ZlRCoYe9G20"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Commercial für ESDI EV Technologies",
|
||||
"text": "ESDI EV baut Klassiker wie VW Käfer, Porsche und Mini Cooper mit Tesla- und Nissan-Leaf-Technik zu Elektrofahrzeugen um. Unser Werbefilm zeigt Handwerk, Technik und Fahrspaß."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/nCNS4veOjBY"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Produktfilm für GOLDBECK & Schüco",
|
||||
"text": "Wie entsteht ein Fenstersystem? Der Produktfilm zeigt Entwicklung und Fertigung des Schüco AWE80 für GOLDBECK in Bielefeld."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/sFjOfG-5cIE"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Porträtfilm: Digitalisierung im Metallbau",
|
||||
"text": "Industrie 4.0 zum Anfassen: Ein Porträtfilm darüber, wie digitale Prozesse den Alltag im Metallbau verändern."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/ktjlpv6j-Fw"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Recruiting-Video für Azubis im Metallbau",
|
||||
"text": "Kampagne zur Ausbildungsplatz-Suche: Unser Recruitingfilm stellt die Berufe Metallbauer*in, Metalltechnik, Technische*r Systemplaner*in und Büromanagement vor – authentisch und auf Augenhöhe."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/ji1ux1Y4Y_U"
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "work_entry",
|
||||
"copy": {
|
||||
"de": {
|
||||
"h2": "Eventfilm: Karrieretag Familienunternehmen",
|
||||
"text": "50 führende Familienunternehmen wie Miele, Hilti und Haribo trafen sich bei Schüco in Bielefeld. Unser Eventfilm fasst den Karrieretag kompakt zusammen."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"video": "https://www.youtube.com/embed/b8ASQboLCO8"
|
||||
},
|
||||
"content": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "faq",
|
||||
"copy": {
|
||||
"de": {
|
||||
"headline": "Häufige Fragen",
|
||||
"text": "<div>Deine Frage ist nicht dabei? Schreib uns an <a href=\"mailto:hi@schnittfest.gmbh\">hi@schnittfest.gmbh</a>.</div>"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"items": [
|
||||
{
|
||||
"tpl": "faq_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"question": "Was kostet ein Imagefilm?",
|
||||
"answer": "<div>Das hängt von Umfang, Drehtagen, Crew und Postproduktion ab. Nach einem kurzen Gespräch bekommst du von uns ein transparentes, unverbindliches Angebot, das zu deinem Budget passt.</div>"
|
||||
}
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "faq_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"question": "Wie lange dauert eine Videoproduktion?",
|
||||
"answer": "<div>Von der ersten Idee bis zum fertigen Film vergehen meist einige Wochen. Kleinere Projekte wie Social-Media-Clips oder Eventfilme sind oft deutlich schneller fertig. Den genauen Zeitplan legen wir gemeinsam fest.</div>"
|
||||
}
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "faq_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"question": "Wo dreht ihr?",
|
||||
"answer": "<div>Unser Sitz ist in Rheda-Wiedenbrück zwischen Gütersloh und Bielefeld. Wir drehen in ganz Ostwestfalen-Lippe, deutschlandweit und auch international.</div>"
|
||||
}
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "faq_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"question": "Welche Videoformate produziert ihr?",
|
||||
"answer": "<div>Imagefilme, Unternehmens- und Produktfilme, Recruiting-Videos, Werbefilme und Commercials, Eventfilme sowie 2D/3D-Animation und Erklärvideos – inklusive Musik und Sounddesign.</div>"
|
||||
}
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"tpl": "faq_item",
|
||||
"copy": {
|
||||
"de": {
|
||||
"question": "Bekomme ich auch Schnittfassungen für Social Media?",
|
||||
"answer": "<div>Auf Wunsch liefern wir neben dem Hauptfilm kurze Cut-downs in Hoch- und Querformat für Instagram, LinkedIn, TikTok oder YouTube.</div>"
|
||||
}
|
||||
},
|
||||
"content": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tpl": "insta",
|
||||
"copy": {
|
||||
"de": {
|
||||
"headline": "Hinter den Kulissen"
|
||||
}
|
||||
},
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"ref": "footer"
|
||||
},
|
||||
{
|
||||
"ref": "end"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+24
-6
@@ -7,11 +7,29 @@
|
||||
},
|
||||
"content": {
|
||||
"content": [
|
||||
{"ref": "head"},
|
||||
{"ref": "nav"},
|
||||
{"tpl": "legal"},
|
||||
{"ref": "footer"},
|
||||
{"ref": "end"}
|
||||
{
|
||||
"ref": "head",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "Impressum & Datenschutz | Schnittfest GmbH",
|
||||
"meta_description": "Impressum und Datenschutzerklärung der Schnittfest GmbH, Videoproduktion aus Rheda-Wiedenbrück."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ref": "nav"
|
||||
},
|
||||
{
|
||||
"tpl": "legal",
|
||||
"content": {}
|
||||
},
|
||||
{
|
||||
"ref": "footer"
|
||||
},
|
||||
{
|
||||
"ref": "end"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"display_name": "Impressum"
|
||||
}
|
||||
@@ -1,3 +1,17 @@
|
||||
{
|
||||
"tpl": "footer"
|
||||
"tpl": "footer",
|
||||
"copy": {
|
||||
"de": {
|
||||
"headline": "Und… Action?",
|
||||
"text": "Du planst einen Imagefilm, ein Recruiting-Video oder eine Kampagne? Erzähl uns von deiner Idee – wir machen einen Film daraus.",
|
||||
"copyright": "Schnittfest GmbH · Videoproduktion in Rheda-Wiedenbrück"
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"email": "hi@schnittfest.gmbh",
|
||||
"phone": "+49 176 93124984",
|
||||
"instagram": "https://instagram.com/schnittfest.gmbh",
|
||||
"vimeo": "https://vimeo.com/schnittfest"
|
||||
},
|
||||
"content": {}
|
||||
}
|
||||
+11
-1
@@ -1,3 +1,13 @@
|
||||
{
|
||||
"tpl": "head"
|
||||
"tpl": "head",
|
||||
"copy": {
|
||||
"de": {
|
||||
"title": "Videoproduktion in OWL | Imagefilm & Animation | Schnittfest",
|
||||
"meta_description": "Schnittfest ist eure Videoproduktion aus Rheda-Wiedenbrück bei Bielefeld: Imagefilme, Recruiting-Videos, Werbefilme, Animation und Sounddesign."
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"robots": "index,follow"
|
||||
},
|
||||
"content": {}
|
||||
}
|
||||
+10
-1
@@ -1,3 +1,12 @@
|
||||
{
|
||||
"tpl": "nav"
|
||||
"tpl": "nav",
|
||||
"copy": {
|
||||
"de": {
|
||||
"service_label": "Leistungen",
|
||||
"work_label": "Referenzen",
|
||||
"faq_label": "FAQ",
|
||||
"contact_label": "Kontakt"
|
||||
}
|
||||
},
|
||||
"content": {}
|
||||
}
|
||||
+5
-1
@@ -6,7 +6,7 @@
|
||||
"shutdown_time": 30,
|
||||
"write_timeout": 5,
|
||||
"read_timeout": 5,
|
||||
"hostname": "schnittfest.gmbh",
|
||||
"hostname": "https://schnittfest.gmbh",
|
||||
"secure_cookies": false,
|
||||
"cookie_domain_name": "schnittfest.gmbh"
|
||||
},
|
||||
@@ -34,5 +34,9 @@
|
||||
"analytics": {
|
||||
"provider": "pirsch",
|
||||
"client_secret": ""
|
||||
},
|
||||
"ui": {
|
||||
"path": "/admin",
|
||||
"admin_password": "${ADMIN_PASSWORD}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
var controller = new ScrollMagic.Controller();
|
||||
|
||||
var backgroundColor = new TweenMax.to(".bg-beige-to-black", 1, {
|
||||
backgroundColor: "#000",
|
||||
ease: Power1.easeOut
|
||||
});
|
||||
|
||||
var backgroundColorScene = new ScrollMagic.Scene({
|
||||
triggerElement: "#work",
|
||||
duration: 256
|
||||
})
|
||||
.setTween(backgroundColor)
|
||||
.addTo(controller);
|
||||
|
||||
var textColor = new TweenMax.to(".black-to-beige", 1, {
|
||||
color: "#f7eee0",
|
||||
ease: Power1.easeOut
|
||||
});
|
||||
|
||||
var textColorScene = new ScrollMagic.Scene({
|
||||
triggerElement: "#work",
|
||||
duration: 256
|
||||
})
|
||||
.setTween(textColor)
|
||||
.addTo(controller);
|
||||
|
||||
|
||||
var reverseBackgroundColor = new TweenMax.to(".bg-beige-to-black", 1, {
|
||||
backgroundColor: "#f7eee0",
|
||||
ease: Power1.easeOut
|
||||
});
|
||||
|
||||
var reverseBackgroundColorScene = new ScrollMagic.Scene({
|
||||
triggerElement: "#rental",
|
||||
duration: 256
|
||||
})
|
||||
.setTween(reverseBackgroundColor)
|
||||
.addTo(controller);
|
||||
|
||||
var reverseTextColor = new TweenMax.to(".black-to-beige", 1, {
|
||||
color: "#000",
|
||||
ease: Power1.easeOut
|
||||
});
|
||||
|
||||
var reverseTextColorScene = new ScrollMagic.Scene({
|
||||
triggerElement: "#rental",
|
||||
duration: 256
|
||||
})
|
||||
.setTween(reverseTextColor)
|
||||
.addTo(controller);
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
(()=>{console.log("Hi!");})();
|
||||
(()=>{function a(t){let e=t.querySelector(".nav__toggle");if(!e)return;let n=o=>{t.classList.toggle("nav--open",o),e.setAttribute("aria-expanded",String(o))};e.addEventListener("click",()=>n(!t.classList.contains("nav--open"))),t.querySelectorAll(".nav__link").forEach(o=>o.addEventListener("click",()=>n(!1))),t.addEventListener("keydown",o=>{o.key==="Escape"&&(n(!1),e.focus())})}var i=null;function g(){return i||(i=new IntersectionObserver(t=>{t.forEach(e=>{e.isIntersecting&&(e.target.classList.add("is-visible"),i.unobserve(e.target))})},{rootMargin:"0px 0px -8% 0px",threshold:.05})),i}function c(t){if(!("IntersectionObserver"in window)){t.classList.add("is-visible");return}g().observe(t)}function s(t){return String(t).padStart(2,"0")}function d(t){let e=performance.now(),n=o=>{if(!t.isConnected)return;let r=Math.floor((o-e)/1e3*25),l=r%25,m=Math.floor(r/25)%60,v=Math.floor(r/1500)%60,p=Math.floor(r/(25*3600));t.textContent=`${s(p)}:${s(v)}:${s(m)}:${s(l)}`,requestAnimationFrame(n)};requestAnimationFrame(n)}document.documentElement.classList.add("js");var b={nav:a,reveal:c,timecode:d};function f(t=document){t.querySelectorAll("[data-component]").forEach(e=>{if(e.dataset.componentReady)return;let n=b[e.dataset.component];n&&(n(e),e.dataset.componentReady="true")})}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",u):u();function u(){f(),new MutationObserver(()=>f()).observe(document.body,{childList:!0,subtree:!0})}})();
|
||||
|
||||
@@ -1,532 +0,0 @@
|
||||
var offset = window.screen.width > 512 ? 20 : 10;
|
||||
|
||||
var controller = new ScrollMagic.Controller();
|
||||
|
||||
var part2 = new TweenMax.from("#part2", 1, {
|
||||
x: "-100vw",
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part2Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
})
|
||||
.setTween(part2)
|
||||
.addTo(controller);
|
||||
|
||||
var part3 = new TweenMax.from("#part3", 1, {
|
||||
x: "-100vw",
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part3Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: this.offset
|
||||
})
|
||||
.setTween(part3)
|
||||
.addTo(controller);
|
||||
|
||||
var part4 = new TweenMax.from("#part4", 1, {
|
||||
x: "-100vw",
|
||||
y: "100%",
|
||||
rotation: 2,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part4Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 2*this.offset
|
||||
})
|
||||
.setTween(part4)
|
||||
.addTo(controller);
|
||||
|
||||
var part5 = new TweenMax.from("#part5", 1, {
|
||||
x: "100vw",
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part5Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250
|
||||
})
|
||||
.setTween(part5)
|
||||
.addTo(controller);
|
||||
|
||||
var part6 = new TweenMax.from("#part6", 1, {
|
||||
x: "100vw",
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part6Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 3*this.offset
|
||||
})
|
||||
.setTween(part6)
|
||||
.addTo(controller);
|
||||
|
||||
var part7 = new TweenMax.from("#part7", 1, {
|
||||
x: "100vw",
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part7Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 4*this.offset
|
||||
})
|
||||
.setTween(part7)
|
||||
.addTo(controller);
|
||||
|
||||
var part8 = new TweenMax.from("#part8", 1, {
|
||||
x: "-100vw",
|
||||
y: "200%",
|
||||
rotation: 4,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part8Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 5*this.offset
|
||||
})
|
||||
.setTween(part8)
|
||||
.addTo(controller);
|
||||
|
||||
var part9 = new TweenMax.from("#part9", 1, {
|
||||
x: "-100vw",
|
||||
y: "300%",
|
||||
rotation: 4,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part9Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 5*this.offset
|
||||
})
|
||||
.setTween(part9)
|
||||
.addTo(controller);
|
||||
|
||||
var part10 = new TweenMax.from("#part10", 1, {
|
||||
x: "100vw",
|
||||
y: "600%",
|
||||
rotation: -12,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part10Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 6*this.offset
|
||||
})
|
||||
.setTween(part10)
|
||||
.addTo(controller);
|
||||
|
||||
var part11 = new TweenMax.from("#part11", 1, {
|
||||
x: "-100vw",
|
||||
y: "800%",
|
||||
rotation: 12,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part11Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 7*this.offset
|
||||
})
|
||||
.setTween(part11)
|
||||
.addTo(controller);
|
||||
|
||||
var part12 = new TweenMax.from("#part12", 1, {
|
||||
x: "100vw",
|
||||
y: "500%",
|
||||
rotation: -16,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part12Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 8*this.offset
|
||||
})
|
||||
.setTween(part12)
|
||||
.addTo(controller);
|
||||
|
||||
var part13 = new TweenMax.from("#part13", 1, {
|
||||
x: "100vw",
|
||||
y: "400%",
|
||||
rotation: -24,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part13Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 9*this.offset
|
||||
})
|
||||
.setTween(part13)
|
||||
.addTo(controller);
|
||||
|
||||
var part14 = new TweenMax.from("#part14", 1, {
|
||||
x: "-100vw",
|
||||
y: "400%",
|
||||
rotation: 24,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part14Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 10*this.offset
|
||||
})
|
||||
.setTween(part14)
|
||||
.addTo(controller);
|
||||
|
||||
var part15 = new TweenMax.from("#part15", 1, {
|
||||
x: "-100vw",
|
||||
y: "400%",
|
||||
rotation: 24,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part15Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 11*this.offset
|
||||
})
|
||||
.setTween(part15)
|
||||
.addTo(controller);
|
||||
|
||||
var part16 = new TweenMax.from("#part16", 1, {
|
||||
x: "100vw",
|
||||
y: "400%",
|
||||
rotation: 24,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part16Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 12*this.offset
|
||||
})
|
||||
.setTween(part16)
|
||||
.addTo(controller);
|
||||
|
||||
var part17 = new TweenMax.from("#part17", 1, {
|
||||
x: "-100vw",
|
||||
y: "400%",
|
||||
rotation: 24,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part17Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 13*this.offset
|
||||
})
|
||||
.setTween(part17)
|
||||
.addTo(controller);
|
||||
|
||||
var part181 = new TweenMax.from("#part18-1", 1, {
|
||||
x: "100vw",
|
||||
y: "800%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part181Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 14*this.offset
|
||||
})
|
||||
.setTween(part181)
|
||||
.addTo(controller);
|
||||
|
||||
var part182 = new TweenMax.from("#part18-2", 1, {
|
||||
x: "100vw",
|
||||
y: "800%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part182Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 15*this.offset
|
||||
})
|
||||
.setTween(part182)
|
||||
.addTo(controller);
|
||||
|
||||
var part191 = new TweenMax.from("#part19-1", 1, {
|
||||
x: "-100vw",
|
||||
y: "800%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part191Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 16*this.offset
|
||||
})
|
||||
.setTween(part191)
|
||||
.addTo(controller);
|
||||
|
||||
var part192 = new TweenMax.from("#part19-2", 1, {
|
||||
x: "-100vw",
|
||||
y: "800%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part192Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 18*this.offset
|
||||
})
|
||||
.setTween(part192)
|
||||
.addTo(controller);
|
||||
|
||||
var part20 = new TweenMax.from("#part20", 1, {
|
||||
x: "100vw",
|
||||
y: "800%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part20Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 19*this.offset
|
||||
})
|
||||
.setTween(part20)
|
||||
.addTo(controller);
|
||||
|
||||
var part21 = new TweenMax.from("#part21", 1, {
|
||||
x: "-100vw",
|
||||
y: "800%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part21Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 20*this.offset
|
||||
})
|
||||
.setTween(part21)
|
||||
.addTo(controller);
|
||||
|
||||
var part22 = new TweenMax.from("#part22", 1, {
|
||||
x: "100vw",
|
||||
y: "800%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part22Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 21*this.offset
|
||||
})
|
||||
.setTween(part22)
|
||||
.addTo(controller);
|
||||
|
||||
var part23 = new TweenMax.from("#part23", 1, {
|
||||
x: "-100vw",
|
||||
y: "2400%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part23Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 22*this.offset
|
||||
})
|
||||
.setTween(part23)
|
||||
.addTo(controller);
|
||||
|
||||
var part24 = new TweenMax.from("#part24", 1, {
|
||||
x: "100vw",
|
||||
y: "1000%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part24Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 23*this.offset
|
||||
})
|
||||
.setTween(part24)
|
||||
.addTo(controller);
|
||||
|
||||
var part25 = new TweenMax.from("#part25", 1, {
|
||||
x: "-100vw",
|
||||
y: "1000%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part25Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 24*this.offset
|
||||
})
|
||||
.setTween(part25)
|
||||
.addTo(controller);
|
||||
|
||||
var part26 = new TweenMax.from("#part26", 1, {
|
||||
x: "100vw",
|
||||
y: "1000%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part26Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 25*this.offset
|
||||
})
|
||||
.setTween(part26)
|
||||
.addTo(controller);
|
||||
|
||||
var part27 = new TweenMax.from("#part27", 1, {
|
||||
x: "-100vw",
|
||||
y: "1600%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part27Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 26*this.offset
|
||||
})
|
||||
.setTween(part27)
|
||||
.addTo(controller);
|
||||
|
||||
var part28 = new TweenMax.from("#part28", 1, {
|
||||
x: "100vw",
|
||||
y: "1600%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part28Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 33*this.offset
|
||||
})
|
||||
.setTween(part28)
|
||||
.addTo(controller);
|
||||
|
||||
var part291 = new TweenMax.from("#part29-1", 1, {
|
||||
x: "-100vw",
|
||||
y: "1600%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part291Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 32*this.offset
|
||||
})
|
||||
.setTween(part291)
|
||||
.addTo(controller);
|
||||
|
||||
var part292 = new TweenMax.from("#part29-2", 1, {
|
||||
x: "-100vw",
|
||||
y: "1600%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part292Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 31*this.offset
|
||||
})
|
||||
.setTween(part292)
|
||||
.addTo(controller);
|
||||
|
||||
var part30 = new TweenMax.from("#part30", 1, {
|
||||
x: "100vw",
|
||||
y: "1600%",
|
||||
rotation: -32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part30Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 34*this.offset
|
||||
})
|
||||
.setTween(part30)
|
||||
.addTo(controller);
|
||||
|
||||
var part311 = new TweenMax.from("#part31-1", 1, {
|
||||
x: "-100vw",
|
||||
y: "3200%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part311Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 30*this.offset
|
||||
})
|
||||
.setTween(part311)
|
||||
.addTo(controller);
|
||||
|
||||
var part312 = new TweenMax.from("#part31-2", 1, {
|
||||
x: "-100vw",
|
||||
y: "3200%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part312Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 29*this.offset
|
||||
})
|
||||
.setTween(part312)
|
||||
.addTo(controller);
|
||||
|
||||
var part321 = new TweenMax.from("#part32-1", 1, {
|
||||
x: "-100vw",
|
||||
y: "3200%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part321Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 28*this.offset
|
||||
})
|
||||
.setTween(part321)
|
||||
.addTo(controller);
|
||||
|
||||
var part322 = new TweenMax.from("#part32-2", 1, {
|
||||
x: "-100vw",
|
||||
y: "3200%",
|
||||
rotation: 32,
|
||||
ease: Power2.easeOut
|
||||
});
|
||||
|
||||
var part322Scene = new ScrollMagic.Scene({
|
||||
triggerElement: "#parts",
|
||||
duration: 250,
|
||||
offset: 27*this.offset
|
||||
})
|
||||
.setTween(part322)
|
||||
.addTo(controller);
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
{{ adminBody .Page }}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- $headline := default (copy .Page .Content "headline") "Häufige Fragen" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
|
||||
<section class="faq" id="faq" itemscope itemtype="https://schema.org/FAQPage" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="faq__inner">
|
||||
<div class="faq__head" data-component="reveal">
|
||||
<h2 class="section-title"><span class="section-title__nr" aria-hidden="true"></span>{{ $headline }}</h2>
|
||||
{{ with $text }}<div class="faq__text">{{ html . }}</div>{{ end }}
|
||||
</div>
|
||||
<div class="faq__list">
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.items" .Content.Position) (index .Content.Content "items") }}
|
||||
<slot name="{{ .Content.Position }}/items"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,12 @@
|
||||
{{- $question := copy .Page .Content "question" -}}
|
||||
{{- $answer := copy .Page .Content "answer" -}}
|
||||
|
||||
<details class="faq-item" itemscope itemprop="mainEntity" itemtype="https://schema.org/Question" data-shifu-element="{{ .Content.Position }}">
|
||||
<summary class="faq-item__question">
|
||||
<h3 class="faq-item__title" itemprop="name">{{ default $question "Frage" }}</h3>
|
||||
<span class="faq-item__icon" aria-hidden="true"></span>
|
||||
</summary>
|
||||
<div class="faq-item__answer" itemscope itemprop="acceptedAnswer" itemtype="https://schema.org/Answer">
|
||||
{{ with $answer }}<div itemprop="text">{{ html . }}</div>{{ end }}
|
||||
</div>
|
||||
</details>
|
||||
+32
-109
@@ -1,111 +1,34 @@
|
||||
<footer id="footer">
|
||||
<div class="container">
|
||||
<ul>
|
||||
<li>© 2024 Schnittfest GmbH</li>
|
||||
<li>
|
||||
<a href="tel:+49017693124984">+49 176 93124984</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="mailto:hi@schnitffest.gmbh">hi@schnittfest.gmbh</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://instagram.com/schnittfest.gmbh">Instagram</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vimeo.com/schnittfest">Vimeo</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/agb" target="_blank">AGB</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/impressum" target="_blank">Impressum</a>
|
||||
</li>
|
||||
</ul>
|
||||
{{- $headline := default (copy .Page .Content "headline") "Und… Action?" -}}
|
||||
{{- $text := default (copy .Page .Content "text") "Erzähl uns von deiner Idee – wir machen einen Film daraus." -}}
|
||||
{{- $email := default (get .Content "email") "hi@schnittfest.gmbh" -}}
|
||||
{{- $phone := default (get .Content "phone") "+49 176 93124984" -}}
|
||||
{{- $instagram := default (get .Content "instagram") "https://instagram.com/schnittfest.gmbh" -}}
|
||||
{{- $vimeo := default (get .Content "vimeo") "https://vimeo.com/schnittfest" -}}
|
||||
{{- $copyright := default (copy .Page .Content "copyright") "Schnittfest GmbH" -}}
|
||||
|
||||
<footer class="footer" id="footer" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="footer__inner">
|
||||
<div class="footer__cta" data-component="reveal">
|
||||
<h2 class="footer__headline">{{ $headline }}</h2>
|
||||
<p class="footer__text">{{ $text }}</p>
|
||||
<a class="button button--yellow footer__mail" href="mailto:{{ $email }}">
|
||||
<span class="button__play" aria-hidden="true"></span>{{ $email }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<dl class="credits" data-component="reveal">
|
||||
<div class="credits__row"><dt>Telefon</dt><dd><a href="tel:{{ $phone | replace " " "" }}">{{ $phone }}</a></dd></div>
|
||||
<div class="credits__row"><dt>E-Mail</dt><dd><a href="mailto:{{ $email }}">{{ $email }}</a></dd></div>
|
||||
<div class="credits__row"><dt>Instagram</dt><dd><a href="{{ $instagram }}" target="_blank" rel="noopener">schnittfest.gmbh</a></dd></div>
|
||||
<div class="credits__row"><dt>Vimeo</dt><dd><a href="{{ $vimeo }}" target="_blank" rel="noopener">schnittfest</a></dd></div>
|
||||
</dl>
|
||||
|
||||
<div class="footer__bottom">
|
||||
<span>© {{ year }} {{ $copyright }}</span>
|
||||
<span class="footer__legal">
|
||||
<a href="/agb">AGB</a>
|
||||
<a href="/impressum">Impressum</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script type="text/javascript" src="https://player.vimeo.com/api/player.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.0.4/gsap.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/ScrollMagic.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.7/plugins/animation.gsap.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
||||
<script type="text/javascript" src="https://cdn.lightwidget.com/widgets/lightwidget.js"></script>
|
||||
<script type="text/javascript" src="static/js/color.js"></script>
|
||||
<script type="text/javascript" src="static/js/parts.js"></script>
|
||||
|
||||
<script>
|
||||
AOS.init({
|
||||
duration: 1000,
|
||||
easing: "cubic-bezier(0.4, 0.0, 0.2, 1)",
|
||||
once: true,
|
||||
offset: 32
|
||||
});
|
||||
|
||||
// navbar mobile menu
|
||||
let mobileMenu = document.getElementById("mobileMenu");
|
||||
let mobileMenuOpen = document.getElementById("mobileMenuOpen");
|
||||
let mobileMenuClose = document.getElementById("mobileMenuClose");
|
||||
|
||||
function toggleMobileMenu() {
|
||||
let hidden = mobileMenu.style.display;
|
||||
|
||||
if(hidden) {
|
||||
mobileMenu.style.display = "";
|
||||
} else {
|
||||
mobileMenu.style.display = "none"
|
||||
}
|
||||
}
|
||||
|
||||
mobileMenuOpen.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
toggleMobileMenu();
|
||||
});
|
||||
|
||||
// scroll to from navigation
|
||||
let scrollToService = document.getElementsByClassName("scrollToService");
|
||||
let scrollToWork = document.getElementsByClassName("scrollToWork");
|
||||
let scrollToRental = document.getElementsByClassName("scrollToRental");
|
||||
let scrollToFooter = document.getElementsByClassName("scrollToFooter");
|
||||
|
||||
function addScrollTo(nodes, anchor) {
|
||||
for (let node of nodes) {
|
||||
node.addEventListener("click", () => {
|
||||
toggleMobileMenu();
|
||||
let section = document.getElementById(anchor);
|
||||
|
||||
if (window.location.pathname === "/") {
|
||||
window.scrollTo({top: section.offsetTop, behavior: "smooth"});
|
||||
} else {
|
||||
window.location = `/#${anchor}`;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("click", e => {
|
||||
if(!mobileMenu.style.display) {
|
||||
mobileMenu.style.display = "none"
|
||||
}
|
||||
});
|
||||
|
||||
addScrollTo(scrollToService, "service");
|
||||
addScrollTo(scrollToWork, "work");
|
||||
addScrollTo(scrollToRental, "rental");
|
||||
addScrollTo(scrollToFooter, "footer");
|
||||
|
||||
// click on logo navigation
|
||||
let homeLink = document.getElementById("homeLink");
|
||||
|
||||
homeLink.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if(window.location.pathname === "/") {
|
||||
window.scrollTo({top: 0, behavior: "smooth"});
|
||||
}
|
||||
else {
|
||||
window.location = "/";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
+54
-25
@@ -1,37 +1,66 @@
|
||||
{{- $title := default (copy .Page .Content "title") "Videoproduktion in OWL | Imagefilm, Animation & Sound | Schnittfest" -}}
|
||||
{{- $description := default (copy .Page .Content "meta_description") "Schnittfest ist eure Videoproduktion aus Rheda-Wiedenbrück bei Bielefeld: Imagefilme, Recruiting-Videos, Commercials, Animation und Sounddesign – vom Konzept bis zum fertigen Film." -}}
|
||||
{{- $robots := default (get .Content "robots") "index,follow" -}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<html lang="{{ .Page.Language }}">
|
||||
<head>
|
||||
<base href="/" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{{ $title }}</title>
|
||||
<meta name="description" content="{{ $description }}" />
|
||||
<meta name="robots" content="{{ $robots }}" />
|
||||
<meta name="copyright" content="Schnittfest GmbH" />
|
||||
<meta name="author" content="Emvi Software GmbH" />
|
||||
<meta name="title" content="Schnittfest" />
|
||||
<meta name="description" content="Film, auf den Frame genau." />
|
||||
<meta name="msapplication-TileColor" content="#000000" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="twitter:card" content="product" />
|
||||
<meta name="twitter:title" content="Schnittfest" />
|
||||
<meta name="twitter:description" content="Film, auf den Frame genau." />
|
||||
<meta name="twitter:image" content="/static/1.jpg" />
|
||||
<meta property="og:url" content="https://schnittfest.gmbh/" />
|
||||
<meta property="og:title" content="Schnittfest" />
|
||||
<meta property="og:description" content="Film, auf den Frame genau." />
|
||||
<meta property="og:image" content="/static/1.jpg" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/static/web/main.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/static/web/manrope.css" />
|
||||
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet" />
|
||||
<meta name="theme-color" content="#0e0c0b" />
|
||||
<meta name="msapplication-TileColor" content="#0e0c0b" />
|
||||
<meta name="apple-mobile-web-app-title" content="Schnittfest" />
|
||||
<meta name="application-name" content="Schnittfest" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="{{ $title }}" />
|
||||
<meta name="twitter:description" content="{{ $description }}" />
|
||||
<meta name="twitter:image" content="{{ hostname }}/static/1.jpg" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:locale" content="de_DE" />
|
||||
<meta property="og:site_name" content="Schnittfest" />
|
||||
<meta property="og:url" content="{{ .Page.CanonicalLink }}" />
|
||||
<meta property="og:title" content="{{ $title }}" />
|
||||
<meta property="og:description" content="{{ $description }}" />
|
||||
<meta property="og:image" content="{{ hostname }}/static/1.jpg" />
|
||||
<link rel="canonical" href="{{ .Page.CanonicalLink }}" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicon/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon/favicon-16x16.png" />
|
||||
<link rel="mask-icon" href="/static/favicon/safari-pinned-tab.svg" color="#000000" />
|
||||
<link rel="mask-icon" href="/static/favicon/safari-pinned-tab.svg" color="#0e0c0b" />
|
||||
<link rel="shortcut icon" href="/static/favicon/favicon.ico" />
|
||||
<meta name="apple-mobile-web-app-title" content="Schnittfest" />
|
||||
<meta name="application-name" content="Schnittfest" />
|
||||
<meta name="msapplication-TileColor" content="#000000" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
|
||||
<title>Schnittfest</title>
|
||||
<link rel="preload" href="/static/fonts/Manrope-ExtraBold.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="stylesheet" href="/static/web/manrope.css" />
|
||||
<link rel="stylesheet" href="/static/web/main.css?v={{ .CMS.LastUpdate }}" />
|
||||
<script defer src="/static/web/main.min.js?v={{ .CMS.LastUpdate }}"></script>
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "LocalBusiness",
|
||||
"@id": "{{ hostname }}/#organization",
|
||||
"name": "Schnittfest GmbH",
|
||||
"description": "Videoproduktion für Imagefilme, Commercials, Animation und Sound in Ostwestfalen-Lippe.",
|
||||
"url": "{{ hostname }}/",
|
||||
"logo": "{{ hostname }}/static/favicon/favicon512x512.png",
|
||||
"image": "{{ hostname }}/static/1.jpg",
|
||||
"email": "hi@schnittfest.gmbh",
|
||||
"telephone": "+49 5242 9079902",
|
||||
"address": {
|
||||
"@type": "PostalAddress",
|
||||
"streetAddress": "Schulbusch 29",
|
||||
"postalCode": "33378",
|
||||
"addressLocality": "Rheda-Wiedenbrück",
|
||||
"addressRegion": "NRW",
|
||||
"addressCountry": "DE"
|
||||
},
|
||||
"areaServed": ["Rheda-Wiedenbrück", "Gütersloh", "Bielefeld", "Ostwestfalen-Lippe", "Deutschland"],
|
||||
"sameAs": ["https://instagram.com/schnittfest.gmbh", "https://vimeo.com/schnittfest"]
|
||||
}
|
||||
</script>
|
||||
{{ adminHead .Page }}
|
||||
</head>
|
||||
<body class="bg-beige-to-black">
|
||||
<body>
|
||||
|
||||
+14
-4
@@ -1,6 +1,16 @@
|
||||
<section id="instagram" class="section-instagram">
|
||||
<div class="container">
|
||||
<script src="https://cdn.lightwidget.com/widgets/lightwidget.js"></script>
|
||||
<iframe src="https://cdn.lightwidget.com/widgets/ea2fc8dd2d55541dbafdc312dbe28aee.html" scrolling="no" allowtransparency="true" class="lightwidget-widget" style="width:100%;border:0;overflow:hidden;"></iframe>
|
||||
{{- $headline := default (copy .Page .Content "headline") "Hinter den Kulissen" -}}
|
||||
{{- $widget := default (get .Content "widget") "https://cdn.lightwidget.com/widgets/ea2fc8dd2d55541dbafdc312dbe28aee.html" -}}
|
||||
{{- $profile := default (get .Content "profile") "https://instagram.com/schnittfest.gmbh" -}}
|
||||
|
||||
<section class="insta" id="instagram" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="insta__inner">
|
||||
<div class="insta__head" data-component="reveal">
|
||||
<h2 class="section-title"><span class="section-title__nr" aria-hidden="true"></span>{{ $headline }}</h2>
|
||||
<a class="button button--outline" href="{{ $profile }}" target="_blank" rel="noopener">@schnittfest.gmbh</a>
|
||||
</div>
|
||||
<div class="insta__frame" data-component="reveal">
|
||||
<script src="https://cdn.lightwidget.com/widgets/lightwidget.js"></script>
|
||||
<iframe src="{{ $widget }}" scrolling="no" allowtransparency="true" class="lightwidget-widget insta__widget" title="Instagram"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+36
-9
@@ -1,13 +1,40 @@
|
||||
<section id="start" class="section-start">
|
||||
<div class="container" data-aos="fade-in">
|
||||
<div class="headline">
|
||||
<h1 data-aos="fade-in">
|
||||
Film, auf den Frame genau.
|
||||
<a href="mailto:hi@schnittfest.gmbh">⟶</a>
|
||||
</h1>
|
||||
{{- $headline := default (copy .Page .Content "headline") "Film, auf den Frame genau." -}}
|
||||
{{- $kicker := default (copy .Page .Content "kicker") "Videoproduktion aus Ostwestfalen" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
{{- $ctaLabel := default (copy .Page .Content "cta_label") "Projekt anfragen" -}}
|
||||
{{- $ctaHref := default (copy .Page .Content "cta_href") "mailto:hi@schnittfest.gmbh" -}}
|
||||
{{- $ticker := default (copy .Page .Content "ticker") "Film ✦ Animation ✦ Sound ✦ Schnitt ✦ Color Grading ✦ Drohne ✦ Imagefilm ✦ Commercial ✦" -}}
|
||||
{{- $video := default (get .Content "video") "/static/hero.mp4" -}}
|
||||
{{- $poster := default (get .Content "poster") "/static/1.jpg" -}}
|
||||
|
||||
<section class="intro" id="start" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="intro__inner">
|
||||
<p class="intro__kicker" data-component="reveal"><span class="intro__kicker-dot"></span>{{ $kicker }}</p>
|
||||
<h1 class="intro__headline" data-component="reveal">{{ $headline }}</h1>
|
||||
{{ with $text }}<div class="intro__text" data-component="reveal">{{ html . }}</div>{{ end }}
|
||||
<div class="intro__cta" data-component="reveal">
|
||||
<a class="button button--yellow" href="{{ $ctaHref }}"><span class="button__play" aria-hidden="true"></span>{{ $ctaLabel }}</a>
|
||||
</div>
|
||||
<div id="hero" class="hero" data-aos="fade-in" data-aos-delay="200">
|
||||
<video src="/static/hero.mp4" autoplay loop muted playsinline />
|
||||
|
||||
<div class="viewfinder" data-component="reveal">
|
||||
<video class="viewfinder__video" aria-label="{{ default (copy .Page .Content "video_label") "Showreel von Schnittfest" }}" src="{{ $video }}" poster="{{ $poster }}" autoplay loop muted playsinline></video>
|
||||
<div class="viewfinder__overlay" aria-hidden="true">
|
||||
<span class="viewfinder__corner viewfinder__corner--tl"></span>
|
||||
<span class="viewfinder__corner viewfinder__corner--tr"></span>
|
||||
<span class="viewfinder__corner viewfinder__corner--bl"></span>
|
||||
<span class="viewfinder__corner viewfinder__corner--br"></span>
|
||||
<span class="viewfinder__rec">REC</span>
|
||||
<span class="viewfinder__timecode" data-component="timecode">00:00:00:00</span>
|
||||
<span class="viewfinder__meta">4K · 25 FPS · ISO 800</span>
|
||||
<span class="viewfinder__battery"></span>
|
||||
<span class="viewfinder__focus"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ticker" aria-hidden="true">
|
||||
<div class="ticker__track">
|
||||
<span>{{ $ticker }}</span><span>{{ $ticker }}</span><span>{{ $ticker }}</span><span>{{ $ticker }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+8
-8
@@ -1,6 +1,6 @@
|
||||
<section id="text" class="section-text">
|
||||
<div class="container">
|
||||
<h3>Impressum</h3>
|
||||
<section class="text" id="text" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="text__inner">
|
||||
<h1>Impressum & Datenschutz</h1>
|
||||
<p>
|
||||
Schnittfest GmbH<br>
|
||||
Schulbusch 29<br>
|
||||
@@ -16,22 +16,22 @@
|
||||
Verantwortlich für den Inhalt nach § 55 Abs. 2 RStV ist:<br>
|
||||
Geschäftsführer: Malte Blum
|
||||
</p>
|
||||
<h4>Datenschutz</h4>
|
||||
<h2>Datenschutz</h2>
|
||||
<p>
|
||||
Die Betreiber dieser Seiten nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Wir behandeln Ihre personenbezogenen Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser Datenschutzerklärung.Die Nutzung un serer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder E-Mail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben.Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich.
|
||||
</p>
|
||||
<h4>Cookies</h4>
|
||||
<h2>Cookies</h2>
|
||||
<p>
|
||||
Die Internetseiten verwenden teilweise so genannte Cookies. Cookies richten auf Ihrem Rechner keinen Schaden an und enthalten keine Viren. Cookies dienen dazu, unser Angebot nutzerfreundlicher, effektiver und sicherer zu machen. Cookies sind kleine Textdateien, die auf Ihrem Rechner abgelegt werden und die Ihr Browser speichert. Die meisten der von uns verwendeten Cookies sind so genannte „Session-Cookies“. Sie werden nach Ende Ihres Besuchs automatisch ge löscht. Andere Cookies bleiben auf Ihrem Endgerät gespeichert, bis Sie diese löschen. Diese Cookies ermöglichen es uns, Ihren Browser beim nächsten Besuch wiederzuerkennen.Sie können Ihren Browser so einstellen, dass Sie über das Setzen von Cookies informiert werden und Cookies nur im Einzelfall erlauben, die Annahme von Cookies für bestimmte Fälle oder generell ausschließen sowie das automatische Löschen der Cookies beim Schließen des Browser aktivieren. Bei der Deaktivierung von Cookies kann die Funktionalität dieser Website eingeschränkt sein.
|
||||
</p>
|
||||
<h4>Kontaktformular</h4>
|
||||
<h2>Kontaktformular</h2>
|
||||
<p>
|
||||
Wenn Sie uns per Kontaktformular Anfragen zukommen lassen, werden Ihre Angaben aus dem Anfrageformular inklusive der von Ihnen dort angegebenen Kontaktdaten zwecks Bearbeitung der Anfrage und für den Fall von Anschlussfragen bei uns gespeichert. Diese Daten geben wir nicht ohne Ihre Einwilligung weiter.
|
||||
</p>
|
||||
<h4>SSL-Verschlüsselung</h4>
|
||||
<h2>SSL-Verschlüsselung</h2>
|
||||
<p>
|
||||
Diese Seite nutzt aus Gründen der Sicherheit und zum Schutz der Übertragung vertraulicher Inhalte, wie zum Beispiel der Anfragen, die Sie an uns als Seitenbetreiber senden, eine SSL-Verschlüsselung. Eine verschlüsselte Verbindung erkennen Sie daran, dass die Adresszeile des Browsers von "http://" auf "https://" wechselt und an dem Schloss-Symbol in Ihrer Browserzeile. Wenn die SSL-Verschlüsselung aktiviert ist, können die Daten, die Sie an uns übermitteln, nicht von Dritten mitgelesen werden.
|
||||
</p>
|
||||
<h4>Stand: 24.05.2020</h4>
|
||||
<p class="text__date">Stand: 24.05.2020</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+27
-28
@@ -1,28 +1,27 @@
|
||||
{{if get .Content "full"}}
|
||||
<nav class="header bg-beige-to-black">
|
||||
<div class="container" data-aos="fade-in" data-aos-delay="50">
|
||||
<div id="homeLink" class="wordmark black-to-beige">Schnittfest</div>
|
||||
<ul class="links hide-sm black-to-beige">
|
||||
<li class="scrollToService">Gewerke</li>
|
||||
<li class="scrollToWork">Referenzen</li>
|
||||
<li class="scrollToFooter">Kontakt</li>
|
||||
</ul>
|
||||
<ul class="show-sm black-to-beige">
|
||||
<li id="mobileMenuOpen">Menü</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<nav id="mobileMenu" class="mobile-menu show-sm" style="display:none">
|
||||
<ul>
|
||||
<li class="scrollToService">Gewerke</li>
|
||||
<li class="scrollToWork">Referenzen</li>
|
||||
<li class="scrollToFooter">Kontakt</li>
|
||||
</ul>
|
||||
</nav>
|
||||
{{else}}
|
||||
<nav class="header bg-beige">
|
||||
<div class="container">
|
||||
<div id="homeLink" class="wordmark">Schnittfest</div>
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
{{- $full := get .Content "full" -}}
|
||||
{{- $service := default (copy .Page .Content "service_label") "Leistungen" -}}
|
||||
{{- $work := default (copy .Page .Content "work_label") "Referenzen" -}}
|
||||
{{- $faq := default (copy .Page .Content "faq_label") "FAQ" -}}
|
||||
{{- $contact := default (copy .Page .Content "contact_label") "Kontakt" -}}
|
||||
|
||||
<header class="nav{{ if $full }} nav--full{{ end }}" data-component="nav" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="nav__inner">
|
||||
<a class="nav__brand" href="/" aria-label="Schnittfest – Startseite">
|
||||
<span class="nav__rec" aria-hidden="true"></span>
|
||||
<span class="nav__word">Schnitt<span class="nav__cut" aria-hidden="true">✂</span>fest</span>
|
||||
</a>
|
||||
{{ if $full }}
|
||||
<button class="nav__toggle" type="button" aria-expanded="false" aria-controls="nav-links">
|
||||
<span class="nav__toggle-bar"></span>
|
||||
<span class="nav__toggle-bar"></span>
|
||||
<span class="visually-hidden">Menü</span>
|
||||
</button>
|
||||
<nav class="nav__links" id="nav-links">
|
||||
<a class="nav__link" href="/#service" data-nr="01">{{ $service }}</a>
|
||||
<a class="nav__link" href="/#work" data-nr="02">{{ $work }}</a>
|
||||
<a class="nav__link" href="/#faq" data-nr="03">{{ $faq }}</a>
|
||||
<a class="nav__link nav__link--cta" href="/#footer" data-nr="04">{{ $contact }}</a>
|
||||
</nav>
|
||||
{{ end }}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- $headline := default (copy .Page .Content "headline") "Ablauf" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
|
||||
<section class="process" id="ablauf" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="process__inner">
|
||||
<div class="process__head" data-component="reveal">
|
||||
<h2 class="section-title"><span class="section-title__nr" aria-hidden="true"></span>{{ $headline }}</h2>
|
||||
{{ with $text }}<div class="process__text">{{ html . }}</div>{{ end }}
|
||||
</div>
|
||||
<ol class="process__steps">
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.steps" .Content.Position) (index .Content.Content "steps") }}
|
||||
<slot name="{{ .Content.Position }}/steps"></slot>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,9 @@
|
||||
{{- $title := copy .Page .Content "title" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
{{- $color := default (get .Content "color") "yellow" -}}
|
||||
|
||||
<li class="frame frame--{{ $color }}" data-component="reveal" data-shifu-element="{{ .Content.Position }}">
|
||||
<span class="frame__nr" aria-hidden="true"></span>
|
||||
{{ with $title }}<h3 class="frame__title">{{ . }}</h3>{{ end }}
|
||||
{{ with $text }}<p class="frame__text">{{ . }}</p>{{ end }}
|
||||
</li>
|
||||
+19
-11
@@ -1,15 +1,23 @@
|
||||
<section id="service" class="section-service bg-beige">
|
||||
<div class="container">
|
||||
<div class="services row">
|
||||
<div class="col-lg-4 col-md-4 col-sm-12 col-xs-12">
|
||||
<h2 class="black-to-beige" data-aos="fade-in" data-aos-delay="100">Film</h2>
|
||||
<p class="black-to-beige" data-aos="fade-in" data-aos-delay="100">sleep.shoot.eat.repeat. </p>
|
||||
<h2 class="black-to-beige" data-aos="fade-in" data-aos-delay="200">Animation</h2>
|
||||
<p class="black-to-beige" data-aos="fade-in" data-aos-delay="200">Herausstechen und Welten erschaffen.</p>
|
||||
<h2 class="black-to-beige" data-aos="fade-in" data-aos-delay="300">Sound</h2>
|
||||
<p class="black-to-beige" data-aos="fade-in" data-aos-delay="300">Keine Musik wäre wie Butter ohne Brot.</p>
|
||||
{{- $headline := default (copy .Page .Content "headline") "Gewerke" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
{{- $image := default (get .Content "image") "/static/1.jpg" -}}
|
||||
{{- $caption := copy .Page .Content "image_caption" -}}
|
||||
|
||||
<section class="service" id="service" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="service__inner">
|
||||
<div class="service__head" data-component="reveal">
|
||||
<h2 class="section-title"><span class="section-title__nr" aria-hidden="true"></span>{{ $headline }}</h2>
|
||||
{{ with $text }}<div class="service__text">{{ html . }}</div>{{ end }}
|
||||
</div>
|
||||
<div class="service__grid">
|
||||
<div class="service__items">
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.items" .Content.Position) (index .Content.Content "items") }}
|
||||
<slot name="{{ .Content.Position }}/items"></slot>
|
||||
</div>
|
||||
<div class="col-lg-8 col-md-8 col-sm-12 col-xs-12 img" data-aos="fade-in"></div>
|
||||
<figure class="polaroid" data-component="reveal">
|
||||
<img class="polaroid__image" src="{{ $image }}" alt="{{ default $caption "Schnittfest am Set" }}" loading="lazy" />
|
||||
{{ with $caption }}<figcaption class="polaroid__caption">{{ . }}</figcaption>{{ end }}
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{{- $title := copy .Page .Content "title" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
{{- $color := default (get .Content "color") "red" -}}
|
||||
|
||||
<article class="slate slate--{{ $color }}" data-component="reveal" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="slate__clapper" aria-hidden="true"></div>
|
||||
<div class="slate__body">
|
||||
{{ with $title }}<h3 class="slate__title">{{ . }}</h3>{{ end }}
|
||||
{{ with $text }}<p class="slate__text">{{ . }}</p>{{ end }}
|
||||
</div>
|
||||
</article>
|
||||
+18
-18
@@ -1,6 +1,6 @@
|
||||
<section id="text" class="section-text">
|
||||
<div class="container">
|
||||
<h3>Allgemeine Geschäftsbedingungen</h3>
|
||||
<section class="text" id="text" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="text__inner">
|
||||
<h1>Allgemeine Geschäftsbedingungen</h1>
|
||||
<p>
|
||||
Alle Preise verstehen sich zzgl. 3% Versicherungsgebühr und 19% MwSt.
|
||||
</p>
|
||||
@@ -10,30 +10,30 @@
|
||||
<p>
|
||||
Alle Lieferungen und Leistungen der Schnittfest GmbH erfolgen ausschließlich zu den nachstehenden Bedingungen. Dies gilt insbesondere auch im Falle entgegenstehender Bedingungen des Auftraggebers. Abweichungen sind nur gültig, wenn sie von uns schriftlich bestätigt werden.
|
||||
</p>
|
||||
<h4>1. Vertragsangebot, Vertragsschluss, Vertragsgegenstand</h4>
|
||||
<h2>1. Vertragsangebot, Vertragsschluss, Vertragsgegenstand</h2>
|
||||
<p>
|
||||
Unsere Angebote sind grundsätzlich freibleibend, sofern nicht eine bestimmte Bindungsdauer zugesichert wird. Der Vertrag kommt erst zustande, wenn er durch uns schriftlich bestätigt oder mit der Erfüllung des Auftrags begonnen wurde. Es bleibt ausdrücklich vorbehalten, den Vertragsgegenstand durch einen solchen zu ersetzen, der Mietsache weitestgehend gleichwertig ist. Geringfügige Abweichungen bleiben vorbehalten
|
||||
</p>
|
||||
<h4>2. Entgelt</h4>
|
||||
<h2>2. Entgelt</h2>
|
||||
<p>
|
||||
Der Mietzins für die Mietsache neben Zubehör richtet sich nach der bei Vertragsabschluss gültigen Preisliste zuzüglich Umsatzsteuer und Versicherungsentgelt für die film- und/oder lichttechnische Ausrüstung in der jeweils geltenden Höhe. Einzel- und Pauschalpreise gelten pro Tag. Bei Gerätschaften mit Zubehör gilt der vollständige Listenpreis oder Pauschalpreis auch dann, wenn auf Wunsch des Mieters einzelne Zubehörstücke nicht mitgeliefert wurden.
|
||||
</p>
|
||||
<h4>3. Mietdauer</h4>
|
||||
<h2>3. Mietdauer</h2>
|
||||
<p>
|
||||
Die Nutzungsbefugnis des Mieters erstreckt sich nur auf den vertraglich vereinbarten Zeitraum. Der Mietzins wird für den vollständigen Zeitraum der Mietzeit einschließlich An- und Ablieferung berechnet, spätestens aber ab dem Zeitpunkt der Bereitstellung im Lager Bielefeld oder der Versendung der Waren an den Mieter bis zur Rückgabe. Der Mietzins wird nach vollen Tagessätzen berechnet. Samstage, Sonntage und Feiertage werden voll berechnet. Eine Rückgabe der Geräte an diesen Tagen ist nach Vereinbarung möglich.
|
||||
</p>
|
||||
<p>
|
||||
Wird die Mietsache nicht bis 10.00 Uhr am Rückgabetag an uns ausgehändigt, wird für den Tag der volle Mietzins berechnet, es sei denn, es ist eine spätere Rückgabe vereinbar oder der Mieter weist nach, dass kein oder ein geringerer Schaden entstanden ist. Nimmt der Mieter die Mietsache nicht ab, und teilt er uns dies nicht mindestens 2 Tage vor dem vereinbarten Vertragsbeginn mit, so hat er 50 % des auf die vertragliche Laufzeit entfallenden Mietzinses als Schadenersatz an uns zu zahlen, es sei denn, der Mieter weist nach, dass kein oder ein geringerer Schaden entstanden ist. Sollte uns die vertragsgemäße Übergabe der Geräte an den Kunden dadurch unmöglich werden, dass wir die Geräte ohne unser Verschulden von einem anderen Kunden verspätet oder beschädigt zurückerhalten, so werden wir von unserer Leistung frei und haften für Folgeschäden nur, soweit wir bei dem anderen Kunden deswegen evtl. Schadensersatzansprüche tatsächlich realisieren.
|
||||
</p>
|
||||
<h4>4. Ort</h4>
|
||||
<h2>4. Ort</h2>
|
||||
<p>
|
||||
Der Mieter ist berechtigt, die Mietsache im Gebiet der Bundesrepublik Deutschland zu nutzen. Will er die Mietsache an einen außerhalb der Bundesr epublik Deutschland gelegenen Ort verbringen, so ist hierzu unsere schriftliche Einwilligung erforderlich. In Ländern, in denen Krieg, Bürgerkrieg, Unruhen oder dergleichen herrschen, oder bei sorgfältiger Prüfung zu erwarten ist, dass innerhalb der Mietze it derartiges auftritt, ist eine Verbringung nur dann möglich, wenn dies von uns schriftlich gestattet und von dem Mieter für den Fall eines Totalverlustes der Mietsache zuvor ausreichend Sicherheit bereitgestellt wird. In jedem sonstigen Falle haftet der Mieter in diesen Ländern für entstandene Schäden in voller Höhe.
|
||||
</p>
|
||||
<h4>5. Transportgefahr</h4>
|
||||
<h2>5. Transportgefahr</h2>
|
||||
<p>
|
||||
Der Mieter trägt grundsätzlich die Transportgefahr. Das gilt auch dann, wenn die Versendung durch uns oder von uns beauftragten Dritten vorgenommen wird. Die Kosten der Ve rsendung und der Rücksendung an unsere gewerbliche Niederlassung einschließlich der Kosten einer ordnungsgemäßen Verpackung trägt der Mieter. Wird die Mietsache vom Mieter ins Ausland verbracht oder auf dessen Wunsch von uns dorthin versandt, verpflichtet sich der Mieter zur ordnungsgemäßen Abwicklung des Zollverfahrens. Die daraus resultierenden Kosten trägt der Mieter.
|
||||
</p>
|
||||
<h4>6. Pflichten des Mieters</h4>
|
||||
<h2>6. Pflichten des Mieters</h2>
|
||||
<p>
|
||||
Der Mieter hat uns darüber zu informieren, für welchen Zweck er die Mietsache verwendet. Über Umstände, die unsere Interessen berühren, hat uns der Mieter unaufgefordert zu unterrichten. Der Mieter verpflichtet sich, die Mietsachen pfleglich und sachkundig zu behandeln. Vorbehaltlich des sachgerechten Austauschs von Leuchtmitteln ist der Mieter nicht berechtigt, an den Mietsachen Instandsetzungsarbeiten vorzunehmen. Der Mieter verpflichtet sich, unverzüglich nach Erhalt der Mietsachen zu prüfen, ob diese funktionstüchtig sind und der Bestellung entsprechen. Abweichungen hinsichtlich der Zahl, Art und Güte von der Bestellung, dem Lieferschein und / oder der Rechnung sind unverzüglich zu rügen. Transportschäden sind uns sofort, spätestens aber am 1. Werktag nach der Ablieferung an den Mieter anzuzeigen, da andernfalls der Verlust des Versicherungsschutzes droht.
|
||||
</p>
|
||||
@@ -43,14 +43,14 @@
|
||||
<p>
|
||||
Zusätzlich zum Mietpreis trägt der Kunde gemäß unserer Preisliste anteilig die Kosten der obligatorischen Sachversicherung für die Geräte. Der Mietpreis einschl. Versicherungspauschale erhöht sich um den jeweils gültigen Mehrwertsteuersatz. Erteilte Rechnungen sind ohne Abzug sofort fällig. Der Kunde gerät auch ohne weitere Mahnung spätestens 14 Tage nach dem Rechnungsdatum in Verzug . Wir sind berechtigt, die Übergabe der Geräte oder Waren von einer vollständigen Vorauszahlung abhängig zu machen.
|
||||
</p>
|
||||
<h4>8. Gebrauchsüberlassung an Dritte / Kündigungsrecht</h4>
|
||||
<h2>8. Gebrauchsüberlassung an Dritte / Kündigungsrecht</h2>
|
||||
<p>
|
||||
Die Mietsache steht in unserem Alleineigentum. Es ist dem Mieter grundsätzlich untersagt, die Mietsachen entgeltlich oder unentgeltlich an Dritte zum Gebrauch zu überlassen, wenn nicht unsere schriftliche Einwilligung erteilt wurde. Wir sind berechtigt, den Vertrag sofort zu kündigen, wenn der Mieter die Mietsache unbefugt einem Drit ten überlässt. Gleichzeitig sind wir in diesem Fall zur sofortigen Inbesitznahme der Mietsache berechtigt. Unbeschadet der vorstehenden Regelung ist der Mieter im Falle der entgeltlichen Weitervermietung verpflichtet, die gesamten davon betroffenen Geräte seinem eigenen Versicherungsschutz zu unterstellen und die Schadensregulierung über seine eigene Versicherung vorzunehmen. In derartigen Fällen ist eine Inanspruchnahme unserer Versicherung ausgeschlossen.
|
||||
</p>
|
||||
<p>
|
||||
Der Mieter ist verpflichtet, bei Vollstreckungsmaß nahmen in die Mietsachen und bei Pfändungen auf die Eigentumsverhältnisse hinzuweisen. Er hat uns in diesen Fällen unverzüglich zu unterrichten. Hält der Mieter das vereinbarte Zahlungsziel nicht ein, sind wir berechtigt, den Vertrag fristlos zu kündigen u nd die sofortige Herausgabe der Mietsache zu verlangen. Für den Fall der Durchsetzung des Herausgabeanspruchs ermächtigt der Mieter unwiderruflich uns oder von uns beauftragte Dritte, jeden Raum zu betreten, in dem sich die Mietsache oder Teile davon dann befinden. Der Mieter verzichtet auf die Geltendmachung eines Zurückbehaltungsrechts, gleich aus welchem Rechtsgrunde.
|
||||
</p>
|
||||
<h4>9. Haftung des Vermieters</h4>
|
||||
<h2>9. Haftung des Vermieters</h2>
|
||||
<p>
|
||||
Für entstandene Schäden – gleich aus welchem Rechtsgrund – haften wir grundsätzlich nur bei Vorsatz oder grober Fahrlässigkeit. Bei der Verletzung von wesentlichen Vertragspflichten, bei Fehlen zugesicherter Eigenschaften sowie bei der Verletzung von Leben, Körper oder Gesundheit haften wir auch dann, wenn der Schaden leicht fahrlässig verursacht wurde.
|
||||
</p>
|
||||
@@ -60,21 +60,21 @@
|
||||
<p>
|
||||
Soweit die Haftung nach den vorbezeichneten Bestimmungen beschränkt oder ausgeschlossen ist, gilt dies auch für unsere Vertreter, Arbeitnehmer, Mitarbeiter und Erfüllungsgehilfen. Eine etwaige Haftung nach dem Produkthaftungsgesetz bleibt unberührt.
|
||||
</p>
|
||||
<h4>10. Versicherung</h4>
|
||||
<h2>10. Versicherung</h2>
|
||||
<p>
|
||||
Die Mietsachen sind nach den allgemeinen Bedingungen für die Elektronikversicherung (AEB) versichert. Der Versicherungsvertrag beinhaltet einen verschuldensunabhängigen Selbstbehalt in Höhe von 500,00 € pro Schadenfall. Die Versicherungsbedingungen liegen bei uns zur Einsicht bereit. Es wird ausdrücklich darauf hingewiesen, dass der Versicherungsvertrag nur in Europa gilt. Will der Mieter die Gerätschaften an einen außereuropäischen Ort verbringen, so hat er dies vor Vertragsschluss mitzuteilen, damit für uns ausreichend Zeit zur Verfügung steht, die Mietsache g egen die Gefahrenerhöhung zu versichern. Bei gefährlichen Einsätzen, wie sie z.B. bei Fahr - , Hubschrauber - , Unterwasser - , Hochsee - (außerhalb der 3 Meilenzone), Hochgebirgsaufnahmen und dergleichen vorliegen, sind zwecks Abschluss einer Zusatzversicherung entsprechende Hinweise an uns bei Vertragschluss zu machen. Die Kosten für eine erforderliche Zusatzversicherung trägt in jedem Falle der Mieter.
|
||||
</p>
|
||||
<p>
|
||||
Der Mieter ist bei Diebstahl, Unterschlagung, Raub oder Veruntreuung durch Dritte oder sonstigem Abhandenkomme n der Mietsache verpflichtet, dieses Ereignis unverzüglich polizeilich anzuzeigen und einen ausführlichen Schadensbericht anzufertigen. Das Nichtbefolgen dieser Pflicht führt zur vollständigen Haftung des Mieters. Nach den Versicherungsbedingungen sind Sch äden an Leuchtmitteln und Kathodenstrahlröhren nicht versichert.
|
||||
</p>
|
||||
<h4>11. Haftung des Mieters / Ausfallschäden</h4>
|
||||
<h2>11. Haftung des Mieters / Ausfallschäden</h2>
|
||||
<p>
|
||||
Während der gesamten Mietdauer übernimmt der Mieter für die gemieteten Gegenstände samt Zubehör die Haftung, auch für Zufall. Entstehen beim Mieter od er Dritten beim Gebrauch der Mietsache Schäden, die auf eine unqualifizierte oder unsachgemäße Ingebrauchnahme der Mietsache oder des Zubehörs zurückzuführen sind, so haftet der Mieter hierfür uneingeschränkt und hat uns auf Verlangen von der Haftung gegen über Dritten freizustellen. Besteht eine Versicherung für eine Gefahr und wird ein Schaden nicht in der entstandenen Höhe von dieser Versicherung getragen, so haftet der Mieter für den Differenzbetrag. Kathodenstrahlröhren nicht versichert.
|
||||
</p>
|
||||
<p>
|
||||
Gibt der Mieter die Mietsache mangelhaft oder nicht zu rück, so hat er während der Reparatur oder Wiederbeschaffungszeit Nutzungsausfall in Höhe des Mietzinses zu zahlen, es sei denn, der Mieter weist nach, dass kein oder ein geringerer Schaden entstanden ist
|
||||
</p>
|
||||
<h4>12. Zahlungsbedingungen</h4>
|
||||
<h2>12. Zahlungsbedingungen</h2>
|
||||
<p>
|
||||
Es ist grundsätzlich Zahlu ng bei Auslieferung bzw. Übergabe vereinbart. Abweichende Zahlungsziele müssen schriftlich vereinbart werden. Eine Aufrechnung gegen unsere Forderungen ist ausgeschlossen, es sei denn, dass die Gegenforderung unbestritten oder rechtskräftig festgestellt is t. Gleiches gilt für die Geltendmachung eines Zurückbehaltungsrechts.
|
||||
</p>
|
||||
@@ -84,18 +84,18 @@
|
||||
<p>
|
||||
Vereinbarte Preisnachlässe geraten bei Zahlungsverzug des Mieters sowie bei einer ge richtlichen Geltendmachung unserer Forderungen in Wegfall.
|
||||
</p>
|
||||
<h4>14. Erfüllungsort, Rechtswahl und Gerichtsstand</h4>
|
||||
<h2>14. Erfüllungsort, Rechtswahl und Gerichtsstand</h2>
|
||||
<p>
|
||||
Erfüllungsort für Lieferung und Leistungen aus diesem Vertrag ist Bielefeld . Für die auf Grundlage dieser Bedingungen abgeschlossenen Verträge und der aus Ihnen folgenden Ansprüche gilt deutsches Recht. Für sämtliche gegenwärtigen und zukünftigen Ansprüche aus der Geschäftsbeziehung einschließlich Wechsel- und Scheckforderungen ist, wenn der Vertragspartner Unternehmer, eine juristische Person des öffentlichen Rechts oder ein öffentlich-rechtliches Sondervermögen ist, ausschließlicher Gerichtsstand Bielefeld .
|
||||
</p>
|
||||
<h4>15. Schriftform</h4>
|
||||
<h2>15. Schriftform</h2>
|
||||
<p>
|
||||
Mündliche Nebenabreden sind zu diesem Vertrag nicht getroffen worden. Änderungen und Ergänzungen sowie die teilweise oder gesamte Aufhebung des Vertrages bedürfen der Schriftform. Dies gilt auch für die Aufhebung oder Änderung des Schriftformerfordernisses.
|
||||
</p>
|
||||
<h4>16. Salvatorische Klausel</h4>
|
||||
<h2>16. Salvatorische Klausel</h2>
|
||||
<p>
|
||||
Sollte eine Bestimmung oder mehrere Bestimmungen dieser Vereinbarung unwirksam sein oder werden, so bl eiben die übrigen Bestimmungen wirksam. Die Parteien verpflichten sich, die unwirksame Bestimmung durch eine wirksame Bestimmung zu ersetzen, die dem ursprünglichen wirtschaftlichen Inhalt der unwirksamen Bestimmung weitestgehend entspricht .
|
||||
</p>
|
||||
<h4>Stand: 24.05.2020</h4>
|
||||
<p class="text__date">Stand: 24.05.2020</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
+15
-3
@@ -1,5 +1,17 @@
|
||||
<section id="work" class="section-work">
|
||||
<div class="container">
|
||||
{{.CMS.Render .Args .Page (fmt "%s.content" .Content.Position) (index .Content.Content "content")}}
|
||||
{{- $headline := default (copy .Page .Content "headline") "Referenzen" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
|
||||
<section class="work" id="work" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="filmstrip" aria-hidden="true"></div>
|
||||
<div class="work__inner">
|
||||
<div class="work__head" data-component="reveal">
|
||||
<h2 class="section-title section-title--light"><span class="section-title__nr" aria-hidden="true"></span>{{ $headline }}</h2>
|
||||
{{ with $text }}<div class="work__text">{{ html . }}</div>{{ end }}
|
||||
</div>
|
||||
<div class="work__list">
|
||||
{{ .CMS.Render .Args .Page (fmt "%s.content" .Content.Position) (index .Content.Content "content") }}
|
||||
<slot name="{{ .Content.Position }}/content"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filmstrip filmstrip--bottom" aria-hidden="true"></div>
|
||||
</section>
|
||||
|
||||
+14
-9
@@ -1,11 +1,16 @@
|
||||
<div class="video row reverse">
|
||||
<div class="col-lg-4 col-md-12 col-sm-12 col-xs-12">
|
||||
<h2 class="black-to-beige" data-aos="fade-in" data-aos-delay="100">{{copy .Page .Content "h2"}}</h2>
|
||||
<p class="black-to-beige" data-aos="fade-in" data-aos-delay="200">{{copy .Page .Content "text"}}</p>
|
||||
{{- $title := copy .Page .Content "h2" -}}
|
||||
{{- $text := copy .Page .Content "text" -}}
|
||||
{{- $video := get .Content "video" -}}
|
||||
|
||||
<article class="take" data-component="reveal" data-shifu-element="{{ .Content.Position }}">
|
||||
<div class="take__info">
|
||||
<span class="take__label" aria-hidden="true">Take</span>
|
||||
{{ with $title }}<h3 class="take__title">{{ . }}</h3>{{ end }}
|
||||
{{ with $text }}<p class="take__text">{{ . }}</p>{{ end }}
|
||||
</div>
|
||||
<div class="col-lg-8 col-md-12 col-sm-12 col-xs-12">
|
||||
<div style="padding:56.25% 0 0 0;position:relative;" data-aos="fade-in">
|
||||
<iframe src="{{get .Content "video"}}" style="position:absolute;top:0;left:0;width:100%;height:100%;" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
<div class="take__screen">
|
||||
{{ with $video }}
|
||||
<iframe class="take__video" src="{{ . }}" title="{{ default $title "Video" }}" loading="lazy" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
Reference in New Issue
Block a user