/* =========================================================
   AS-Deko · Site CSS

   Port of the Claude design draft. In the draft every rule sat as an inline
   style inside the HTML; here they live as classes so that the Django templates
   stay readable. Values, spacings and animations are carried over unchanged.

   Fixed design variants: theme "light", hero "cross fade b/w",
   gallery part 1 as masonry.
   ========================================================= */

/* Deliberately hard while loading: if the page is opened with a jump anchor —
   /#kontakt after submitting, for instance — smooth scrolling would first put
   the visitor at the top and then visibly travel downwards. The script switches
   to smooth after loading, so that anchor links glide gently during use. */
html { scroll-behavior: auto; }
html.scroll-smooth { scroll-behavior: smooth; }

/* The navigation sits fixed above the content (75 px tall). Without this offset
   the heading of a jumped-to section slides underneath it and can no longer be
   seen — on narrow devices this is most noticeable, because there is little
   height available there anyway. */
#start, #vorher, #ueber, #kontakt, #galerie, #inhalt {
  scroll-margin-top: 95px;
}

@media (prefers-reduced-motion: reduce) {
  html, html.scroll-smooth { scroll-behavior: auto; }
}

/* ---------------------------------------------------------
   Theme
   The design knows a dark and a light theme. The light one runs live; the
   --s* variables remain as a layer so that a later switch costs no more than
   one class on the wrapper.
   --------------------------------------------------------- */

.site {
  --sbg: #F4F2EE;
  --sfg: #0E0E0E;
  --smut: #5F594F;
  --sfaint: #847C70;
  --sbord: rgba(14, 14, 14, 0.10);
  --sbord2: rgba(14, 14, 14, 0.32);
  --ssurf: rgba(255, 255, 255, 0.7);
  --sbtnbg: #0E0E0E;
  --sbtnfg: #F4F2EE;
  --snav: rgba(244, 242, 238, 0.72);

  background: var(--sbg);
  color: var(--sfg);
  font-family: var(--font-body);
  min-height: 100vh;
}

/* Images carry width/height as attributes so that the browser can reserve the
   space before loading and nothing jumps. Without `height: auto` the attribute
   height would however act as a fixed CSS height and distort the image. */
img {
  max-width: 100%;
  height: auto;
}

.wrap {
  max-width: var(--container-base);
  margin: 0 auto;
  padding: 0 32px;
}

.wrap-wide { max-width: 1280px; }

/* Jump anchor for keyboard users, visible only on focus. */
.skip-link {
  position: absolute;
  left: -9999px;
  z-index: 200;
  padding: 14px 22px;
  background: var(--ink);
  color: var(--paper);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus { left: 16px; top: 16px; }

.eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--leaf);
  margin-bottom: 14px;
}

/* ---------------------------------------------------------
   Navigation
   --------------------------------------------------------- */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  backdrop-filter: blur(16px) saturate(120%);
  -webkit-backdrop-filter: blur(16px) saturate(120%);
  background: var(--snav);
  border-bottom: 1px solid var(--sbord);
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 32px;
}

.nav-brand {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: 0.02em;
  color: var(--sfg);
  text-decoration: none;
}

.nav-right { display: flex; align-items: center; gap: 26px; }
.nav-left { display: flex; gap: 26px; font-size: 13.5px; font-weight: 600; }
.nav-left a,
.nav-back {
  color: var(--smut);
  text-decoration: none;
}
.nav-left a:hover,
.nav-back:hover { color: var(--leaf); }
.nav-back { font-size: 13.5px; font-weight: 600; }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--sbtnbg);
  color: var(--sbtnfg);
  border: 0;
  padding: 10px 20px;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-default),
              color var(--duration-fast) var(--ease-default);
}
.btn:hover { background: var(--leaf); color: var(--ink); }

.btn-large { padding: 16px 28px; font-size: 15px; }

.btn-ghost {
  background: transparent;
  border: 1px solid var(--sbord2);
  color: var(--sfg);
  padding: 15px 28px;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  transition: color var(--duration-fast), border-color var(--duration-fast);
}
.btn-ghost:hover { border-color: var(--leaf); color: var(--leaf); }

.arrow { font-family: var(--font-mono); }

