/* ---------- Alte Haas Grotesk — regular only, no bold cut ---------- */
@font-face {
  font-family: "Alte Haas Grotesk";
  src: url("fonts/AlteHaasGroteskRegular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #ffffff;
  --ink: #000000;
  --rule: 1.5px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

.filter-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

html { height: 100%; }

body {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font-family: "Alte Haas Grotesk", sans-serif;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
}

/* the regular cut is the only weight — never let the browser fake a bold one */
h1, h2, h3, h4, strong, b, th { font-weight: 400; }

/* index only: the grid fills the screen exactly */
body.fullscreen { height: 100vh; height: 100svh; overflow: hidden; }

a { color: var(--ink); }

/* ---------- Header ---------- */
.site-header {
  flex: none;
  position: relative;
  z-index: 20;
  /* equal outer columns keep the nav on the true centre line of the page,
     no matter how wide the wordmark or the mark are */
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(1rem, 4vw, 3rem);
  padding: clamp(0.75rem, 1.6vw, 1.25rem) clamp(0.9rem, 2.2vw, 1.75rem);
  background: var(--bg);
}
/* drawn rather than bordered so it carries the same ink bleed as the grid */
.site-header::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--rule);
  background: var(--ink);
  filter: url(#ink-bleed);
}

.logo-type {
  display: flex;
  flex-direction: column;
  text-align: left;
  text-decoration: none;
  text-transform: uppercase;
  font-size: clamp(1.05rem, 2.1vw, 1.6rem);
  line-height: 0.9;
  letter-spacing: -0.015em;
  justify-self: start;
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  font-size: clamp(0.72rem, 1.05vw, 0.85rem);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.site-nav a { text-decoration: none; }
.site-nav a:hover,
.site-nav a[aria-current="page"] { text-decoration: underline; }

.header-right {
  display: flex;
  align-items: center;
  gap: clamp(0.7rem, 1.8vw, 1.3rem);
  justify-self: end;
}

/* The icons are sized in em against the navigation's type size rather than in
   pixels, so they keep the same presence as the lettering at every width. */
.cart-link {
  display: flex;
  align-items: center;
  gap: 0.4em;
  color: var(--ink);
  text-decoration: none;
  font-size: clamp(0.72rem, 1.05vw, 0.85rem);
  letter-spacing: 0.08em;
}
.icon-cart { width: 2.2em; height: auto; display: block; }
.cart-count { font-size: 0.9em; min-width: 1.4em; }

.logo-mark { width: clamp(46px, 5.5vw, 74px); height: auto; display: block; }

/* ---------- Product grid (index) ---------- */
.grid {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  display: grid;
  /* four products: two by two fills the screen exactly, where three per row
     would leave a hole in the second row */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  overflow: hidden;
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: transparent;
  text-decoration: none;
}
a.tile, .card { cursor: crosshair; }

.tile-art {
  flex: 1;
  min-height: 0;
  width: 100%;
  display: block;
  object-fit: contain;
  padding: clamp(0.75rem, 2vw, 1.75rem);
}

.tile-bar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem clamp(0.6rem, 1.4vw, 1rem);
  font-size: clamp(0.72rem, 1.15vw, 0.9rem);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.tile--empty { color: rgba(0, 0, 0, 0.45); cursor: default; }

/* ---------- Grid rules, drawn as one filtered layer ---------- */
.rules {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}
/* Der Siebdruck-Filter sitzt auf jeder Linie einzeln, nicht auf der ganzen
   Ebene. Auf dem Handy ist die Ebene so hoch wie alle Kacheln zusammen, und
   Safari verwirft einen SVG-Filter über einer bestimmten Fläche — samt dem
   Element darunter. Die Linien waren dort deshalb unsichtbar. Eine einzelne
   Linie ist nur 1,5 px hoch und bleibt weit unter der Grenze. */
.rules i {
  position: absolute;
  display: block;
  background: var(--ink);
  filter: url(#ink-bleed); /* screen-print ink spread */
}
.rule-v { top: 0; bottom: 0; width: var(--rule); transform: translateX(-50%); }
.rule-h { left: 0; right: 0; height: var(--rule); transform: translateY(-50%); }

/* ---------- Product page: object left, colours right ---------- */
.product {
  flex: 1;
  display: grid;
  /* minmax(0, …) keeps the split fixed — wide content in the panel must not
     squeeze the product view */
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  min-height: 0;
}

.product-view {
  position: relative;
  display: flex;
  min-height: clamp(320px, 56vh, 720px);
  border-right: var(--rule) solid var(--ink);
}
.product-view > canvas,
.product-view > video,
.product-view > img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  padding: clamp(1rem, 3vw, 3rem);
}

/* Colour variants stack on top of each other; only the active one is painted.
   They stay in the layer tree so a switch never re-runs layout.

   The swap is a short cross-fade rather than a cut. The clips are frame-matched
   and both keep running through it, so it reads as the object changing colour;
   switching outright felt like a jolt. The duration is mirrored by FADE_MS in
   product-video.js.

   Hidden with opacity, deliberately NOT with `visibility`: WebKit refuses to
   play a video it considers invisible, and the incoming clip has to be running
   before it is faded in. With `visibility: hidden` it only started once it was
   already on screen, which is exactly the stutter this is meant to avoid. */
.product-view[data-video-stack] > video {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms linear;
}
.product-view[data-video-stack] > video.is-active { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .product-view[data-video-stack] > video { transition: none; }
}

/* Ausverkauft: die Farbe bleibt wählbar und ansehbar, nur bestellen lässt sie
   sich nicht. Ein Strich durch die Scheibe sagt das, ohne sie zu verstecken.

   Bezugsrahmen ist die Scheibe selbst — nicht der ganze Knopf mit
   Beschriftung, sonst sitzt der Strich zwischen Scheibe und Text. Aufgehellt
   wird über einen Schleier statt über die Deckkraft der Scheibe, die sonst
   auch den Strich blass gemacht hätte. */
.swatch.is-soldout .swatch-chip { position: relative; }
.swatch.is-soldout .swatch-chip::before,
.swatch.is-soldout .swatch-chip::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
}
.swatch.is-soldout .swatch-chip::before { background: rgba(255, 255, 255, 0.6); }
.swatch.is-soldout .swatch-chip::after {
  background: linear-gradient(
    to bottom right,
    transparent calc(50% - 0.75px),
    var(--ink) calc(50% - 0.75px),
    var(--ink) calc(50% + 0.75px),
    transparent calc(50% + 0.75px)
  );
}

.colour-stock,
.colour-loading {
  margin-left: 0.5em;
  opacity: 0.45;
  font-size: 0.85em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.product-panel {
  display: flex;
  flex-direction: column;
  gap: clamp(1.25rem, 3vw, 2rem);
  padding: clamp(1.25rem, 3vw, 2.5rem);
}

.product-title {
  font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  line-height: 1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}
.product-price { font-size: clamp(1.1rem, 2vw, 1.4rem); }
.product-text { font-size: 0.92rem; line-height: 1.5; max-width: 46ch; }

.specs {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.45rem 1.25rem;
  max-width: 52ch;
  padding-top: 0.9rem;
  font-size: 0.85rem;
  line-height: 1.45;
}
.specs dt {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding-top: 0.1rem;
}
.specs dd { margin: 0; }

.field-label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 0.6rem;
}

/* Colour chart: each option is a chip with its name printed underneath, like
   a sample card. The chosen one gets an inverted label and an offset frame. */
.field-label [data-colour-name] {
  margin-left: 0.75em;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.85rem;
}

/* sized so all seven vase colours fit one row and the buy button stays in view */
.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(52px, 1fr));
  gap: 0.9rem 0.5rem;
  max-width: 520px;
}

