/* moewe.art - the visual language, after the Bauhaus: form follows
   function, three basic shapes in three primary colours, each with one
   meaning, one geometric typeface, a strict grid, lines instead of
   shadows. The pictures are the only thing that has colour in quantity.
   Rationale and rules: 03-design/moewe-art-visual-language.md

   Nothing is loaded from a foreign server; the typeface (Jost, SIL Open
   Font License) lies in fonts/. */

@font-face {
  font-family: "Jost";
  src: url("fonts/jost.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* --- Tokens: the only colours, sizes and distances there are ----------- */

:root {
  /* Paper and ink. */
  --paper: #faf8f3;
  --ink: #141414;
  --muted: #6b6862;
  --faint: #b5b1a8;
  --line: #e3dfd6;
  --surface: #efece5;
  --overlay: rgba(250, 248, 243, 0.98);
  /* The three primary colours, each with one meaning - never decoration:
     red    = ordering: cart, checkout, prices you can buy
     blue   = now: live
     yellow = once: an original, and what is still open */
  --red: #d1342b;
  --blue: #1d4e9e;
  --yellow: #f2b705;
  --on-colour: #faf8f3;
  /* The frame: every picture sits in a mat of print white, as on the
     printed piece, with a hairline around it - in the dark mode too, like
     a print on a dark wall. 03-design/moewe-art-visual-language.md,
     "Bilder im Rahmen" */
  --mat: #fff;
  /* The mat of a preview tile: a share of its edge, so the picture sits in
     the square as it would on a print - the long side close to the edge,
     the white above and below (or beside) it. */
  --mat-tile: 2.4%;
  --mat-l: clamp(0.5rem, 1.5vw, 1.1rem);

  --sans: "Jost", "Futura", "Century Gothic", "Avenir Next", system-ui, sans-serif;
  /* Type scale 1.25. */
  --t-xs: 0.75rem; --t-s: 0.875rem; --t-m: 1rem; --t-l: 1.25rem; --t-xl: 1.563rem;
  --t-2xl: 1.953rem; --t-3xl: clamp(2.2rem, 4.5vw, 3.052rem);
  /* Spacing on an 8 px base. */
  --s1: 0.5rem; --s2: 1rem; --s3: 1.5rem; --s4: 2.5rem; --s5: 4rem; --s6: 6.5rem;
  --rule: 2px;
  --gutter: clamp(1rem, 4vw, 3.5rem);
  --gap: clamp(1rem, 2.2vw, 2rem);
  --ease: cubic-bezier(0.2, 0, 0, 1);
  /* The three shapes as lines with round ends - drawn like the gull.
     Used as masks, so they take any colour of the tokens. */
  --shape-circle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='8' cy='8' r='6.4'/%3E%3C/svg%3E");
  --shape-square: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1.9' y='1.9' width='12.2' height='12.2' rx='0.6'/%3E%3C/svg%3E");
  --shape-triangle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 1.8 L14.4 13.6 L1.6 13.6 Z'/%3E%3C/svg%3E");
}
/* Dark: as the device says, unless the switch in the footer chose -
   theme.js puts data-theme on <html>. The tokens stand twice, once per
   way in; keep both blocks equal. */
:root { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #131312;
    --ink: #f1ede4;
    --muted: #a19d94;
    --faint: #5e5b55;
    --line: #2a2926;
    --surface: #1c1b19;
    --overlay: rgba(19, 19, 18, 0.98);
    --red: #e5534b;
    --blue: #6b97ea;
    --yellow: #f5c542;
    --on-colour: #131312;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --paper: #131312;
  --ink: #f1ede4;
  --muted: #a19d94;
  --faint: #5e5b55;
  --line: #2a2926;
  --surface: #1c1b19;
  --overlay: rgba(19, 19, 18, 0.98);
  --red: #e5534b;
  --blue: #6b97ea;
  --yellow: #f5c542;
  --on-colour: #131312;
}

/* --- Base -------------------------------------------------------------- */

/* The frame for small and cropped pictures: the mat around the box that
   holds the picture. A framed picture does not zoom on hover - the
   hairline turns to ink instead. */
.tile .frame, .theme .frame, .offer-item .frame, .similar-item .frame {
  position: relative; background: var(--mat); outline: 1px solid var(--line); outline-offset: -1px;
  transition: outline-color 0.2s ease;
}
/* The picture inside the square, the mat around it. Placed absolutely, not
   by height: 100% - Safari resolves that against the whole square and the
   picture runs into the mat at the bottom. */
.tile .frame img, .theme .frame img, .offer-item .frame img, .similar-item .frame img {
  position: absolute; top: var(--mat-tile); left: var(--mat-tile);
  width: calc(100% - 2 * var(--mat-tile)); height: calc(100% - 2 * var(--mat-tile)); object-fit: contain;
}
.tile:hover .frame, .theme:hover .frame, .offer-item:hover .frame, .similar-item:hover .frame,
.tile:focus-visible .frame { outline-color: var(--ink); }

* { box-sizing: border-box; }
/* "hidden" must win over any display set below - otherwise a hidden button
   such as "Mehr Bilder (0)" stays on the page. */
[hidden] { display: none !important; }
html { background: var(--paper); color: var(--ink); -webkit-text-size-adjust: 100%; }
body { margin: 0; font: 400 var(--t-m)/1.6 var(--sans); font-feature-settings: "kern"; }
a { color: inherit; }
button { font: inherit; color: inherit; border-radius: 0; }
img { display: block; max-width: 100%; }
:focus-visible { outline: var(--rule) solid var(--ink); outline-offset: 3px; }

/* A label: small, upper case, spaced - for everything that names rather
   than says. */
.section-title, .original-kind, .order-head, .badge, .menu a, .cart-button, .primary, .more-button,
.filters button, .live-updated, .bottom nav a, .section-more {
  font-size: var(--t-xs); font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
}

/* --- The shapes ---------------------------------------------------------
   One shape before a title says what kind of thing follows. Circle, blue:
   live. Square, red: prints and ordering. Triangle, yellow: an original.
   Square, ink: a neutral section. Drawn, not filled: outlines with round
   ends, like the lines of the gull. */

.section-title::before, .page h2[id]::before, .shape {
  content: ""; display: inline-block; width: 0.85em; height: 0.85em; margin-right: 0.6em;
  background: var(--ink); flex: none;
  -webkit-mask: var(--shape-square) center / contain no-repeat; mask: var(--shape-square) center / contain no-repeat;
}
#originals-title::before, .page h2#einzelstuecke::before {
  background: var(--yellow);
  -webkit-mask-image: var(--shape-triangle); mask-image: var(--shape-triangle);
}
#series-title::before, .page h2#drucke::before, .page h2#serien::before { background: var(--red); }

/* --- Header ------------------------------------------------------------ */

.top {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s3) var(--gutter) var(--s2);
  position: fixed; top: 0; left: 0; right: 0; z-index: 10; background: var(--paper);
  border-bottom: var(--rule) solid transparent;
  will-change: transform;
  transition: transform 0.3s var(--ease), border-color 0.3s ease;
}
/* The header is fixed, as in the Headroom.js playroom; the page keeps its
   height free at the top, so at the top it never lies over anything.
   app.js measures the height (it differs on a phone); the value here holds
   until then. Anchors stop below it too. */