/* ---------------------------------------------------------
   Hero with cross fade
   Six grayscale photos fade into one another. Duration and delay come as CSS
   variables from the template, so that the fade runs evenly for any number of
   images.
   --------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  padding: 150px 0 64px;
}

.hero-stage { position: absolute; inset: 0; background: #0E0E0E; }

.hero-photo {
  position: absolute;
  inset: 0 0 0 25%;
  background-size: cover;
  background-position: center;
  filter: grayscale(1) brightness(0.88) contrast(1.04);
  opacity: 0;
  animation: heroXfade var(--hero-duration, 24s) linear infinite;
  animation-delay: var(--hero-delay, 0s);
}

/* The first image additionally lies statically underneath, so that no empty
   area is visible before the first run of the animation. */
.hero-photo-base { opacity: 1; animation: none; }

@keyframes heroXfade {
  0%     { opacity: 0; }
  4.2%   { opacity: 1; }
  16.7%  { opacity: 1; }
  20.9%  { opacity: 0; }
  100%   { opacity: 0; }
}

.hero-veil {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 85% 140% at 20% 50%,
    #0E0E0E 0%,
    rgba(14, 14, 14, 0.94) 34%,
    rgba(14, 14, 14, 0.58) 52%,
    rgba(14, 14, 14, 0.20) 70%,
    rgba(14, 14, 14, 0.03) 88%,
    rgba(14, 14, 14, 0) 100%);
}

.hero-content { position: relative; z-index: 2; }

/* On the fade the text is always light, independent of the theme. */
.hero h1 { color: #F4F2EE; }
.hero-text { color: #C9C2B4; }
.hero-meta {
  color: #A9A193;
  border-color: rgba(244, 242, 238, 0.16);
  margin-top: 56px;
  padding-top: 18px;
  border-top: 1px solid rgba(244, 242, 238, 0.16);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.hero .btn { background: #F4F2EE; color: #0E0E0E; }
.hero .btn:hover { background: var(--leaf); color: var(--ink); }
.hero .btn-ghost { border-color: rgba(244, 242, 238, 0.32); color: #F4F2EE; }
.hero .btn-ghost:hover { border-color: var(--leaf); color: var(--leaf); }

.hero h1 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: clamp(48px, 7.2vw, 104px);
  line-height: 0.98;
  letter-spacing: -0.025em;
  margin: 0 0 30px;
  max-width: 14ch;
  text-wrap: balance;
}

.hero h1 .display-hand {
  color: var(--leaf);
  display: inline-block;
  transform: translateY(0.04em) rotate(-1.5deg);
}

.hero-text {
  font-size: 19px;
  line-height: 1.55;
  max-width: 52ch;
  margin: 0 0 38px;
}

.hero-ctas { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }

/* ---------------------------------------------------------
   Sections
   --------------------------------------------------------- */

.section {
  position: relative;
  padding: 96px 0;
  border-top: 1px solid var(--sbord);
}

.section h2 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: clamp(30px, 3.6vw, 52px);
  line-height: 1.02;
  letter-spacing: -0.025em;
  margin: 0;
  color: var(--sfg);
}

.section-content { position: relative; z-index: 2; }

.sec-grid {
  display: grid;
  grid-template-columns: minmax(260px, 1fr) 2fr;
  gap: 48px;
}

.prose { font-size: 17px; line-height: 1.6; color: var(--smut); }

/* One statement instead of three pills.
   Pills read as tags - three of them next to each other invite comparison and
   suggest a list that could be continued. The claim is a single sentence and
   gets the form of one: heading type, marked by a short leaf coloured rule
   that picks up the eyebrow above it. Rounded pills also sat against the
   editorial look, which works with sharp corners (--radius-0). */
.claim-line {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 28px 0 0;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: clamp(20px, 2.2vw, 26px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--sfg);
}

/* flex: none, otherwise the rule shrinks away next to the text as soon as the
   column gets narrow. */
.claim-line::before {
  content: "";
  flex: none;
  width: 40px;
  height: 3px;
  background: var(--leaf);
}

/* ---------------------------------------------------------
   Before/after
   --------------------------------------------------------- */

.ba-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 34px;
}

.ba-counter {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--sfaint);
}
.ba-counter .number { color: var(--leaf); }

.ba-window { overflow: hidden; }
.ba-track {
  display: flex;
  align-items: flex-start;
  transition: transform 460ms var(--ease-default);
}
.ba-slide { min-width: 100%; }

/* The stage has a fixed landscape format, independent of the images stored.
   Reason: all slides lie side by side in the same track — if each brought its
   own ratio along, the height would jump when paging on, and a portrait pair
   would tear the section open across the full screen height.

   3:2 is the classic 35 mm format, in which camera shots arrive anyway — they
   fit without cropping. The draft had 1385 × 912 (= 1.519:1), which went back
   to the dimensions of one concrete example photo; 3:2 is 1.2 % off and is the
   round equivalent.

   Diverging landscape formats are cut in centred via `cover`; portrait format
   is rejected by the admin from the outset. */
.ba-stage {
  position: relative;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: #14161a;
  cursor: ew-resize;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
}

.ba-layer {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  pointer-events: none;
}

/* The before layer is clipped open from the left. */
.ba-before {
  position: absolute;
  inset: 0;
  clip-path: inset(0 50% 0 0);
  will-change: clip-path;
}

.ba-tag {
  position: absolute;
  top: 14px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 6px 11px;
  border-radius: var(--radius-pill);
  line-height: 1;
  z-index: 3;
  pointer-events: none;
}
.ba-tag-before {
  left: 14px;
  background: rgba(14, 14, 14, 0.7);
  color: var(--paper);
  backdrop-filter: blur(6px);
}
.ba-tag-after { right: 14px; background: var(--leaf); color: var(--ink); }

.ba-divider { position: absolute; top: 0; bottom: 0; width: 0; z-index: 4; left: 50%; }
.ba-line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 2px;
  background: var(--paper);
  box-shadow: 0 0 0 1px rgba(14, 14, 14, 0.18), 0 0 16px rgba(14, 14, 14, 0.35);
  transform: translateX(-1px);
}

