/* ==========================================================================
   Woonklasse design system — THE swappable stylesheet.
   Every token below is copied from WOONKLASSE-DESIGN.md
   (/Users/sander/dev/website-tinder/rebuilds/woonklasse-restyle/WOONKLASSE-DESIGN.md),
   which was extracted from the real Woonklasse theme source.
   Re-point this one file at the final design system and the configurator follows.
   ========================================================================== */
/* Anton (latin), self-hosted from /wk/ — no external font requests (SEO audit 2026-07). */
@font-face{font-family:'Anton';font-style:normal;font-weight:400;font-display:swap;src:url('/wk/anton-latin.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

:root{
  /* colour — roles, not names. gold is an ACTION colour only. */
  --ink:#2B2A28;
  --merk:#3A3A38;
  --merk-hover:#4C4C49;
  --muted:#A2968A;
  --line:#DDD5C9;
  --line-strong:#A2968A;
  --bg:#FAF9F7;
  --card:#E5DED4;
  --accent:#E8B44A;
  --accent-dark:#D4A038;
  --accent-text:#412402;
  --sale:#A32D2D;
  --success:#3B6D11;

  --font:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --display:'Anton',var(--font);

  --max:1360px;
  --r:14px;
  --r-card:12px;
  --shadow:0 6px 24px rgba(43,42,40,.10);
  --shadow-lift:0 14px 44px rgba(43,42,40,.16);

  /* the two harvested room textures. Both are crops of assets/scene/*.jpg with
     their baked lighting divided back out, so the drawn room is made of the same
     plaster and the same oak as the original photograph. Two files serve every
     colour × size combination; nothing here is ever per-variant. */
  --plaster:url("scene/plaster.jpg");
  --oak:url("scene/oak.jpg");
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:var(--font);
  background:var(--bg);
  color:var(--ink);
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
h1,h2,h3,h4{font-weight:700;letter-spacing:-.01em;margin:0}
button{font:inherit;color:inherit}
img{max-width:100%;display:block}

/* ---------- chrome ---------- */
.topbar{
  background:var(--bg);border-bottom:1px solid var(--line);
  font-size:12.5px;color:var(--muted);
}
.topbar .in{max-width:var(--max);margin:0 auto;padding:9px 24px;display:flex;
  gap:22px;align-items:center;flex-wrap:wrap}
.topbar .usp{display:flex;gap:7px;align-items:center}
.topbar .spacer{margin-left:auto}
.topbar a{color:var(--muted);text-decoration:none}
.topbar a:hover{color:var(--ink)}

.header{
  position:sticky;top:0;z-index:40;background:var(--bg);
  border-bottom:1px solid var(--line);
}
.header .in{max-width:var(--max);margin:0 auto;padding:16px 24px;
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px}
.header nav{display:flex;gap:22px;font-size:14px}
.header nav a{color:var(--ink);text-decoration:none}
.header nav a:hover{color:var(--muted)}
.header .brand{
  font-family:var(--display);font-size:26px;letter-spacing:.06em;
  text-transform:uppercase;text-align:center;white-space:nowrap
}
.header .right{justify-self:end;font-size:13px;color:var(--muted)}

/* ---------- crumbs + title ---------- */
.crumbs{max-width:var(--max);margin:0 auto;padding:18px 24px 0;
  font-size:12.5px;color:var(--muted)}
.crumbs a{color:var(--muted);text-decoration:none}

/* ---------- layout ---------- */
.pdpx{max-width:var(--max);margin:0 auto;padding:14px 24px 90px;
  display:flex;gap:0;align-items:flex-start}
.pdpx-stagecol{flex:1 1 auto;min-width:0;position:sticky;top:86px}
.pdpx-card{
  flex:0 0 460px;background:var(--card);border:1px solid var(--line);
  border-radius:var(--r-card);padding:26px 26px 22px;
  margin:16px 0 16px -32px;box-shadow:var(--shadow);position:relative;z-index:2
}

/* ---------- stage ---------- */
.stage{
  background:var(--bg);border:1px solid var(--line);border-radius:var(--r-card);
  height:calc(100vh - 250px);min-height:540px;max-height:760px;
  display:flex;align-items:center;justify-content:center;
  overflow:hidden;position:relative
}
.stage-tools{
  display:flex;gap:10px;align-items:center;justify-content:space-between;
  /* the card overlaps the stage column by 32px and sits above it — without this
     right pad the meta text is sliced by the card edge */
  padding:12px 44px 0 4px;font-size:12.5px;color:var(--muted);flex-wrap:wrap
}
.seg{display:inline-flex;background:var(--card);border:1px solid var(--line);
  border-radius:999px;padding:3px}
.seg button{
  border:0;background:transparent;border-radius:999px;padding:6px 14px;
  font-size:12.5px;cursor:pointer;color:var(--ink);opacity:.62;transition:.18s
}
.seg button[aria-pressed="true"]{background:var(--bg);opacity:1;font-weight:600;
  box-shadow:0 1px 3px rgba(43,42,40,.12)}
.stage-meta{display:flex;gap:14px;align-items:center}
.stage-meta b{color:var(--ink);font-weight:600}
/* the fit note may wrap on a phone; a measurement never splits across lines */
.stage-meta b,.stage-meta #metaArea{white-space:nowrap}

/* ---------- price header inside card ---------- */
.eyebrow{font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);margin-bottom:6px}
.title{font-family:var(--display);font-size:26px;font-weight:400;
  text-transform:uppercase;letter-spacing:.01em;line-height:1.1}
.pricerow{display:flex;align-items:baseline;gap:10px;margin-top:12px}
.pricerow .now{font-size:24px;font-weight:600;font-variant-numeric:tabular-nums}
.pricerow .lbl{font-size:12px;color:var(--muted)}
.vat{font-size:11px;color:var(--muted);margin-top:2px}

/* ---------- progress ---------- */
.prog{margin:20px 0 4px}
.prog-track{height:3px;background:rgba(43,42,40,.12);border-radius:999px;overflow:hidden}
.prog-fill{height:100%;background:var(--accent);border-radius:999px;
  transition:width .35s cubic-bezier(.4,0,.2,1)}
.prog-steps{display:flex;justify-content:space-between;margin-top:10px;gap:6px}
.prog-steps button{
  border:0;background:transparent;padding:0;cursor:pointer;text-align:left;
  font-size:11.5px;color:var(--muted);letter-spacing:.02em;flex:1;
  white-space:nowrap;overflow:hidden;display:flex;align-items:center
}
.prog-steps button .n{
  display:inline-flex;width:19px;height:19px;border-radius:999px;
  border:1px solid var(--line-strong);align-items:center;justify-content:center;
  font-size:10.5px;margin-right:5px;transition:.2s
}
.prog-steps button[data-state="current"]{color:var(--ink);font-weight:600}
.prog-steps button[data-state="current"] .n{background:var(--ink);color:var(--bg);
  border-color:var(--ink)}
.prog-steps button[data-state="done"]{color:var(--ink)}
.prog-steps button[data-state="done"] .n{background:var(--success);border-color:var(--success);
  color:#fff}

/* ---------- steps ---------- */
.step{display:none;padding-top:20px}
.step[data-active="true"]{display:block;animation:fade .3s ease both}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.step-h{font-size:16px;font-weight:700;margin-bottom:2px}
.step-sub{font-size:12.5px;color:var(--muted);margin-bottom:18px}

.grp{margin-bottom:22px}
.grp-head{display:flex;justify-content:space-between;align-items:baseline;
  gap:12px;margin-bottom:9px}
.grp-name{font-size:14px;font-weight:600}
.grp-val{font-size:12.5px;font-weight:700;text-align:right;color:var(--ink)}
.grp-hint{font-size:11.5px;color:var(--muted);margin-top:7px}

/* text + number inputs */
.field{
  width:100%;background:var(--bg);border:1px solid var(--line);border-radius:999px;
  padding:12px 16px;font-size:14px;color:var(--ink);outline:0;transition:.18s
}
.field:focus{border-color:var(--line-strong);box-shadow:0 0 0 3px rgba(162,150,138,.18)}
.field.bad{border-color:var(--sale);box-shadow:0 0 0 3px rgba(163,45,45,.13)}
.mmrow{display:flex;gap:10px;align-items:center}
.mmrow .field{flex:1}
.mmrow .unit{font-size:12px;color:var(--muted);width:26px}
input[type=range]{
  -webkit-appearance:none;appearance:none;width:100%;height:3px;margin:14px 0 2px;
  background:rgba(43,42,40,.14);border-radius:999px;outline:0
}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:20px;height:20px;border-radius:999px;
  background:var(--bg);border:1px solid var(--line-strong);cursor:pointer;
  box-shadow:0 2px 6px rgba(43,42,40,.18)
}
.rangecap{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}

/* tile options (image + label + surcharge) */
.tiles{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}
.tiles.c1{grid-template-columns:1fr}
.tile{
  display:flex;gap:11px;align-items:center;text-align:left;cursor:pointer;
  background:var(--bg);border:1px solid var(--line);border-radius:10px;
  padding:9px 11px;transition:.18s;position:relative
}
.tile:hover{border-color:var(--line-strong)}
.tile[aria-pressed="true"]{border-color:var(--ink);box-shadow:0 0 0 1px var(--ink)}
.tile img,.tile .ph{
  width:40px;height:40px;border-radius:7px;object-fit:cover;flex:none;
  border:1px solid var(--line)
}
.tile .tx{min-width:0}
.tile .t1{font-size:12.5px;font-weight:600;line-height:1.25}
.tile .t2{font-size:11px;color:var(--muted);margin-top:2px}
.tile .t2.plus{color:var(--ink);font-weight:600}

/* circular colour swatches */
.chips{display:grid;grid-template-columns:repeat(8,1fr);gap:10px}
.chip{
  position:relative;width:100%;aspect-ratio:1;border-radius:999px;border:1px solid var(--line);
  background-size:cover;background-position:center;cursor:pointer;padding:0;transition:.18s
}
.chip:hover{transform:scale(1.07)}
.chip[aria-pressed="true"]::after{
  content:"";position:absolute;inset:-4px;border-radius:999px;border:2px solid var(--ink)
}
.chipname{font-size:11.5px;color:var(--muted);margin-top:9px;min-height:17px}

/* ---------- overzicht ---------- */
.sum{background:var(--bg);border:1px solid var(--line);border-radius:10px;
  padding:4px 14px;margin-bottom:16px}
.sum .r{display:flex;justify-content:space-between;gap:14px;padding:9px 0;
  border-bottom:1px solid var(--line);font-size:12.5px}
.sum .r:last-child{border-bottom:0}
.sum .r .k{color:var(--muted)}
.sum .r .v{font-weight:600;text-align:right}

.totals{background:var(--bg);border:1px solid var(--line);border-radius:10px;
  padding:14px;margin-bottom:16px}
.totals .r{display:flex;justify-content:space-between;font-size:13px;padding:5px 0;
  font-variant-numeric:tabular-nums}
.totals .r .k{color:var(--muted)}
.totals .r.grand{border-top:1px solid var(--line);margin-top:6px;padding-top:11px;
  font-size:17px;font-weight:700}
.totals .r.grand .k{color:var(--ink)}
.totals details{margin-top:10px}
.totals summary{font-size:11.5px;color:var(--muted);cursor:pointer;list-style:none}
.totals summary::-webkit-details-marker{display:none}
.totals summary::before{content:"› ";display:inline-block;transition:.2s}
.totals details[open] summary::before{transform:rotate(90deg)}
.calc{font-size:11.5px;color:var(--muted);margin-top:8px;line-height:1.7;
  font-variant-numeric:tabular-nums}
.calc code{background:var(--card);padding:1px 5px;border-radius:4px;font-size:11px}

.notice{
  border:1px solid var(--line);border-left:3px solid var(--merk);
  background:var(--bg);border-radius:8px;padding:12px 14px;margin-bottom:16px
}
.notice h4{font-size:12.5px;margin-bottom:5px}
.notice p{font-size:11.5px;color:var(--muted);margin:0 0 6px}
.notice p:last-child{margin-bottom:0}

/* ---------- buttons ---------- */
.nav{display:flex;gap:10px;margin-top:6px}
.btn{
  background:var(--accent);color:var(--accent-text);padding:14px 26px;
  border-radius:999px;font-weight:700;font-size:15px;border:0;cursor:pointer;
  transition:background-color .2s
}
.btn:hover{background:var(--accent-dark)}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.btn.full{width:100%}
.btn-ghost{
  background:transparent;border:1px solid var(--line);color:var(--ink);
  padding:14px 22px;border-radius:999px;font-size:14px;font-weight:600;cursor:pointer;
  transition:.2s
}
.btn-ghost:hover{border-color:var(--line-strong)}
.trust{font-size:11.5px;color:var(--muted);margin-top:14px;display:flex;
  gap:7px;align-items:flex-start}

/* ==========================================================================
   Live layered preview
   ========================================================================== */
.pv{position:relative;display:flex;align-items:center;justify-content:center;
  width:100%;height:100%;overflow:hidden}

/* ---------- the interior room ----------
   The room is a real CSS 3D scene, not a photograph with a hole in it, because
   the opening has to be whatever size the customer types. preview.js sets the
   camera (perspective + perspective-origin) and the size of every surface from
   breedte × hoogte; the stylesheet only says what each surface is made of.

   World units: 1 px here is one px on the wall plane, and preview.js keeps the
   metre-to-px scale for the wall, the floor, the dagkant, the vensterbank and
   the blind identical, so everything on screen is in one consistent scale.

   Sunlight enters from outside left, travelling right and into the room. So the
   RIGHT jamb catches the sun, the LEFT jamb is in shade, the lintel underside is
   darkest, and the patch of sun on the floor sits right of the window. Every
   shadow below follows that. */

.rm{position:absolute;inset:0}

/* the wall plane at z = 0. Plaster is a real crop of the room photograph
   (assets/scene/plaster.jpg), tiled at a fixed size IN METRES, so the grain
   stays the same physical size whatever the window does. */
.rm-wall{
  position:absolute;inset:0;background-repeat:repeat;background-color:#E7DFD2;
  background-image:
    /* daylight from an off-camera window, upper left */
    linear-gradient(152deg, rgba(255,251,238,.60) 0%, rgba(255,251,238,.12) 33%,
      rgba(255,251,238,0) 57%),
    /* the room's own falloff towards the floor */
    linear-gradient(180deg, rgba(74,60,44,.06) 0%, rgba(74,60,44,0) 24%,
      rgba(74,60,44,.08) 72%, rgba(74,60,44,.19) 100%),
    var(--plaster);
  background-blend-mode:screen,multiply,normal
}
/* There is deliberately NO patch of sun painted on this wall. Sunlight through
   the window in the scene travels INTO the room: it lands on the floor and on
   the wall opposite, never on the wall the window is set in. The only thing that
   could light this wall directly is a second window behind the camera, and the
   scene gives the viewer no evidence for one. So the wall carries ambient and
   bounce light only — everything below is traceable to the opening in frame. */
/* daylight the opening throws back onto the wall around it: bounce off the floor
   and the reveal, plus the bright glazing itself seen at a grazing angle. Soft,
   radial, centred on the real opening — it moves and grows with it. */
.rm-spill{position:absolute;pointer-events:none;mix-blend-mode:screen}
/* the opening's own contact darkening on the wall it is cut into */
.rm-edge{position:absolute;pointer-events:none;mix-blend-mode:multiply}

.rm-space{position:absolute;inset:0;transform-style:preserve-3d}

/* the floor: one plane, hinged along the wall/floor junction and laid flat by
   rotateX(90deg). The browser's own perspective then does the foreshortening,
   which is why the boards converge correctly at every window size. */
.rm-floor{
  position:absolute;transform-origin:0 0;transform:rotateX(90deg);
  background-repeat:repeat;backface-visibility:hidden;overflow:hidden;
  background-color:#D9C8B1;
  background-image:
    /* the floor tucking in under the wall, and the room going quiet up close */
    linear-gradient(to bottom, rgba(46,34,20,.34) 0%, rgba(46,34,20,.11) 3.5%,
      rgba(46,34,20,0) 14%, rgba(46,34,20,0) 62%, rgba(46,34,20,.14) 100%),
    var(--oak);
  background-blend-mode:multiply,normal
}
/* The sun coming THROUGH this window, landing on this floor. The shape is the
   UNCOVERED part of the aperture, projected along the scene's one sun vector, so
   it is cast by the window that is actually in frame and by the part of it the
   blind is not covering. Closed = no sun shape at all, only whatever the fabric
   diffuses through (see preview.js).

   Two elements on purpose: the blur has to be applied AFTER the clip, or the
   projected quad keeps a razor edge and reads as a decal. The outer carries the
   penumbra, the inner carries the shape. */
.rm-floorsun{position:absolute;inset:0;mix-blend-mode:screen;pointer-events:none}
.rm-floorsun .shape{position:absolute;inset:0}

/* the opening: a box of breedte × hoogte × dagkant set into the wall */
.rm-open{position:absolute;transform-style:preserve-3d}
.rv{
  position:absolute;background-repeat:repeat;backface-visibility:hidden;
  overflow:hidden
}

/* the far end of that box. Its overflow clips the blind, and the four reveal
   faces meet it edge to edge, so the blind owns the whole opening — no strip of
   glass left over beside it. */
.pv-ap{position:absolute;z-index:2}
.pv[data-mode="room"] .pv-ap{display:block;overflow:hidden}
/* fallback: a texture did not load, so the room collapses back to the pure-CSS
   wall and the opening stops being a box and goes back to being the plain
   centring wrapper that wall expects. The blind itself is untouched. */
.pv[data-mode="css"] .rm-wall,
.pv[data-mode="css"] .rm-spill,
.pv[data-mode="css"] .rm-edge,
.pv[data-mode="css"] .rm-floor,
.pv[data-mode="css"] .rv{display:none}
.pv[data-mode="css"] .rm-space,
.pv[data-mode="css"] .rm-open{
  position:absolute;inset:0;transform:none;transform-style:flat
}
.pv[data-mode="css"] .pv-ap{
  position:absolute;left:0;top:0;width:100%;height:100%;
  display:flex;align-items:center;justify-content:center;overflow:visible
}
.pv[data-mode="css"] .pv-view,
.pv[data-mode="css"] .pv-sheen,
.pv[data-mode="css"] .pv-recess{display:none}

/* 1 — the view, its own photograph */
.pv-view{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:center 46%;pointer-events:none
}
/* 2 — glazing. Restrained on purpose: enough to say "there is glass here",
   not enough to fog the view. */
.pv-sheen{
  position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(116deg,
    rgba(255,255,255,.17) 0 8%, rgba(255,255,255,0) 26%,
    rgba(255,255,255,0) 67%, rgba(255,255,255,.10) 79%, rgba(255,255,255,0) 91%)
}
/* the shadow the reveal throws back onto the blind. Much lighter than it used
   to be: the jambs and the lintel are now real surfaces that shade themselves,
   so this only has to carry the contact shadow at the very edges. */
.pv-recess{
  /* shadow-border ring removed (Sander): aperture edge reads clean, not a dark soft border */
  position:absolute;inset:0;pointer-events:none;
  box-shadow:none
}

/* ---------- the four faces of the reveal ----------
   Each is a rectangle of plaster (the sill is oak) hinged on one edge of the
   opening and folded back into the wall by 90°. Their far edges land exactly on
   the aperture, so the reveal reads as thickness rather than as a drawn border.
   The gradients run from the room end to the glass end of each face. */
.rv-left{                         /* reveal face — flattened, no dark shadow border */
  background-image:var(--plaster)
}
.rv-right{                        /* reveal face — flattened, no dark shadow border */
  background-image:var(--plaster)
}
.rv-top{                          /* latei underside — flattened, no dark shadow border */
  background-image:var(--plaster)
}
.rv-sill{                         /* oak vensterbank — gentle daylight, no heavy shadow */
  background-image:
    linear-gradient(to bottom, rgba(255,250,234,.16), rgba(255,251,238,.10)),
    var(--oak)
}

/* the painted wall, floor, glass, plaster reveal and sill of the pure-CSS
   fallback. They only apply in data-mode="css". */
.pv[data-mode="room"]::before,
.pv[data-mode="room"]::after,
.pv[data-mode="room"] .pv-win::before{content:none}
.pv[data-mode="room"] .pv-glass,
.pv[data-mode="room"] .pv-sill{display:none}
.pv[data-mode="room"] .pv-win{position:absolute}
/* the panel's own shadow, falling on the view it is hanging in front of */
.pv[data-mode="room"] .pv-fabric{box-shadow:5px 8px 16px rgba(43,38,30,.30)}
.pv[data-mode="room"] .pv-stack{box-shadow:0 0 0 1px rgba(43,42,40,.16),
  6px 8px 16px rgba(43,38,30,.34)}
/* over a photographic wall the bare grey text disappears into the plaster */
.pv[data-mode="room"] .pv-dims{
  color:#514840;background:rgba(250,249,247,.82);border-radius:999px;
  padding:2px 8px;backdrop-filter:blur(4px)
}

/* ---------- photo scene ----------
   The background is a real interior photo (wall, WHITE kozijn, vensterbank and
   garden are all IN it); only the blind is composited over the measured opening.
   So: show the photo, drop the drawn room, flatten the 3D chain to the opening
   box, hide the drawn glass/frame, and clip the blind to the photo's window.
   What the blind does not cover stays transparent, so the photo shows through
   (half-open, and through a translucent mesh when closed). */
.pv-photo{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center;display:none;z-index:0;
  pointer-events:none;user-select:none
}
.pv[data-mode="photo"] .pv-photo{display:block}
.pv[data-mode="photo"] .rm-wall,
.pv[data-mode="photo"] .rm-spill,
.pv[data-mode="photo"] .rm-edge,
.pv[data-mode="photo"] .rm-floor,
.pv[data-mode="photo"] .rv{display:none}
.pv[data-mode="photo"] .rm{perspective:none}
.pv[data-mode="photo"] .rm-space,
.pv[data-mode="photo"] .rm-open{position:absolute;inset:0;transform:none;transform-style:flat}
.pv[data-mode="photo"] .pv-ap{display:block;overflow:hidden}   /* clip blind to the opening */
.pv[data-mode="photo"] .pv-view,
.pv[data-mode="photo"] .pv-sheen,
.pv[data-mode="photo"] .pv-recess,
.pv[data-mode="photo"] .pv-glass,
.pv[data-mode="photo"] .pv-sill,
.pv[data-mode="photo"] .pv-frame{display:none}       /* photo already has the kozijn */
.pv[data-mode="photo"]::before,
.pv[data-mode="photo"]::after,
.pv[data-mode="photo"] .pv-win::before{content:none}
.pv[data-mode="photo"] .pv-win{position:absolute}
/* seat the blind in the opening: a gentle inset reveal shadow around its edges,
   so the fabric sits IN the photo's window rather than floating as a flat panel
   over it. Kept subtle (not a dark drawn border) and clipped by .pv-ap so it can
   never spill onto the white frame. */
.pv[data-mode="photo"] .pv-fabric{
  box-shadow:
    inset 0 3px 12px rgba(58,42,22,.24),
    inset 0 -3px 12px rgba(58,42,22,.18),
    inset 8px 0 18px rgba(58,42,22,.12),
    inset -8px 0 18px rgba(58,42,22,.12)
}
.pv[data-mode="photo"] .pv-stack{box-shadow:0 0 0 1px rgba(43,42,40,.14),0 6px 14px rgba(43,38,30,.30)}
.pv[data-mode="photo"] .pv-dims{
  color:#514840;background:rgba(250,249,247,.82);border-radius:999px;
  padding:2px 8px;backdrop-filter:blur(4px)
}

/* wall */
.pv::before{
  content:"";position:absolute;inset:0;
  background:
    radial-gradient(120% 90% at 50% 12%, rgba(255,255,255,.55), rgba(255,255,255,0) 62%),
    linear-gradient(180deg,#F3F0EB 0%,#E9E4DC 78%,#DED7CD 100%)
}
/* floor line */
.pv::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:16%;
  background:linear-gradient(180deg,#D9D1C5,#CFC6B8);
  box-shadow:inset 0 1px 0 rgba(43,42,40,.10)
}

/* NO transition on the geometry. The blind IS the opening: preview.js sizes the
   aperture and the blind from the same breedte × hoogte in the same call, so any
   easing here makes the blind lag the hole it is supposed to be filling and a
   CLOSED blind visibly stops covering its own aperture for a third of a second
   on every slider step. Same reason .pv-fabric, .pv-stack and .pv-rail below
   only ever transition colour. */
.pv-win{position:relative;z-index:2}
/* plaster reveal around the window */
.pv-win::before{
  content:"";position:absolute;inset:-14px;border-radius:3px;
  background:linear-gradient(160deg,#FBF9F5,#E6E0D6);
  box-shadow:0 18px 44px rgba(43,42,40,.20), inset 0 0 0 1px rgba(43,42,40,.06)
}
/* sill */
.pv-sill{
  position:absolute;left:-26px;right:-26px;top:100%;height:12px;z-index:3;
  background:linear-gradient(180deg,#FCFAF6,#DFD8CC);
  box-shadow:0 8px 16px rgba(43,42,40,.16);border-radius:0 0 3px 3px
}

/* daylight behind the blind */
.pv-glass{
  position:absolute;inset:0;overflow:hidden;
  background:linear-gradient(180deg,#CFE2EE 0%,#E4EEF2 44%,#D7E0D2 68%,#BFCBB4 100%)
}
.pv-glass::after{
  content:"";position:absolute;inset:0;
  background:radial-gradient(70% 55% at 62% 22%, rgba(255,255,255,.85), rgba(255,255,255,0) 70%)
}

/* the fabric.
   .pv-weave IS the cloth: the real plissexxl swatch PNG, tiled, unfiltered, opaque.
   .pv-fabric behind it only carries the sampled average colour as a pre-decode
   fallback, so there is never a white flash when the colour changes. */
.pv-fabric{
  position:absolute;left:0;right:0;overflow:hidden;
  transition:background-color .25s
}
.pv-weave{
  position:absolute;inset:0;background-repeat:repeat;background-position:center
}

/* real swatch, native resolution, no filters — the honest material reference */
.pv-detail{
  position:absolute;left:18px;bottom:18px;z-index:7;display:flex;gap:11px;
  align-items:center;background:rgba(250,249,247,.92);border:1px solid var(--line);
  border-radius:999px;padding:7px 15px 7px 7px;backdrop-filter:blur(6px)
}
.pv-detail .sw{
  width:38px;height:38px;border-radius:999px;flex:none;border:1px solid var(--line);
  background-size:150px auto;background-position:center
}
.pv-detail .tx{display:flex;flex-direction:column;line-height:1.25}
.pv-detail .tx .a{font-size:12px;font-weight:600}
.pv-detail .tx .b{font-size:9.5px;color:var(--muted);letter-spacing:.09em;
  text-transform:uppercase}
/* concertina pleat shading, drawn on top of the real texture */
.pv-pleats{position:absolute;inset:0;mix-blend-mode:multiply;opacity:.92}
.pv-pleats-hi{position:absolute;inset:0;mix-blend-mode:screen}
/* daylight bleeding through, scaled by the fabric's lichtdoorlatendheid */
.pv-glow{position:absolute;inset:0;mix-blend-mode:screen;pointer-events:none;
  transition:opacity .3s}
/* soft occlusion under the head rail */
.pv-fabric::after{
  content:"";position:absolute;left:0;right:0;top:0;height:14px;
  background:linear-gradient(180deg,rgba(43,42,40,.24),rgba(43,42,40,0))
}

/* stacked pleats (the gathered pack when opened) */
.pv-stack{position:absolute;overflow:hidden;background-repeat:repeat;
  background-position:center;
  /* outline + cast shadow so the compressed pack reads as a separate solid body
     and not as a slightly different patch of the same panel */
  box-shadow:0 0 0 1px rgba(43,42,40,.16), 0 5px 14px rgba(43,42,40,.22)}
.pv-stack .sh{position:absolute;inset:0;mix-blend-mode:multiply}

/* frame / rails — filled with the sampled RAL colour of the real swatch */
.pv-frame{position:absolute;inset:0;pointer-events:none;z-index:4}
.pv-rail{position:absolute;transition:background .25s}
/* Bevelled kozijn profile. The room's daylight (ROOM.sun) rakes in from the upper
   left, so each member carries a crisp micro-bevel highlight on its lit edge, a
   defined inner edge, and — for the top/left members that stand between the light
   and the recessed cloth — a soft rebate contact shadow thrown inward onto it.
   Shading only: the flat face of every rail keeps the exact sampled RAL hue; the
   profile lives entirely at the edges, never washing the face toward white. */
.pv-rail::after{content:"";position:absolute;inset:0}
/* top + left = lit side: bright outer chamfer -> true-hue face -> shadowed inner edge */
.pv-rail.t::after{background:linear-gradient(180deg,
  rgba(255,251,242,.38) 0%,rgba(255,251,242,.08) 12%,rgba(0,0,0,0) 60%,
  rgba(0,0,0,.12) 90%,rgba(0,0,0,.24) 100%)}
.pv-rail.l::after{background:linear-gradient(90deg,
  rgba(255,251,242,.38) 0%,rgba(255,251,242,.08) 12%,rgba(0,0,0,0) 60%,
  rgba(0,0,0,.12) 90%,rgba(0,0,0,.24) 100%)}
/* bottom + right = shadow side: dim inner-chamfer catch -> face -> shadowed outer edge */
.pv-rail.b::after{background:linear-gradient(180deg,
  rgba(255,251,242,.14) 0%,rgba(255,255,255,0) 16%,rgba(0,0,0,0) 55%,
  rgba(0,0,0,.16) 92%,rgba(0,0,0,.24) 100%)}
.pv-rail.r::after{background:linear-gradient(90deg,
  rgba(255,251,242,.14) 0%,rgba(255,255,255,0) 16%,rgba(0,0,0,0) 55%,
  rgba(0,0,0,.16) 92%,rgba(0,0,0,.24) 100%)}
/* rebate: the frame is raised over the set-back cloth, so its top and left lips
   cast a soft contact shadow inward; the shadow-side lips barely register */
.pv-rail.t{box-shadow:0 3px 5px -2px rgba(30,26,20,.30)}
.pv-rail.l{box-shadow:3px 0 5px -2px rgba(30,26,20,.30)}
.pv-rail.b{box-shadow:0 1px 2px -1px rgba(30,26,20,.12)}
.pv-rail.r{box-shadow:1px 0 2px -1px rgba(30,26,20,.12)}
/* mitred corner joints: a fine two-tone hairline on the 45° line from each outer
   corner to the inner corner, so the butt-jointed rails read as a cut-and-joined
   kozijn. Tones come from preview.js (--seam-hi / --seam-sh, scaled to the RAL). */
.pv-seam{position:absolute;z-index:2;pointer-events:none}
.pv-seam.tl{left:0;top:0}.pv-seam.tr{right:0;top:0}
.pv-seam.bl{left:0;bottom:0}.pv-seam.br{right:0;bottom:0}
.pv-seam.tl,.pv-seam.br{background:linear-gradient(45deg,
  transparent calc(50% - .7px),var(--seam-hi,rgba(255,252,245,.42)) calc(50% - .7px),
  var(--seam-hi,rgba(255,252,245,.42)) 50%,var(--seam-sh,rgba(0,0,0,.26)) 50%,
  var(--seam-sh,rgba(0,0,0,.26)) calc(50% + .7px),transparent calc(50% + .7px))}
.pv-seam.tr,.pv-seam.bl{background:linear-gradient(135deg,
  transparent calc(50% - .7px),var(--seam-hi,rgba(255,252,245,.42)) calc(50% - .7px),
  var(--seam-hi,rgba(255,252,245,.42)) 50%,var(--seam-sh,rgba(0,0,0,.26)) 50%,
  var(--seam-sh,rgba(0,0,0,.26)) calc(50% + .7px),transparent calc(50% + .7px))}
.pv-cord{position:absolute;width:1.5px;background:rgba(43,42,40,.30);z-index:5;
  border-radius:999px}

/* placed by preview.js against the blind, in both scene and fallback mode */
.pv-dims{position:absolute;z-index:6;font-size:11px;color:var(--muted);
  font-variant-numeric:tabular-nums;letter-spacing:.02em;white-space:nowrap}
.pv-dims.w{transform:translateX(-50%)}
.pv-dims.h{transform:translateY(-50%) rotate(90deg)}

.pv-badge{
  position:absolute;left:18px;top:18px;z-index:7;background:rgba(250,249,247,.92);
  border:1px solid var(--line);border-radius:999px;padding:6px 13px;font-size:11.5px;
  color:var(--ink);backdrop-filter:blur(6px);display:flex;gap:8px;align-items:center
}
.pv-badge .dot{width:9px;height:9px;border-radius:999px;border:1px solid rgba(43,42,40,.2)}

/* ---------- responsive ---------- */
@media (max-width:1080px){
  .pdpx{flex-direction:column;padding:14px 24px 90px}
  .pdpx-stagecol{position:static;width:100%}
  .pdpx-card{flex:none;width:100%;margin:18px 0 0}
  .stage{height:auto;min-height:0;aspect-ratio:4/3;max-height:none}
  .stage-tools{padding-right:4px}
}
@media (max-width:760px){
  .pdpx{padding:10px 14px 90px}
  .crumbs{padding:14px 14px 0}
  .header .in,.topbar .in{padding-left:14px;padding-right:14px}
  .header nav,.header .right,.topbar .spacer~a,.topbar .usp:nth-child(n+2){display:none}
  .topbar .in{flex-wrap:nowrap;padding-top:7px;padding-bottom:7px}
  .header .in{grid-template-columns:1fr;padding-top:11px;padding-bottom:11px}
  .header .brand{font-size:21px}
  .title{font-size:22px}
  .pdpx-card{padding:18px 16px 18px;border-radius:var(--r-card)}
  .chips{grid-template-columns:repeat(6,1fr);gap:8px}
  .tiles{grid-template-columns:1fr}
  .stage{aspect-ratio:4/5}
  .stage-tools{font-size:11.5px}
  .prog-steps button span.lbl{display:none}
  /* the size is already stated in .stage-tools right below the stage, and the
     dimension labels collide with the swatch chip at this width */
  .pv-dims{display:none}
  .pv-badge{left:10px;top:10px;font-size:10.5px;padding:5px 10px}
  .pv-detail{left:10px;bottom:10px;padding:5px 12px 5px 5px}
  .pv-detail .sw{width:30px;height:30px}
}