html { scroll-padding-top: var(--head-h, 6rem); }
body { padding-top: var(--head-h, 6rem); }
/* Out of the way while scrolling down, back when scrolling up - then with
   its rule. */
.top.away { transform: translateY(-100%); }
.top.lifted { border-bottom-color: var(--ink); }
.brand {
  display: inline-flex; align-items: center; gap: 0.6rem; color: var(--ink);
  font-weight: 700; font-size: var(--t-l); letter-spacing: 0.01em; text-decoration: none;
}
/* The logo: inline, so the gull takes the colour of the text. */
.brand .mark { height: 2.75rem; width: 2.75rem; flex: none; }
/* In the footer the gull's feet, standing on the water line: the name
   stands on the same line. */
.bottom .brand { align-items: flex-end; }
.brand .mark.feet { height: 4.5rem; width: calc(4.5rem * 72 / 48); }
.menu { display: flex; align-items: center; gap: var(--s3); }
.menu a { text-decoration: none; color: var(--muted); padding: 0.3rem 0; border-bottom: var(--rule) solid transparent; }
.menu a:hover { color: var(--ink); }
/* The page one is on: an ink bar under it. */
.menu a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--ink); }
/* The cart: ordering, hence red - a square with the count. */
.menu .cart-button, .cart-button {
  display: inline-flex; align-items: center; gap: 0.5rem; margin-left: var(--s1);
  background: none; border: 0; padding: 0; cursor: pointer; color: var(--ink);
}
.cart-button span {
  display: inline-block; min-width: 1.6rem; padding: 0 0.4rem;
  background: var(--red); color: var(--on-colour);
  font-size: var(--t-xs); line-height: 1.6rem; text-align: center; letter-spacing: 0;
}

/* --- Start page -------------------------------------------------------- */

main { padding: 0 var(--gutter) var(--s5); }

.intro { max-width: 40rem; margin: var(--s5) 0; }
.intro p { margin: 0 0 var(--s2); font-size: clamp(var(--t-l), 2.2vw, var(--t-xl)); line-height: 1.35; }
.intro a { text-decoration: none; border-bottom: var(--rule) solid var(--ink); }

/* A section: its title on an ink rule, the shape before it. */
.section-title {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0 var(--s2);
  margin: 0 0 var(--s3); padding-top: var(--s1); border-top: var(--rule) solid var(--ink);
  color: var(--ink);
}
.section-title::before { margin-right: 0; }
.section-more { margin-left: auto; color: var(--muted); text-decoration: none; }
.section-more::after { content: " →"; }
.section-more:hover { color: var(--ink); }

/* Filters: square chips; the chosen ones in ink. */
.filters { display: flex; flex-wrap: wrap; gap: var(--s1); margin: 0 0 var(--s4); }
.filters button {
  background: none; border: var(--rule) solid var(--line); padding: 0.35rem 0.75rem; cursor: pointer;
  color: var(--ink); transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.filters button:hover { border-color: var(--ink); }
.filters button[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
/* The gallery's filters: one row per category, its name in front. */
#tags { flex-direction: column; gap: var(--s2); }
.filter-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1); }
.filter-label { flex: 0 0 5rem; color: var(--muted); font-size: var(--t-s); letter-spacing: 0.04em; }
@media (max-width: 30rem) { .filter-label { flex-basis: 100%; } }

.scope { margin: calc(-1 * var(--s3)) 0 var(--s3); font-size: var(--t-s); color: var(--muted); }
.scope button { background: none; border: 0; padding: 0; color: var(--ink); cursor: pointer;
  border-bottom: var(--rule) solid var(--ink); font-size: inherit; }