.ba-handle {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translate(-50%, -50%);
  width: 50px;
  height: 50px;
  border-radius: var(--radius-pill);
  background: var(--paper);
  color: var(--ink);
  border: 2px solid var(--paper);
  box-shadow: 0 6px 18px -6px rgba(14, 14, 14, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: ew-resize;
  padding: 0;
  touch-action: none;
}
.ba-handle:hover { background: var(--leaf); border-color: var(--leaf); }
.ba-handle svg { margin: 0 -3px; }

/* Before the first touch the handle pulses, so that it is recognisable that it
   can be dragged. After the first interaction this stops for good. */
@keyframes ba-pulse {
  0%, 100% { box-shadow: 0 6px 18px -6px rgba(14, 14, 14, 0.55), 0 0 0 0 rgba(111, 170, 42, 0.5); }
  50%      { box-shadow: 0 6px 18px -6px rgba(14, 14, 14, 0.55), 0 0 0 13px rgba(111, 170, 42, 0); }
}
@keyframes ba-fade {
  0%, 100% { opacity: .35; }
  50%      { opacity: 1; }
}
.ba-hint { animation: ba-pulse 1.9s cubic-bezier(0.2, 0.6, 0.2, 1) infinite; }
.ba-nudge {
  position: absolute;
  top: calc(50% + 40px);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--paper);
  background: rgba(14, 14, 14, 0.55);
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  z-index: 4;
  pointer-events: none;
  animation: ba-fade 2.4s ease-in-out infinite;
}

.ba-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 18px;
  gap: 14px;
}
.ba-dots { display: flex; gap: 8px; }
.ba-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-pill);
  border: 0;
  padding: 0;
  cursor: pointer;
  background: var(--sbord2);
  transition: width var(--duration-fast), background var(--duration-fast);
}
.ba-dot[aria-current="true"] { width: 22px; background: var(--leaf); }

.round-btn {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--sbord2);
  background: transparent;
  color: var(--sfg);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: border-color 160ms, color 160ms;
}
.round-btn:hover { border-color: var(--leaf); color: var(--leaf); }
.ba-arrows { display: flex; gap: 8px; }

/* ---------------------------------------------------------
   Logowall
   --------------------------------------------------------- */

.lw {
  padding: 28px clamp(24px, 5vw, 72px) 34px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  border-top: 1px solid var(--sbord);
}
.lw-eyebrow {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-muted);
}
.lw-marquee {
  position: relative;
  overflow: hidden;
  margin-top: 18px;
  touch-action: pan-y;
  cursor: grab;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}