.swatch {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* A pressed disc seen from below: colour runs around the centre along the
   spiral of the print path, with the tool-path rings on top. */
.swatch-chip {
  display: block;
  aspect-ratio: 1;
  border: 0;
  border-radius: 50%;
  outline: var(--rule) solid transparent;
  outline-offset: 4px;
  background-image:
    repeating-radial-gradient(
      circle at 50% 50%,
      rgba(0, 0, 0, 0.14) 0 1px,
      rgba(255, 255, 255, 0.10) 1px 3px
    ),
    radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0.42), rgba(0, 0, 0, 0) 58%),
    var(--sw);
}

.swatch-label {
  align-self: flex-start;
  padding: 0.12rem 0.25rem;
  margin-left: -0.25rem;
  font-size: 0.62rem;
  line-height: 1.25;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* hover changes the cursor only — no frame around the colour */
.swatch[aria-pressed="true"] .swatch-chip { outline-color: var(--ink); }
.swatch[aria-pressed="true"] .swatch-label { background: var(--ink); color: var(--bg); }
.swatch:focus-visible { outline: var(--rule) dashed var(--ink); outline-offset: 6px; }

/* ---------- GGGRID Konfigurator ---------- */

/* Die Bühne trägt keinen Innenabstand wie die Produktansichten: das Raster
   soll die Fläche ausnutzen, seine eigenen Ränder sind der Rahmen. */
.gg-stage {
  padding: clamp(1rem, 2.5vw, 2.5rem);
  touch-action: none; /* Ziehen darf die Seite nicht mitscrollen */
  cursor: crosshair;
}
.gg-svg { width: 100%; height: 100%; display: block; }
.gg-glyph { cursor: grab; }
.gg-selection {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.2;
  stroke-dasharray: 4 3;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.gg-panel { gap: 1.4rem; overflow-y: auto; }
.gg-block { display: flex; flex-direction: column; }
.gg-sub { margin-top: 0.9rem; }

.gg-size { display: flex; flex-direction: column; gap: 0.5rem; }
.gg-stepper {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: center;
  gap: 0.5rem;
}
.gg-stepper-name {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.gg-stepper-value {
  min-width: 8ch;
  text-align: center;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}
.gg-stepper button {
  width: 2rem;
  height: 2rem;
  border: var(--rule) solid var(--ink);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  line-height: 1;
  cursor: pointer;
}
.gg-stepper button:disabled { opacity: 0.3; cursor: default; }

.gg-letters {
  display: grid;
  grid-template-columns: repeat(13, minmax(0, 1fr));
  gap: var(--rule);
  max-width: 420px;
}
.gg-letter {
  aspect-ratio: 1;
  border: var(--rule) solid var(--ink);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 0.72rem;
  padding: 0;
  cursor: pointer;
}
.gg-letter[aria-pressed="true"] { background: var(--ink); color: var(--bg); }

.gg-variants { display: flex; gap: 0.5rem; }
.gg-variant {
  width: 2.4rem;
  height: 2rem;
  border: var(--rule) solid var(--ink);
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
}
.gg-variant[aria-pressed="true"] { background: var(--ink); color: var(--bg); }

.gg-colours { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.gg-colour {
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: var(--rule) solid var(--ink);
  background: var(--c);
  cursor: pointer;
}
.gg-colour[aria-pressed="true"] { outline: var(--rule) solid var(--ink); outline-offset: 3px; }

.gg-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.btn--ghost {
  background: var(--bg);
  color: var(--ink);
  border: var(--rule) solid var(--ink);
}
.btn--ghost:disabled { opacity: 0.35; cursor: default; }

.gg-summary {
  font: inherit;
  font-size: 0.74rem;
  line-height: 1.5;
  white-space: pre-wrap;
  max-height: 11rem;
  overflow-y: auto;
  padding: 0.7rem 0.8rem;
  margin-bottom: 0.8rem;
  border: var(--rule) solid var(--ink);
}

@media (max-width: 760px) {
  .gg-stage { min-height: 52svh; }
  .gg-letters { grid-template-columns: repeat(9, minmax(0, 1fr)); max-width: none; }
  .gg-panel { overflow-y: visible; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font: inherit;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-decoration: none;
  color: var(--bg);
  background: var(--ink);
  border: var(--rule) solid var(--ink);
  padding: 0.85rem 1.6rem;
  cursor: pointer;
  align-self: flex-start;
}
.btn:hover { color: var(--ink); background: var(--bg); }
.btn--ghost { color: var(--ink); background: var(--bg); }
.btn--ghost:hover { color: var(--bg); background: var(--ink); }
.btn[disabled] { opacity: 0.35; cursor: not-allowed; }

/* ---------- Text pages ---------- */
.page {
  flex: 1;
  padding: clamp(1.5rem, 4vw, 3.5rem) clamp(1rem, 4vw, 3.5rem);
  max-width: 860px;
}
.page h1 {
  font-size: clamp(1.8rem, 4vw, 3rem);
  line-height: 1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
}
.page h2 {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin: 2rem 0 0.5rem;
}
.page p, .page li { font-size: 0.95rem; line-height: 1.6; max-width: 62ch; }
.page .lead {
  font-size: clamp(1.15rem, 2.2vw, 1.5rem);
  line-height: 1.3;
  letter-spacing: -0.01em;
  max-width: 34ch;
  margin-bottom: 1.25rem;
}
.page p + p { margin-top: 0.9rem; }
.page ul { margin-top: 0.5rem; padding-left: 1.1rem; }

/* ---------- Cart ---------- */
.cart-line {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: clamp(0.75rem, 2vw, 1.5rem);
  align-items: center;
  padding: 1rem 0;
  border-bottom: var(--rule) solid var(--ink);
}
.cart-line:first-of-type { border-top: var(--rule) solid var(--ink); }
.cart-item-name { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.03em; }
.cart-item-colour { font-size: 0.82rem; opacity: 0.65; }

.qty { display: flex; align-items: center; border: var(--rule) solid var(--ink); }
.qty button {
  font: inherit;
  width: 2rem;
  height: 2rem;
  background: var(--bg);
  border: 0;
  cursor: pointer;
}
.qty button:hover { background: var(--ink); color: var(--bg); }
.qty span { min-width: 2rem; text-align: center; font-size: 0.9rem; }

.link-remove {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  background: none;
  border: 0;
  font-family: inherit;
  cursor: pointer;
  text-decoration: underline;
}

.cart-sum {
  display: flex;
  justify-content: space-between;
  padding: 0.5rem 0;
  font-size: 0.95rem;
}
.cart-total {
  display: flex;
  justify-content: space-between;
  padding: 0.9rem 0;
  margin-top: 0.25rem;
  border-top: var(--rule) solid var(--ink);
  font-size: 1.15rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.6rem;
  align-items: start;
  font-size: 0.82rem;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.45;
}
.check input { margin-top: 0.15rem; }

.checkout { margin-top: 1.5rem; display: grid; gap: 0.9rem; max-width: 520px; }
.checkout label { display: grid; gap: 0.35rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; }
.checkout input, .checkout textarea {
  font: inherit;
  font-size: 0.95rem;
  padding: 0.6rem 0.7rem;
  border: var(--rule) solid var(--ink);
  background: var(--bg);
  color: var(--ink);
  border-radius: 0;
}
.checkout .row { display: grid; grid-template-columns: 1fr 2fr; gap: 0.9rem; }
.note { font-size: 0.8rem; line-height: 1.5; opacity: 0.7; max-width: 52ch; }

/* Bestandswarnung an einer Warenkorbzeile */
.cart-warn {
  grid-column: 1 / -1;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.3rem 0.45rem;
  background: var(--ink);
  color: var(--bg);
  justify-self: start;
}

/* ---------- Footer ---------- */
.site-footer {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  padding: 1rem clamp(0.9rem, 2.2vw, 1.75rem);
  border-top: var(--rule) solid var(--ink);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.site-footer a { text-decoration: none; }
.site-footer a:hover { text-decoration: underline; }
.site-footer .icon-link { display: flex; align-items: center; }
.site-footer .icon-link svg { width: 1.55em; height: 1.55em; display: block; }

/* ---------- Mobile ---------- */
@media (max-width: 760px) {
  body.fullscreen { height: auto; min-height: 100svh; overflow: visible; }
  .grid { grid-template-columns: minmax(0, 1fr); grid-auto-rows: minmax(72svh, auto); overflow: visible; }
  /* one line, as on desktop: the nav stays on the page's centre line next to
     the wordmark instead of dropping into a row of its own. The sizes below
     are what keeps that fitting down to roughly 320px. */
  .site-header { column-gap: 0.7rem; }
  .site-nav { gap: 0.7rem; flex-wrap: nowrap; }
  .header-right { gap: 0.55rem; }
  /* the mark carries the same weight as the three-line wordmark beside it */
  .logo-mark { width: clamp(46px, 13.5vw, 58px); }

  /* Four to a row, so all eight colours sit together and can be compared at a
     glance instead of being scrolled past one row at a time. */
  .swatches {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.5rem;
    max-width: 300px;
  }
  .swatch { position: relative; gap: 0; }
  .swatch-chip { outline-offset: 3px; }

  /* No caption under the discs — eight of them made the block noisy, and the
     selected colour is spelled out next to "Farbe" anyway. The text stays in
     the document so the buttons keep their name for screen readers. */
  .swatch-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* room for the home indicator, plus air under the last line of links */
  .site-footer {
    gap: 0.5rem 1.1rem;
    padding-top: 1.1rem;
    padding-bottom: calc(1.9rem + env(safe-area-inset-bottom, 0px));
  }

  .product { grid-template-columns: minmax(0, 1fr); }
  /* a shorter object panel brings the colour chart up into the same screen */
  .product-view {
    border-right: 0;
    border-bottom: var(--rule) solid var(--ink);
    min-height: 42svh;
  }
  .cart-line { grid-template-columns: 1fr auto; row-gap: 0.5rem; }
  .checkout .row { grid-template-columns: 1fr; }
}

/* On the narrowest phones the right-hand side outgrew its column and pushed
   the navigation off the centre line. Give back the space the empty cart
   counter was reserving and trim the mark a little. */
@media (max-width: 360px) {
  .cart-count { min-width: 0; }
  .logo-mark { width: 42px; }
}