.status { color: var(--muted); margin: 0 0 var(--s3); }
.status:empty { display: none; }

/* Squares in rows: every picture in the overview is a white square with the
   whole picture in it - its shape shows once a format is chosen. */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(16rem, 100%), 1fr)); gap: var(--gap); }
.tile {
  display: flex; flex-direction: column; justify-content: flex-start; align-self: start; width: 100%; margin: 0; padding: 0;
  border: 0; background: none; text-align: left; cursor: zoom-in;
}
.tile .frame { display: block; aspect-ratio: 1; overflow: hidden; }
.tile img { width: 100%; height: 100%; object-fit: contain; }
.tile .caption { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; padding-top: var(--s1);
  font-size: var(--t-s); color: var(--muted); }

/* Badges say what kind of thing it is, in the colour of its meaning. */
.badge {
  display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.05rem 0.4rem;
  background: var(--ink); color: var(--paper); font-size: 0.65rem;
}
.badge.quiet { background: none; color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink); }
.badge[data-original] { background: var(--yellow); color: #141414; }
.badge[data-original]::before { content: ""; width: 0.7rem; height: 0.7rem; background: #141414;
  -webkit-mask: var(--shape-triangle) center / contain no-repeat; mask: var(--shape-triangle) center / contain no-repeat; }

.more-button {
  display: block; margin: var(--s3) auto 0; padding: 0.8rem 1.8rem; cursor: pointer;
  background: none; border: var(--rule) solid var(--ink); color: var(--ink);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.more-button:hover { background: var(--ink); color: var(--paper); }

/* --- Stage: the selection, large, one after another --------------------- */

.stage { position: relative; margin: var(--s2) var(--gutter) 0; }
.stage-slides {
  position: relative; height: min(76vh, 52rem); min-height: 22rem;
  background: var(--surface); overflow: hidden; cursor: zoom-in;
  /* Horizontal moves are a swipe, vertical ones still scroll the page. */
  touch-action: pan-y; user-select: none; -webkit-user-select: none;
}
.stage-arrow {
  position: absolute; top: 50%; z-index: 2; transform: translateY(-50%);
  width: 3rem; height: 3rem; border: 0; cursor: pointer;
  background: var(--ink); color: var(--paper); font-size: 1.5rem; line-height: 1;
  opacity: 0; transition: opacity 0.25s ease;
}
.stage-arrow.prev { left: 0; }
.stage-arrow.next { right: 0; }
.stage-slides:hover .stage-arrow, .stage-arrow:focus-visible { opacity: 1; }
/* Touch screens have no hover: there, the swipe does it. */
@media (hover: none) { .stage-arrow { display: none; } }
/* Embla: the viewport is .stage-slides, the track holds one slide per
   picture. The fade plugin sets each slide's opacity itself. */
.stage-track { display: flex; height: 100%; touch-action: pan-y pinch-zoom; cursor: pointer; }
.slide { flex: 0 0 100%; min-width: 0; height: 100%; display: flex; align-items: center; justify-content: center;
  padding: clamp(1.25rem, 4vw, 3.5rem); container-type: size; }
/* The square: the shorter side of the room the slide has - by container
   units, so no browser has to guess a percentage height. */
.slide img { width: min(100cqw, 100cqh); height: min(100cqw, 100cqh); max-width: none; object-fit: contain; padding: var(--mat-l);
  background: var(--mat); outline: 1px solid var(--line); outline-offset: -1px; }
.slide.active img { animation: drift 9s ease-out both; }
@keyframes drift { from { transform: scale(1); } to { transform: scale(1.03); } }
.stage-bar {
  display: flex; align-items: flex-end; justify-content: center; gap: var(--s2);
  padding: var(--s2) 0 var(--s1); border-bottom: var(--rule) solid var(--ink);
}
/* Where one is in the selection: short strokes with round ends, the
   current one long and dark. */
.stage-dots { display: flex; align-items: center; gap: 0.4rem; padding-bottom: 0.5rem; }
.stage-dots button {
  width: 1rem; height: 3px; padding: 0; border: 0; border-radius: 2px; cursor: pointer;
  background: var(--faint); transition: background-color 0.2s ease, width 0.3s var(--ease);
}
.stage-dots button[aria-selected="true"] { background: var(--ink); width: 2rem; }

/* --- Live: blue, the circle --------------------------------------------- */

/* The page "Live" (live/): a stage as wide as the start page's, the text
   beside it as narrow as on every page. */
.page:has(#live) { max-width: none; }
.page:has(#live) > :not(.live) { max-width: 40rem; }
.live { margin: var(--s4) 0 var(--s5); }
.live .stage, .live .stage-bar { margin: 0; }
.live-updated { color: var(--blue); font-weight: 600; letter-spacing: 0.08em; margin: var(--s2) 0 0; text-align: center; }
.live-updated:empty { display: none; }
/* The heart under the stage: given, it stays filled. */
.live-heart { display: grid; justify-items: center; gap: var(--s2); margin: var(--s2) auto 0; max-width: 32rem; }
.live-heart .heart { padding: 0.45rem 1rem; border: var(--rule) solid var(--blue); background: none; color: var(--blue); cursor: pointer;
  font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; }
.live-heart .heart:hover { background: var(--blue); color: var(--on-colour); }
.live-heart .heart[aria-pressed="true"] { background: var(--blue); color: var(--on-colour); cursor: default; }
.live-heart .heart-note { width: 100%; }
/* The sign in the header while something is live: a pulsing dot, drawn
   as a ring like the other shapes. */
.menu .corner { display: inline-flex; align-items: center; gap: var(--s3); }
.live-signal, .menu .live-signal { display: inline-flex; align-items: center; gap: 0.45rem; text-decoration: none; color: var(--blue); }
.live-signal .live-dot { width: 0.7rem; height: 0.7rem; animation: pulse 2s ease-out infinite; }
.live-signal-word { font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; }
.live-dot { width: 0.85rem; height: 0.85rem; border-radius: 50%; border: 2.4px solid var(--blue); background: none; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--blue) 55%, transparent); }
  70% { box-shadow: 0 0 0 0.6rem transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.feedback { display: grid; gap: var(--s1); margin-top: var(--s1); }
.feedback h3 { font-size: var(--t-l); font-weight: 500; margin: 0 0 0.2rem; }
.feedback textarea, .feedback input {
  width: 100%; padding: 0.65rem 0.7rem; border: var(--rule) solid var(--line); border-radius: 0;
  background: var(--paper); color: var(--ink); font: inherit; resize: vertical;
}
.feedback textarea:focus, .feedback input:focus { outline: none; border-color: var(--ink); }
.feedback .trap { position: absolute; left: -10000px; width: 1px; height: 1px; opacity: 0; }
.feedback .note { color: var(--muted); font-size: var(--t-s); margin: 0; }
/* Sending a message is not buying: ink, not red. */
.feedback .primary { background: var(--ink); color: var(--paper); }
.feedback .primary:hover { background: var(--blue); color: var(--on-colour); }

/* --- Rows of cards: originals and series (class names from the former
   theme cards) -------------------------------------------------------- */

.themes { margin: var(--s5) 0; }
.theme-row {
  /* Cards keep their size on the grid, however few there are. */
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(11rem, 15rem); justify-content: start;
  gap: var(--gap); overflow-x: auto; scroll-snap-type: x mandatory;
  padding-bottom: var(--s1); scrollbar-width: thin;
}
.theme {
  display: flex; flex-direction: column; justify-content: flex-start; padding: 0; border: 0; background: none;
  text-align: left; cursor: pointer;
  scroll-snap-align: start;
}
.theme .frame { display: block; aspect-ratio: 1; overflow: hidden; }
.theme img { width: 100%; height: 100%; object-fit: contain; }
.theme-name { display: block; margin-top: var(--s1); font-weight: 500; }
.theme-count { display: block; font-size: var(--t-s); color: var(--muted); }
.theme-count.original-price { color: var(--red); font-weight: 600; }

/* A series: a stack of its pieces - the first in front, up to two behind,
   each offset up and to the right, each in its own frame. The room for the
   offset is taken from the front piece, so the card keeps its size. */
.stack { display: grid; position: relative; padding: 14px 14px 0 0; }
.stack > .frame { grid-area: 1 / 1; }
.stack > .frame:not(:last-child) { pointer-events: none; }
.stack[data-count="3"] > .frame:nth-child(1) { transform: translate(14px, -14px); }
.stack[data-count="3"] > .frame:nth-child(2), .stack[data-count="2"] > .frame:nth-child(1) { transform: translate(7px, -7px); }
.theme:hover .stack > .frame:last-child, .offer-item:hover .stack > .frame:last-child { outline-color: var(--ink); }

/* --- Viewer ------------------------------------------------------------ */

dialog { border: 0; padding: 0; color: var(--ink); background: var(--paper); }
dialog::backdrop { background: var(--overlay); }
.close {
  position: absolute; top: var(--s2); right: var(--s3); z-index: 1;
  background: none; border: 0; cursor: pointer; color: var(--muted);
  font-size: var(--t-xs); font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
}
.close:hover { color: var(--ink); }
/* The dialog focuses its first button on opening; a ring there would look
   like an error. Keyboard users still see where they are. */
.close:focus-visible { outline: none; text-decoration: underline; text-underline-offset: 4px; }

.viewer { width: 100vw; height: 100vh; max-width: none; max-height: none; margin: 0; }
.viewer[open] { display: flex; flex-direction: column; }
.viewer-top { position: static; border-bottom: var(--rule) solid var(--ink); }
/* Right, also where the header has no brand (the viewer of the page Live). */
.viewer-top .close { position: static; margin-left: auto; }
.viewer figure {
  margin: 0; flex: 1; min-height: 0; display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(19rem, 27rem);
  grid-template-rows: 100%;
  --around: clamp(1.5rem, 4vw, 3.5rem);
  background: var(--surface);
}
/* The sheet: a white square, until a format is chosen - then the piece in
   that format, its margin to scale, the picture fitted inside. Sized to
   the room it has, by container units. */
.viewer .sheet-area { container-type: size; display: grid; place-items: center; min-height: 0;
  padding: var(--around); }
.viewer .sheet {
  --ratio: 1; --margin: 0;
  aspect-ratio: var(--ratio); width: min(100cqw, 100cqh * var(--ratio));
  padding: var(--mat-l); background: var(--mat); outline: 1px solid var(--line); outline-offset: -1px;
}
.viewer .sheet.as-format { padding: calc(min(100cqw, 100cqh * var(--ratio)) * var(--margin)); }
.viewer .sheet img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: 50% var(--y, 50%); }
.viewer figcaption { overflow-y: auto; padding: var(--s4) var(--s3) var(--s3); border-left: var(--rule) solid var(--ink);
  background: var(--paper); }
.viewer h2 { font-size: var(--t-2xl); font-weight: 600; line-height: 1.15; margin: 0 0 var(--s1); }
.picture-tags { color: var(--ink); font-size: var(--t-s); margin: 0 0 var(--s4);
  display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3); }
.picture-tags .tag-category { color: var(--muted); }
@media (max-width: 780px) {
  .viewer[open] { display: block; overflow-y: auto; }
  .viewer figure { grid-template-columns: 1fr; grid-template-rows: auto auto; }
  .viewer figure { background: none; }
  .viewer .sheet-area { height: min(70vh, 100vw); padding: var(--s3) var(--s2) var(--s2); }
  .viewer figcaption { border-left: 0; border-top: var(--rule) solid var(--ink); padding: var(--s3) var(--gutter) var(--s4); }
}

/* In the viewer a series replaces the large image with its pieces, laid
   out as printed. */
.series-sheet {
  display: flex; flex-wrap: wrap; align-content: center; justify-content: center;
  gap: clamp(1rem, 2.5vw, 2rem); padding: clamp(1.5rem, 4vw, 3.5rem); overflow-y: auto;
  background: var(--surface);
}
.series-piece { display: grid; justify-items: center; gap: var(--s1); text-decoration: none; font-size: var(--t-s); color: var(--muted); }
.series-piece span { max-width: 14rem; text-align: center; }
.series-piece .piece { transition: transform 0.3s var(--ease); }
.series-piece:hover .piece { transform: translateY(-4px); }

/* An original: the yellow triangle. */
.original-box { margin: 0 0 var(--s3); }
.original-kind {
  display: inline-flex; align-items: center; gap: 0.45rem; margin: 0 0 var(--s1); padding: 0.1rem 0.5rem;
  background: var(--yellow); color: #141414;
}
.original-kind::before { content: ""; width: 0.75rem; height: 0.75rem; background: #141414;
  -webkit-mask: var(--shape-triangle) center / contain no-repeat; mask: var(--shape-triangle) center / contain no-repeat; }
.original-technique { margin: 0 0 var(--s2); color: var(--muted); font-size: var(--t-s); }
.original-text { margin: 0 0 var(--s2); }
.original-amount { margin: 0 0 var(--s2); font-size: var(--t-xl); font-weight: 600; color: var(--red); font-variant-numeric: tabular-nums; }
.original-sold { margin: 0; color: var(--muted); }
.order-head { color: var(--ink); margin: var(--s4) 0 var(--s2); padding-top: var(--s1); border-top: var(--rule) solid var(--ink); }
.series-link { margin-top: var(--s3) !important; }
.series-link a { color: var(--ink); text-decoration: none; border-bottom: var(--rule) solid var(--red); }

/* --- Formats, preview, ordering ---------------------------------------- */

.order .note { color: var(--muted); font-size: var(--t-s); margin: var(--s1) 0 0; }
.order .note.delivery { color: var(--ink); }
.order .note.delivery::before { content: ""; display: inline-block; width: 0.7rem; height: 0.7rem;
  margin-right: 0.5rem; vertical-align: -0.05em; background: var(--ink);
  -webkit-mask: var(--shape-square) center / contain no-repeat; mask: var(--shape-square) center / contain no-repeat; }

/* The preview: each piece in its proportions, white, the margin at its real
   width, the picture fitted inside - as printed. All pieces share one
   scale, so their sizes compare. Rule: 03-design/moewe-art.md, "Einpassen,
   nicht beschneiden". */
.previews {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s2);
  padding: var(--s3); margin: 0 0 var(--s1); background: var(--surface);
}
.piece { display: flex; background: #fff; cursor: pointer; outline: 1px solid var(--line); outline-offset: 0; }
.piece.selected { outline: var(--rule) solid var(--ink); outline-offset: 3px; }
.piece .area { flex: 1; display: flex; align-items: center; justify-content: center; min-width: 0; min-height: 0; }
/* Fitted, and placed as the format says: in the middle, or a little higher
   (--y, the share of the white above it). */
.piece img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: 50% var(--y, 50%); }
.preview-label { font-size: var(--t-s); color: var(--muted); margin: 0 0 var(--s3); }
/* No delivery time before a format is chosen - and no shape before nothing. */
.note.delivery:empty { display: none; }