.lw-marquee:active { cursor: grabbing; }
.lw-track {
  display: flex;
  align-items: center;
  gap: clamp(28px, 4vw, 60px);
  width: max-content;
  will-change: transform;
  user-select: none;
  -webkit-user-select: none;
}
.lw-logo {
  height: clamp(40px, 4.8vw, 66px);
  width: auto;
  display: block;
  object-fit: contain;
  filter: brightness(0);
  opacity: 0.72;
  transition: opacity 240ms var(--ease-default);
}
.lw-logo:hover { opacity: 1; }
.lw-sep {
  color: var(--leaf);
  font-size: 26px;
  line-height: 1;
  opacity: 0.85;
  user-select: none;
}

/* ---------------------------------------------------------
   Contact form
   --------------------------------------------------------- */

/* First column at 224 px minimum width (previously 280 px, so 20 % narrower),
   so that the two-column layout carries longer on narrow tablets. */
.contact-grid {
  display: grid;
  grid-template-columns: minmax(224px, 1.3fr) minmax(0, 1.3fr);
  gap: 56px;
}

.contact-data {
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 15px;
  color: var(--smut);
}
.contact-data dt,
.contact-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sfaint);
  display: inline-block;
  width: 76px;
}
.contact-data a { color: inherit; text-decoration: none; }
.contact-data a:hover { color: var(--leaf); }

/* The browser shifts the view on its own when the height of an area changes
   (scroll anchoring). When the form is exchanged for the shorter confirmation
   this causes the confirmation to slide out of view. The script restores the
   position itself and needs no second corrector for that. */
[data-inquiry-area] { overflow-anchor: none; }

.form { display: flex; flex-direction: column; gap: 18px; }

/* The minimum width steers the grid, not the input field: `auto-fit` places
   name and email side by side as long as both get 224 px, and otherwise wraps
   them underneath one another by itself. The `min(…, 100%)` prevents the
   224 px from causing an overflow themselves on very narrow devices. */
.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(224px, 100%), 1fr));
  gap: 18px;
}
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }

.field label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--sfg);
}
.field .optional { font-weight: 400; color: var(--sfaint); }
.required { color: var(--leaf); }

/* Input fields come with an intrinsic minimum width of about 20 characters
   (around 366 px including inner padding). Inside a flex or grid container
   `min-width: auto` applies, which is why they do not shrink below that and
   run past the screen edge on narrow devices — at 320 px the page was 386 px
   wide and could be pushed sideways.

   `min-width: 0` lifts the block, `width: 100%` with `border-box` lets the
   field follow the container exactly. The lower bound is set by the grid
   (see .field-row), not by the field itself. */
.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field textarea {
  background: var(--ssurf);
  border: 1px solid var(--sbord2);
  color: var(--sfg);
  padding: 13px 14px;
  font-family: var(--font-body);
  font-size: 15px;
  outline: none;
  border-radius: 0;
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
}
.field textarea { resize: vertical; }
.field input:focus,
.field textarea:focus { border-color: var(--leaf); }

.field-error {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--leaf-700);
}

.file-field {
  border: 1px dashed var(--sbord2);
  padding: 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  transition: border-color var(--duration-fast);
}
.file-field:hover,
.file-field:focus-within { border-color: var(--leaf); }
.file-field input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }
.file-button {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--leaf-700);
}
.file-name { font-size: 13.5px; color: var(--sfaint); }

.consent {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  cursor: pointer;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--smut);
}
.consent input {
  margin-top: 3px;
  accent-color: #6FAA2A;
  width: 16px;
  height: 16px;
}
.consent a {
  color: var(--sfg);
  text-decoration: underline;
  text-decoration-color: var(--leaf);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

/* Honeypot: unreachable for humans, tempting for bots. Deliberately not
   display:none - some bots skip hidden fields. */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.sent {
  border: 1px solid var(--leaf);
  padding: 36px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.sent-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--leaf-700);
}
.sent-title {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 26px;
  letter-spacing: -0.02em;
  color: var(--sfg);
}

.note {
  border-left: 3px solid var(--leaf);
  background: var(--ssurf);
  padding: 14px 18px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--smut);
}
.note[hidden] { display: none; }

/* While the form is on its way. Prevents double submission and makes visible
   that something is happening. */
.form button[type="submit"]:disabled {
  opacity: 0.65;
  cursor: progress;
}

/* A field the server has objected to. */
.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: var(--leaf-600);
}

/* ---------------------------------------------------------
   Gallery teaser on the home page
   --------------------------------------------------------- */

.gal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 16px; }
.gal-tile { display: block; overflow: hidden; text-decoration: none; }
.gal-tile img {
  width: 100%;
  height: 340px;
  object-fit: cover;
  display: block;
  transition: transform var(--duration-slow) var(--ease-default);
}
.gal-tile:hover img { transform: scale(1.02); }
.gal-tile-small img { height: 300px; }