/* Similar pictures: small squares in three columns, under the order. */
.similar { margin: var(--s4) 0 0; padding-top: var(--s1); border-top: var(--rule) solid var(--ink); }
.similar h3 { font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; margin: 0 0 var(--s2); }
.similar-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s1); }
.similar-item { display: block; border: 0; }
.similar-item .frame { display: block; aspect-ratio: 1; overflow: hidden; }

/* Upright or across: two buttons like the filters, under the preview. */
.orientation-choice { margin: var(--s3) 0; }
.orientation-label { margin: 0 0 var(--s1); font-size: var(--t-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.filters.orientation { margin: 0; }
.filters.orientation button:disabled { opacity: 0.35; cursor: default; }
.orientation-note { margin: var(--s1) 0 0; font-size: var(--t-s); }

.formats { display: grid; margin: 0 0 var(--s3); border-top: var(--rule) solid var(--ink); }
.format {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--s2);
  padding: 0.8rem 0; border-bottom: 1px solid var(--line); cursor: pointer;
}
.format input { accent-color: var(--ink); margin: 0; }
.format small { display: block; color: var(--muted); font-size: var(--t-s); }
.format .price { white-space: nowrap; font-weight: 600; font-variant-numeric: tabular-nums; }

.add { display: flex; gap: var(--s1); align-items: stretch; }
.add input, .cart-line input {
  width: 4.5rem; padding: 0.6rem 0.5rem; border: var(--rule) solid var(--ink); border-radius: 0;
  background: var(--paper); color: var(--ink); font: inherit; text-align: center;
}
/* The one action that buys: red, square, in capitals. */
.primary {
  flex: 1; padding: 0.9rem 1.5rem; border: 0; cursor: pointer;
  background: var(--red); color: var(--on-colour);
  transition: background-color 0.2s ease, transform 0.15s ease;
}
.primary:hover { background: var(--ink); color: var(--paper); }
.primary:active { transform: translateY(1px); }
.primary:disabled { background: var(--faint); color: var(--paper); cursor: default; }

/* --- Dialogs: cart, notices -------------------------------------------- */

.text-dialog {
  width: min(92vw, 34rem); max-height: 90vh; padding: var(--s4) var(--s3) var(--s3);
  border: var(--rule) solid var(--ink);
}
.text-dialog h2 { font-size: var(--t-xl); font-weight: 600; margin: 0 0 var(--s2); }
.cart { width: min(94vw, 38rem); border-top: 0.5rem solid var(--red); }
.cart-line {
  display: grid; grid-template-columns: 3.5rem 1fr auto auto; gap: var(--s2); align-items: center;
  padding: var(--s1) 0; border-bottom: 1px solid var(--line);
}
.cart-line img { width: 3.5rem; height: 3.5rem; object-fit: contain; padding: 3px; background: var(--mat);
  outline: 1px solid var(--line); outline-offset: -1px; }
.cart-line small { color: var(--muted); }
.cart-line .remove { background: none; border: 0; color: var(--muted); cursor: pointer; font-size: var(--t-l); }
.cart-line .remove:hover { color: var(--red); }
.cart-one { min-width: 4.5rem; text-align: center; color: var(--muted); }
.cart-sum { width: 100%; margin: var(--s3) 0 var(--s1); border-collapse: collapse; font-variant-numeric: tabular-nums; }
.cart-sum td { padding: 0.2rem 0; }
.cart-sum td:last-child { text-align: right; }
.cart-sum tr:last-child td { font-weight: 700; font-size: var(--t-l); padding-top: var(--s1); border-top: var(--rule) solid var(--ink); }
.cart-note { color: var(--muted); font-size: var(--t-s); }
.consent { display: flex; gap: var(--s1); align-items: flex-start; font-size: var(--t-s); margin: var(--s2) 0 var(--s3); }
.consent input { accent-color: var(--ink); margin-top: 0.3rem; }
.cart .primary { width: 100%; }
/* The coupon: a label, a field, a button - one row on the rule. */
.cart .coupon { display: flex; align-items: center; gap: var(--s1); margin: var(--s2) 0 0; }
.cart .coupon label { font-size: var(--t-s); color: var(--muted); }
.cart .coupon input { flex: 1; min-width: 0; font: inherit; text-transform: uppercase; letter-spacing: 0.05em;
  padding: 0.4rem 0.55rem; border: var(--rule) solid var(--line); background: var(--paper); color: var(--ink); border-radius: 0; }
.cart .coupon input:focus { outline: none; border-color: var(--ink); }
.cart .coupon button { padding: 0.45rem 0.8rem; border: var(--rule) solid var(--ink); background: none; cursor: pointer;
  font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; }
.cart .coupon button:hover { background: var(--ink); color: var(--paper); }
.cart .coupon-note { font-size: var(--t-s); margin: var(--s1) 0 0; }
.cart .coupon-note.bad { color: var(--red); }

/* --- Card view (?id=) -------------------------------------------------- */

.card-view { max-width: 40rem; margin: var(--s5) 0; }
.card-view img { width: 100%; height: auto; aspect-ratio: 1; object-fit: contain; padding: var(--mat-l); background: var(--mat); outline: 1px solid var(--line); outline-offset: -1px; }
.card-view h1 { font-size: var(--t-2xl); font-weight: 600; margin: var(--s3) 0 var(--s1); }
.card-view p { margin: 0.2rem 0; color: var(--muted); }
.card-view .more { margin-top: var(--s3); }
.card-view .more a { color: var(--ink); text-decoration: none; border-bottom: var(--rule) solid var(--ink); }

/* --- Content pages ----------------------------------------------------- */

.page { max-width: 40rem; margin: var(--s5) 0 var(--s4); }
.page h1 { font-size: var(--t-3xl); font-weight: 700; line-height: 1.05; letter-spacing: -0.01em;
  margin: 0 0 var(--s4); padding-bottom: var(--s2); border-bottom: var(--rule) solid var(--ink); }
.page h2 { display: flex; align-items: center; font-size: var(--t-l); font-weight: 600; margin: var(--s4) 0 var(--s1); }
.page h3 { font-size: var(--t-m); font-weight: 600; margin: var(--s3) 0 0.3rem; }
.page ul, .page ol { padding-left: 1.2rem; }
.page li { margin: 0.3rem 0; }
/* Bullets: the neutral square, drawn. */
.page ul { list-style: none; padding-left: 0; }
.page ul li { position: relative; padding-left: 1.4em; }
.page ul li::before { content: ""; position: absolute; left: 0.1em; top: 0.55em; width: 0.6em; height: 0.6em;
  background: var(--ink); -webkit-mask: var(--shape-square) center / contain no-repeat; mask: var(--shape-square) center / contain no-repeat; }
.page table { width: 100%; border-collapse: collapse; margin: var(--s1) 0 var(--s3); font-size: var(--t-s); font-variant-numeric: tabular-nums; }
.page th { text-align: left; font-weight: 600; border-bottom: var(--rule) solid var(--ink); padding: 0.4rem 0.75rem 0.4rem 0; }
.page td { padding: 0.55rem 0.75rem 0.55rem 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.page a { text-decoration: none; border-bottom: var(--rule) solid var(--faint); }
.page a:hover { border-bottom-color: var(--ink); }
/* The eye in detail, on "Über" and on the page that does not exist. */
.page-art { margin: 0 0 var(--s4); color: var(--ink); }
.page-art .mark.detail { display: block; width: 100%; max-width: 30rem; height: auto; aspect-ratio: 22 / 18; }
/* A gap only the operator can fill: yellow - open, once. */
.open { background: var(--yellow); color: #141414; padding: 0 0.3rem; font-size: 0.9em; font-style: normal; }

/* The page "Angebot": wider, in sections with jump links. */
.page:has(.offer-grid) { max-width: 64rem; }
.page .subnav { display: flex; flex-wrap: wrap; gap: var(--s1); margin: 0 0 var(--s4); }
.page .subnav a { border: var(--rule) solid var(--ink); padding: 0.35rem 0.75rem; font-size: var(--t-xs);
  font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase; }
.page .subnav a:hover { background: var(--ink); color: var(--paper); }
.page .offer-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: var(--gap);
  margin: var(--s2) 0 var(--s1); }
.page .offer-item { display: block; border: 0; text-decoration: none; }
.offer-item .frame { display: block; aspect-ratio: 1; overflow: hidden; }
.offer-item img { width: 100%; height: 100%; object-fit: contain; }
.offer-name { display: block; margin-top: var(--s1); font-weight: 500; }
.offer-line { display: block; font-size: var(--t-s); color: var(--muted); }

/* The account: a column of sections on the rule, like the content pages;
   the order cards framed by lines, not boxes. */
.page:has(.account) { max-width: 52rem; }
.account section { margin: var(--s4) 0; }
.account-signin { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); margin: var(--s3) 0 var(--s1); }
.account-signin label { flex-basis: 100%; font-size: var(--t-s); color: var(--muted); }
.account input[type="email"], .account input[type="text"] { flex: 1; min-width: 12rem; font: inherit; padding: 0.55rem 0.7rem;
  border: var(--rule) solid var(--line); background: var(--paper); color: var(--ink); border-radius: 0; }
.account input:focus { outline: none; border-color: var(--ink); }
.account-signin .primary { width: auto; }
.account-note { font-size: var(--t-s); min-height: 1.5em; }
.account-note.bad, .account-error { color: var(--red); }
.account-small { font-size: var(--t-s); }
.account-name { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s1); }
.account-name label { font-size: var(--t-s); color: var(--muted); }
.account button:not(.primary) { padding: 0.45rem 0.8rem; border: var(--rule) solid var(--ink); background: none; cursor: pointer;
  font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; }
.account button:not(.primary):hover { background: var(--ink); color: var(--paper); }
.account button.danger { border-color: var(--red); color: var(--red); }
.account button.danger:hover { background: var(--red); color: var(--on-colour); }
.account-order { border-top: var(--rule) solid var(--ink); padding: var(--s2) 0; }
.account-order header { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3); align-items: baseline; }
.account-order ul { margin: var(--s1) 0; }
.account-status { font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; }
.account-status.s-storniert { color: var(--red); }
.account-actions { display: flex; gap: var(--s2); flex-wrap: wrap; }
/* The heart in the viewer, and the filter beside the tags. */
.viewer .fav { margin: 0 0 var(--s1); padding: 0.3rem 0.7rem; border: var(--rule) solid var(--ink); background: none; cursor: pointer;
  font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; }
.viewer .fav[aria-pressed="true"] { background: var(--ink); color: var(--paper); }
/* "Konto" in the header: an entry like the others, beside the cart. */
.menu .account-link { margin-left: var(--s1); }

/* The page "Netz": tags as drawn circles, pictures in square frames, a
   thin line for each picture-tag pair. Only the pictures have colour. */
.page:has(.network-list) { max-width: none; }
.page:has(.network-list) > :not(.network):not(.network-list) { max-width: 40rem; }
.network { margin: var(--s3) 0 var(--s4); }
.network-filter { margin-bottom: var(--s2); }
.network-canvas { overflow-x: auto; border-top: var(--rule) solid var(--ink); border-bottom: var(--rule) solid var(--ink); }
.network-drawing { display: block; min-width: 100%; }
.network-drawing a { border: 0; }
.net-edges line { stroke: var(--faint); stroke-width: 1; }
.net-edges line.on { stroke: var(--ink); stroke-width: 1.5; }
.net-picture rect { fill: var(--mat); stroke: var(--line); stroke-width: 1; }
.net-picture.on rect, .net-picture:hover rect { stroke: var(--ink); }
.net-tag circle { fill: var(--paper); stroke: var(--ink); stroke-width: 2; }
.net-tag text { fill: var(--ink); font: 500 13px var(--sans); }
.net-tag .net-count { fill: var(--muted); font-size: 11px; }
.net-tag.on circle { fill: var(--ink); }
.net-tag.on .net-count { fill: var(--paper); }
.net-categories text { fill: var(--muted); font: 600 12px var(--sans); letter-spacing: 0.12em; text-transform: uppercase; }
.net-picture, .net-tag, .net-edges line { transition: opacity 0.2s var(--ease); }
.focused .net-picture:not(.on), .focused .net-tag:not(.on) { opacity: 0.2; }
.focused .net-edges line:not(.on) { opacity: 0.12; }
.network-drawing a:focus { outline: none; }
.net-tag:focus-visible circle, .net-picture:focus-visible rect { stroke-width: 3.5; }
.network-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 0 var(--gap); }
.page .network-group h2 { font-size: var(--t-m); margin-top: var(--s3); }
.network-count { color: var(--muted); font-size: var(--t-s); }
@media (prefers-reduced-motion: reduce) { .net-picture, .net-tag, .net-edges line { transition: none; } }