/* ---------------------------------------------------------
   Gallery page
   --------------------------------------------------------- */

/* Only padding-top/-bottom, never the shorthand: `.page-head` always sits
   together with `.wrap` on the same element, and a `padding: 150px 0 40px`
   would set its lateral 32 px to zero. This became visible between 760 px
   (where the mobile breakpoint sets padding-left/-right explicitly) and
   1120 px (from there on max-width centres and creates a margin by itself) —
   in between, the headings of imprint and privacy stuck to the left screen
   edge. */
.page-head {
  padding-top: 150px;
  padding-bottom: 40px;
}
.page-head h1 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: clamp(38px, 5vw, 72px);
  line-height: 1.0;
  letter-spacing: -0.025em;
  margin: 0 0 16px;
  color: var(--sfg);
}
.page-text {
  font-size: 17px;
  line-height: 1.6;
  color: var(--smut);
  max-width: 56ch;
  margin: 0 0 44px;
}

/* Part 1: masonry via columns. The images keep their aspect ratio. */
.mas { column-count: 3; column-gap: 16px; }
.mas-item {
  break-inside: avoid;
  margin-bottom: 16px;
  cursor: zoom-in;
  display: block;
  width: 100%;
  border: 0;
  padding: 0;
  background: none;
  text-align: left;
}
.mas-item .frame { overflow: hidden; }
.mas-item img {
  width: 100%;
  /* Must stay auto: the height attribute carries the original height in pixels. */
  height: auto;
  display: block;
  transition: transform var(--duration-slow) var(--ease-default);
}
.mas-item:hover img { transform: scale(1.02); }

.image-caption {
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--sfaint);
}
.image-caption .number { color: var(--leaf); }

/* Part 2: cutout pieces on a light box. */
.workshop-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
}
.workshop-card {
  background: var(--ssurf);
  border: 1px solid var(--sbord);
  padding: 24px 18px 14px;
  cursor: zoom-in;
  transition: border-color var(--duration-fast);
  text-align: left;
  font: inherit;
  color: inherit;
}
.workshop-card:hover { border-color: var(--leaf); }
.workshop-card img {
  width: 100%;
  height: 240px;
  object-fit: contain;
  display: block;
}

/* ---------------------------------------------------------
   Lightbox
   --------------------------------------------------------- */