/* --- Footer: an ink block that closes every page ------------------------ */

.bottom { margin-top: var(--s5); padding: var(--s4) var(--gutter); background: var(--ink); color: var(--paper); }
.bottom nav { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s4); }
.bottom a { text-decoration: none; color: var(--paper); opacity: 0.75; }
.bottom a:hover, .bottom a[aria-current="page"] { opacity: 1; }
.bottom p { margin: var(--s4) 0 0; }
/* The footprint beside the feet: small, a little turned, quiet until one
   finds it. The drawing's fine lines are made thicker for its small size. */
.bottom .feet { display: flex; align-items: flex-end; gap: var(--s3); }
.bottom .track-link { display: inline-block; padding: 0.6rem; margin: -0.6rem; opacity: 0.45; transform: rotate(-14deg) translateY(-2px); transition: opacity 0.3s ease, transform 0.3s var(--ease); }
.bottom .track-link:hover, .bottom .track-link:focus-visible, .bottom .track-link[aria-current="page"] { opacity: 1; transform: rotate(-14deg) translateY(-4px); }
.bottom .track { display: block; width: 1.6rem; height: 1.6rem; color: var(--paper); }
.bottom .track path { stroke-width: 1.1; }
/* On the ink block the gull turns to paper; sun and horizon stay. */
.bottom .brand { color: var(--paper); opacity: 1; }
/* The switch light / dark / auto: three words, the chosen one underlined
   like the current page in the menu. */
.theme-switch { display: flex; align-items: baseline; gap: var(--s2); margin-top: var(--s3);
  font-size: var(--t-s); }
.theme-switch > span { opacity: 0.75; }
.theme-switch button { background: none; border: 0; padding: 0.2rem 0; cursor: pointer; color: var(--paper);
  opacity: 0.75; border-bottom: var(--rule) solid transparent; }
.theme-switch button:hover { opacity: 1; }
.theme-switch button[aria-pressed="true"] { opacity: 1; border-bottom-color: var(--paper); }
.theme-switch button:focus-visible { outline: var(--rule) solid var(--paper); outline-offset: 3px; }

/* --- Narrow screens ----------------------------------------------------- */

@media (max-width: 600px) {
  .top { flex-direction: column; align-items: flex-start; gap: var(--s1); padding-top: var(--s2); }
  .viewer-top { flex-direction: row; align-items: center; }
  /* One line, even on a narrow phone: it scrolls sideways rather than wrap. */
  .menu { gap: var(--s2); max-width: 100%; overflow-x: auto; white-space: nowrap; scrollbar-width: none; }
  /* The cart beside the logo, top right - in the row of the menu it would
     be pushed off the edge. */
  .menu .corner { position: absolute; top: var(--s2); right: var(--gutter); }
  .menu .cart-button { margin: 0; }
  .stage { margin: var(--s1) 0 0; }
  .stage-slides { height: 62vh; }
  /* The picture runs to the edge; its rule keeps the gutter, like every other. */
  .stage-bar { margin: 0 var(--gutter); }
  .theme-row { grid-auto-columns: 62%; }
  .section-more { margin-left: 0; }
}