.lb {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: rgba(14, 14, 14, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 56px;
}
.lb[hidden] { display: none; }
.lb-image {
  max-width: 82vw;
  max-height: 82vh;
  object-fit: contain;
  filter: drop-shadow(0 24px 40px rgba(0, 0, 0, 0.5));
}
/* Cutout pieces need a light ground, otherwise they disappear. */
.lb-box {
  background: #F4F2EE;
  padding: 48px;
  max-height: 82vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lb-box .lb-image { max-width: 60vw; max-height: 70vh; filter: none; }

.lb-cap {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 20px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--stone-300);
  pointer-events: none;
  padding: 0 60px;
}
.lb-cap .number { color: var(--leaf); }

.lb-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(244, 242, 238, 0.32);
  background: rgba(14, 14, 14, 0.5);
  color: #F4F2EE;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lb-nav:hover { border-color: var(--leaf); color: var(--leaf); }
.lb-prev { left: 24px; }
.lb-next { right: 24px; }
.lb-close {
  position: absolute;
  right: 24px;
  top: 24px;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(244, 242, 238, 0.32);
  background: rgba(14, 14, 14, 0.5);
  color: #F4F2EE;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lb-close:hover { border-color: var(--leaf); color: var(--leaf); }

/* ---------------------------------------------------------
   Decorations at the page margin
   Cutout workshop pieces floating in the margin zones. They sit centred in the
   space between screen edge and content.
   --------------------------------------------------------- */

.decor-slot {
  position: absolute;
  z-index: 1;
  pointer-events: none;
  width: var(--decor-width, 180px);
}
/* Three layers, because CSS knows only one `transform` property per element and
   the value set last replaces all previous ones. Kept apart, floating
   (.decor-float), hovering and clicking (.decor-motif) overlay each other
   cleanly instead of cutting one another off. */
.decor-float { display: block; }

.decor-motif {
  width: 100%;
  display: block;
  filter: drop-shadow(0 24px 30px rgba(0, 0, 0, 0.28));
  transform-origin: center center;
  user-select: none;
  -webkit-user-drag: none;
}

/* The decoration sits centred in the space between screen edge and content:
   gutter = (100vw - content width)/2, its centre = /4, minus half the image
   width.

   The `max(…)` catches the case that the margin zone is narrower than half the
   decoration: at 1440 px screen width and a 200 px wide motif the calculation
   goes negative, and the image would push the page wider — visible as a
   horizontal scrollbar. Instead of sticking out, it lays itself against the
   edge.

   The minimum distance is deliberately 12 px and not 0: the floating animation
   rotates the motifs by up to 2.5°, which makes the area they actually occupy
   wider than the image itself (at 190 × 285 px around 12 px, so 6 per side). */
.decor-left {
  left: max(12px, calc((100vw - var(--decor-container, 1120px)) / 4 - var(--decor-width, 180px) / 2));
}
.decor-right {
  right: max(12px, calc((100vw - var(--decor-container, 1120px)) / 4 - var(--decor-width, 180px) / 2));
}

@keyframes decor-float-a {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50%      { transform: translateY(-14px) rotate(-2deg); }
}
@keyframes decor-float-b {
  0%, 100% { transform: translateY(0) rotate(2.5deg); }
  50%      { transform: translateY(-20px) rotate(2.5deg); }
}
@keyframes decor-float-c {
  0%, 100% { transform: translateY(-8px); }
  50%      { transform: translateY(8px); }
}
.decor-a { animation: decor-float-a 7.5s ease-in-out infinite; }
.decor-b { animation: decor-float-b 9s ease-in-out infinite; }
.decor-c { animation: decor-float-c 8.5s ease-in-out infinite; }

/* ---------------------------------------------------------
   Touchable decorations

   Only takes effect when the template has set `data-decor` — controlled via
   DECOR_INTERACTIVE in the .env. Without the attribute everything stays as it
   was: no clicks, no cursor change, no reaction.
   --------------------------------------------------------- */

.decor-slot[data-decor] {
  pointer-events: auto;
  cursor: pointer;
}

/* Hint on hovering over it: tilt once to the right and straight back into the
   starting position.

   What matters is the tilting back: if the motif stayed tilted, there would be
   a jump at the end of every click animation — the animation ends at 0°, after
   which the still applied hover state would pull it back to 4°. Because the
   movement ends in its starting position, there is no longer any conflict
   between hovering and clicking.

   It is triggered by the script on `mouseenter`, not via `:hover` in the
   stylesheet: a hover selector would be more specific than the click classes
   and would displace their animation as long as the pointer rests on it. */
.decor-tilt {
  transform-origin: center center;
  animation: decor-tilt 620ms var(--ease-out-slow);
}

@keyframes decor-tilt {
  0%   { transform: rotate(0deg) translateY(0); }
  32%  { transform: rotate(5deg) translateY(-6px); }
  64%  { transform: rotate(-1.5deg) translateY(-2px); }
  100% { transform: rotate(0deg) translateY(0); }
}

/* The four movements on clicking. The script attaches the class and takes it
   off again after `animationend`. No `animation-fill-mode`: afterwards the
   motif should stand exactly where it stood before. */
/* The motifs carry a drop-shadow filter that is recalculated on every rotation.
   `will-change` asks the browser to put the element on its own layer for the
   duration of the movement — only during the animation, set permanently it
   costs memory needlessly. */
.decor-tilt,
.decor-click-swing,
.decor-click-hop,
.decor-click-flip,
.decor-click-squash {
  will-change: transform;
}

/* The keyframes lie on the reversal points of the pendulum, where the movement
   stands still. `ease-in-out` per section matches this behaviour exactly. */
.decor-click-swing {
  transform-origin: top center;
  animation: decor-click-swing 1100ms ease-in-out;
}
.decor-click-hop {
  transform-origin: bottom center;
  animation: decor-click-hop 700ms cubic-bezier(0.3, 0.7, 0.4, 1);
}
/* `linear`, and not some soft curve: a timing function acts in CSS per keyframe
   section, not across the whole animation. With an ease curve the rotation
   braked at each of the intermediate steps and picked up again — that was the
   stuttering. Interpolated evenly it turns through; the jump curve sits instead
   in the distribution of the keyframes. */
.decor-click-flip {
  transform-origin: center center;
  animation: decor-click-flip 900ms linear;
}
.decor-click-squash {
  transform-origin: bottom center;
  animation: decor-click-squash 600ms cubic-bezier(0.3, 0.8, 0.4, 1);
}

/* Nudged mobile: tips far out and swings to rest in ever smaller
   deflections. */
@keyframes decor-click-swing {
  0%   { transform: rotate(0deg); }
  14%  { transform: rotate(-15deg); }
  31%  { transform: rotate(11deg); }
  47%  { transform: rotate(-7.5deg); }
  62%  { transform: rotate(4.5deg); }
  76%  { transform: rotate(-2.5deg); }
  89%  { transform: rotate(1deg); }
  100% { transform: rotate(0deg); }
}

/* Jump with squash and stretch: first duck, stretch in the air, squash on
   landing. Without this deformation a hop looks stiff. */
@keyframes decor-click-hop {
  0%   { transform: translateY(0) scale(1, 1); }
  16%  { transform: translateY(0) scale(1.07, 0.9); }
  34%  { transform: translateY(-24px) scale(0.94, 1.09); }
  54%  { transform: translateY(-30px) scale(1, 1); }
  74%  { transform: translateY(0) scale(1.09, 0.9); }
  88%  { transform: translateY(0) scale(0.98, 1.03); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* Full rotation with a brief lift-off — the most conspicuous of the four.

   The angle grows in exactly equal steps (45° per eighth), so that the rotation
   feels even. The height follows a projectile parabola (h = 4·H·t·(1−t) with
   H = 30 px), resolved finely enough that the linear interpolation in between
   does not stand out as a kink. */
@keyframes decor-click-flip {
  0%     { transform: translateY(0)      rotate(0deg); }
  12.5%  { transform: translateY(-13px)  rotate(45deg); }
  25%    { transform: translateY(-22px)  rotate(90deg); }
  37.5%  { transform: translateY(-28px)  rotate(135deg); }
  50%    { transform: translateY(-30px)  rotate(180deg); }
  62.5%  { transform: translateY(-28px)  rotate(225deg); }
  75%    { transform: translateY(-22px)  rotate(270deg); }
  87.5%  { transform: translateY(-13px)  rotate(315deg); }
  100%   { transform: translateY(0)      rotate(360deg); }
}

/* Rubber ball: squeeze together, spring out beyond the starting size, settle. */
@keyframes decor-click-squash {
  0%   { transform: scale(1, 1); }
  24%  { transform: scale(1.13, 0.85); }
  48%  { transform: scale(0.93, 1.09); }
  70%  { transform: scale(1.05, 0.97); }
  87%  { transform: scale(0.99, 1.01); }
  100% { transform: scale(1, 1); }
}

@media (prefers-reduced-motion: reduce) {
  .decor-a, .decor-b, .decor-c, .ba-hint, .ba-nudge, .hero-photo {
    animation: none !important;
  }
  /* Whoever has cancelled motion does not get the playful part either: neither
     the tilting on hover nor the movement on clicking. The script additionally
     holds itself back, this here is the safeguard in the stylesheet. */
  .decor-motif { transition: none !important; }
  .decor-tilt,
  .decor-click-swing,
  .decor-click-hop,
  .decor-click-flip,
  .decor-click-squash { animation: none !important; }
  /* Without the fade the first hero image stays put. */
  .hero-photo-base { opacity: 1; }
}

/* ---------------------------------------------------------
   Footer
   Deliberately always dark, independent of the theme.
   --------------------------------------------------------- */

.footer {
  background: #1E1B19;
  color: var(--paper);
  border-top: 1px solid rgba(244, 242, 238, 0.12);
}
.foot-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 48px;
  padding: 64px 32px 40px;
}
.foot-logo { height: 64px; display: block; margin-bottom: 20px; }
.foot-text {
  font-size: 14px;
  line-height: 1.6;
  color: var(--stone-300);
  max-width: 38ch;
  margin: 0;
}
.foot-column { display: flex; flex-direction: column; gap: 10px; }
.foot-title {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--stone-400);
  margin-bottom: 6px;
}
.foot-column span,
.foot-column a { font-size: 14px; color: var(--stone-200); text-decoration: none; }
.foot-column a:hover { color: var(--leaf); }

.foot-bottom { border-top: 1px solid rgba(244, 242, 238, 0.12); }
.foot-bottom-inner {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 32px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--stone-500);
}

/* ---------------------------------------------------------
   Legal pages
   --------------------------------------------------------- */

/* Legal texts are full of monster words like "Umsatzsteuer-Identifikations-
   nummer" or "Verbraucherschlichtungsstelle". On 320 px wide devices such a
   word fits into no line and pushes the page open: set as a heading it stuck
   out 28 px past the edge. Hyphenation takes effect because the <html> element
   carries lang="de"; `break-word` catches whatever is left over after that. */
/* Sits as its own element INSIDE `.wrap`, not on the same node: together on
   the `.wrap` the reading width of 68ch would replace its max-width and
   `margin: 0 auto` would centre the whole block — the body text would then
   stand further to the right than the heading above it. This way both stay
   left-aligned. */
.legal-text {
  max-width: 68ch;
  padding-bottom: 96px;
  hyphens: auto;
  overflow-wrap: break-word;
}
.legal-text h2 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 26px;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 44px 0 14px;
  color: var(--sfg);
}
.legal-text h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 18px;
  margin: 28px 0 10px;
  color: var(--sfg);
}
.legal-text p,
.legal-text li { font-size: 15.5px; line-height: 1.65; color: var(--smut); }
.legal-text ul { padding-left: 22px; margin: 0 0 16px; }
.legal-text li { margin-bottom: 6px; }
.legal-text a { color: var(--sfg); }
.legal-text dl { margin: 0 0 16px; }
.legal-text dt {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sfaint);
  margin-top: 12px;
}
.legal-text dd { margin: 4px 0 0; font-size: 15.5px; color: var(--smut); }