/* --- Motion: short, straight, geometric - and off for whoever asks the
   system to reduce it. Tiles rise into place as they scroll in and show
   their picture once loaded; the viewer slides in; the chosen format
   lifts; the cart count gives a short nudge. ---------------------------- */

@keyframes rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes slide { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes nudge { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.3); } }

.intro { animation: rise 0.7s var(--ease) both; }
.filters { animation: fade 0.7s 0.15s both; }

.tile { opacity: 0; transform: translateY(18px); transition: opacity 0.6s ease, transform 0.6s var(--ease); }
.tile.visible { opacity: 1; transform: none; }
.tile img { opacity: 0; transition: opacity 0.5s ease, transform 0.9s var(--ease); }
.tile img.loaded { opacity: 1; }
.tile .caption { transition: color 0.3s ease; }
.tile:hover .caption { color: var(--ink); }

dialog[open] { animation: fade 0.25s ease both; }
dialog[open]::backdrop { animation: fade 0.25s ease both; }
.viewer[open] .sheet { animation: fade 0.5s ease both; }
.viewer[open] figcaption { animation: slide 0.5s 0.05s var(--ease) both; }
.text-dialog[open] { animation: rise 0.3s var(--ease) both; }

.piece { transition: transform 0.25s var(--ease), outline-color 0.2s ease; }
.piece.selected { transform: translateY(-4px); }
.format { transition: background-color 0.15s ease; }
.format:hover { background: var(--surface); }
.cart-button span.nudge { animation: nudge 0.4s ease; }
.cart-line { animation: rise 0.3s ease both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .tile, .tile img { opacity: 1; transform: none; }
}

/* Read, not seen: the start page's heading. */
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* Secondary text on the site's pages - the account, the empty live page. */
.muted { color: var(--muted); }