.placeholder {
  background: var(--leaf-50);
  border-left: 3px solid var(--leaf);
  padding: 2px 8px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--leaf-800);
}

/* ---------------------------------------------------------
   Cookie banner
   Built, but only visible once services actually requiring consent are
   embedded. Without tracking there is nothing to ask.
   --------------------------------------------------------- */

.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  background: var(--ink);
  color: var(--paper);
  padding: 20px 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  box-shadow: 0 -12px 40px -24px rgba(14, 14, 14, 0.6);
}
.cookie-banner[hidden] { display: none; }
.cookie-text { font-size: 14px; line-height: 1.55; max-width: 70ch; margin: 0; }
.cookie-text a { color: var(--leaf-300); }
.cookie-buttons { display: flex; gap: 10px; flex-wrap: wrap; }
.cookie-banner .btn { background: var(--paper); color: var(--ink); }
.cookie-banner .btn-ghost { border-color: var(--paper-48); color: var(--paper); padding: 9px 20px; font-size: 13.5px; }

/* ---------------------------------------------------------
   Responsive
   The values come from the design; desktop stays unchanged.
   --------------------------------------------------------- */

/* Decorations need room next to the content. If there is not enough, they
   disappear. */
@media (max-width: 1439px) {
  .decor-slot { display: none; }
}

@media (max-width: 1023px) {
  .nav-left { display: none; }
}

@media (max-width: 900px) {
  .mas { column-count: 2; }
}

@media (max-width: 760px) {
  .wrap { padding-left: 20px; padding-right: 20px; }
  .nav-back { display: none; }

  .hero { padding-top: 114px; }
  .hero h1 { font-size: clamp(38px, 11.5vw, 52px); }
  .hero-ctas { flex-direction: column; align-items: stretch; }
  .hero-ctas a { justify-content: center; text-align: center; }
  .hero-meta { margin-top: 40px; }

  .page-head { padding-top: 114px; }
  .section { padding: 64px 0; }
  .sec-grid, .contact-grid { grid-template-columns: 1fr; gap: 36px; }
  /* .field-row needs no rule here: auto-fit wraps by itself. */

  .gal-grid { grid-template-columns: 1fr; }
  .gal-tile { grid-column: auto !important; }
  .gal-tile img { height: 280px; }

  .foot-grid { grid-template-columns: 1fr; gap: 36px; }

  .lb { padding: 16px; }
  .lb-prev { left: 8px; width: 42px; height: 42px; }
  .lb-next { right: 8px; width: 42px; height: 42px; }
  .lb-close { right: 12px; top: 12px; }
  .lb-box { padding: 20px; }
  .lb-box .lb-image { max-width: 78vw; }
  .lb-cap { padding: 0 60px; }

  .cookie-banner { padding: 18px 20px; }
}

@media (max-width: 600px) {
  .mas { column-count: 1; }
}
