/* Maison Silya — Tufted The atelier's hand-tufted work, gathered in two collections: ÉPURE — ten graphic, monochrome geometries (Bauhaus restraint). MÉRIDIENNE — eight painterly landscapes in full colour (the PDF collection). The Tufted route opens on a landing that presents the two collections; entering one reveals its artistic statement and its pieces. */ /* ── Dimensions rule: fixed sizes + any bespoke size share the same surface-area computation (m²), used for made-to-order enquiries. No prices are shown — every piece is offered by enquiry. ──────── */ function msTuftedArea(a, b, shape) { return shape === 'round' ? Math.PI * (a / 2) * (a / 2) / 10000 : (a * b) / 10000; } const MS_TUFTED_SIZES = [ { key: 's', label: '170 × 240 cm', w: 170, l: 240 }, { key: 'm', label: '200 × 300 cm', w: 200, l: 300 }, { key: 'l', label: '250 × 350 cm', w: 250, l: 350 }, { key: 'xl', label: '300 × 400 cm', w: 300, l: 400 }, ]; const MS_TUFTED_ROUND_SIZES = [ { key: 's', label: 'Ø 180 cm', d: 180 }, { key: 'm', label: 'Ø 220 cm', d: 220 }, { key: 'l', label: 'Ø 250 cm', d: 250 }, { key: 'xl', label: 'Ø 300 cm', d: 300 }, ]; /* ════════════════════════════════════════════════════════════════ COLLECTION I — ÉPURE (the original ten geometric pieces) ════════════════════════════════════════════════════════════════ */ const MS_EPURE = [ { id: 'orbite', image: 'media/tufted-01.jpg', name: 'Orbite', fr: { line: 'L\'arc et le cercle, dans les ocres minéraux.', desc: 'Orbite recompose le vocabulaire du Bauhaus avec les matières du sol. Les arches concentriques et les cercles pleins dialoguent dans une palette de gris pierre, d\'ivoire et de terracotta — une géométrie tempérée par la chaleur.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'The arc and the circle, in mineral ochres.', desc: 'Orbite recomposes the Bauhaus vocabulary with the materials of the floor. Concentric arches and solid circles dialogue in a palette of stone grey, ivory and terracotta — geometry tempered by warmth.', mat: '100% New Zealand Wool' }, }, { id: 'flux', image: 'media/tufted-02.jpg', name: 'Flux', fr: { line: 'Des lignes qui obéissent — puis se libèrent.', desc: 'Flux commence dans la rigueur des rayures parallèles et se dissout dans le mouvement organique. Le noir et l\'ivoire entrent en tension jusqu\'au bord, où la forme du tapis elle-même se dérobe. Une pièce qui ne se laisse pas oublier.', mat: '100% Laine de Nouvelle-Zélande · Contour sculpté' }, en: { line: 'Lines that obey — then break free.', desc: 'Flux begins in the rigour of parallel stripes and dissolves into organic movement. Black and ivory hold in tension to the edge, where the very shape of the rug gives way. A piece that refuses to be forgotten.', mat: '100% New Zealand Wool · Sculpted contour' }, }, { id: 'meandre', image: 'media/tufted-03.jpg', name: 'Méandre', fr: { line: 'La ligne qui hésite entre la rigueur et la courbe.', desc: 'Méandre trace un seul geste architectural en fils de laine serrés : des lignes parallèles ivoire et taupe qui pivotent dans un angle unique. La sobriété du trait, la densité de la matière.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie pure de Chine' }, en: { line: 'The line that hesitates between rigour and curve.', desc: 'Méandre traces a single architectural gesture in tightly-packed wool threads — ivory and taupe parallel lines that pivot in one precise angle. The sobriety of the line, the density of the matter.', mat: '80% New Zealand Wool · 20% Pure Chinese Silk' }, }, { id: 'vortex', image: 'media/tufted-04.jpg', name: 'Vortex', fr: { line: 'Deux forces contraires qui s\'équilibrent en un point.', desc: 'Vortex organise le noir et l\'ivoire en un double mouvement spiralé. Les lignes se répondent de part et d\'autre d\'un centre imperceptible, créant une composition optique d\'une intensité rare. À distance : de l\'architecture. De près : de la matière.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'Two opposing forces balanced at a single point.', desc: 'Vortex organises black and ivory into a double spiralling movement. Lines answer each other across an imperceptible centre, creating an optical composition of rare intensity. At distance: architecture. Up close: matter.', mat: '100% New Zealand Wool' }, }, { id: 'onde', image: 'media/tufted-05.jpg', name: 'Onde', fr: { line: 'Le mouvement de l\'eau, figé dans la laine.', desc: 'Onde pose deux courbes ondulantes en bleu poudre sur un fond ivoire. Les lignes s\'étirent et se contractent comme des ondulations à la surface d\'un lac — une tranquillité active, qui change avec la lumière du jour.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie pure de Chine' }, en: { line: 'The movement of water, held still in wool.', desc: 'Onde lays two undulating curves in powder blue on an ivory ground. The lines stretch and contract like ripples on a lake\'s surface — an active tranquillity that shifts with the light of day.', mat: '80% New Zealand Wool · 20% Pure Chinese Silk' }, }, { id: 'module', image: 'media/tufted-06.jpg', name: 'Module', fr: { line: 'Les formes primaires, réunies sans hiérarchie.', desc: 'Module assemble bandes verticales, demi-cercles hachurés et aplats noirs dans une composition qui cite le constructivisme sans le reproduire. La texture des hachures contraste avec la densité des aplats — un tapis qui est aussi une étude.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'Primary forms, assembled without hierarchy.', desc: 'Module assembles vertical bands, hatched half-circles and solid black planes in a composition that cites constructivism without reproducing it. The texture of the hatching contrasts with the density of the solids — a rug that is also a study.', mat: '100% New Zealand Wool' }, }, { id: 'circuit', image: 'media/tufted-07.jpg', name: 'Circuit', fr: { line: 'Les orbites qui se croisent sans jamais se toucher.', desc: 'Circuit superpose cercles, demi-arches et lignes concentriques dans les gris les plus doux. La composition évoque les schémas de circulation, les plans d\'urbanisme — une abstraction géographique posée sur le sol.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie pure de Chine' }, en: { line: 'Orbits that cross without ever touching.', desc: 'Circuit layers circles, half-arches and concentric lines in the softest greys. The composition evokes circulation diagrams, urban plans — a geographic abstraction laid on the floor.', mat: '80% New Zealand Wool · 20% Pure Chinese Silk' }, }, { id: 'lune', image: 'media/tufted-08.jpg', name: 'Lune', fr: { line: 'Des phases lunaires traduites en volumes de laine.', desc: 'Lune compose de grands cercles qui s\'emboîtent et se chevauchent dans une palette de sable, de taupe et d\'ivoire. La douceur des tons tempère l\'amplitude des formes — une présence qui apaise.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'Lunar phases translated into wool volumes.', desc: 'Lune composes large overlapping circles in a palette of sand, taupe and ivory. The softness of the tones tempers the amplitude of the forms — a presence that calms.', mat: '100% New Zealand Wool' }, }, { id: 'dune', image: 'media/tufted-09.jpg', name: 'Dune', fr: { line: 'Les courbes de niveau d\'un paysage silencieux.', desc: 'Dune traduit la topographie en ornement : des lignes concentriques ivoire et taupe tracent les ondulations d\'un terrain invisible. La surface vibre doucement, comme si elle respirait.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie pure de Chine' }, en: { line: 'The contour lines of a silent landscape.', desc: 'Dune translates topography into ornament — ivory and taupe concentric lines trace the undulations of an invisible terrain. The surface vibrates gently, as though breathing.', mat: '80% New Zealand Wool · 20% Pure Chinese Silk' }, }, { id: 'faille', image: 'media/tufted-10.jpg', name: 'Faille', fr: { line: 'Deux plateaux séparés par un silence.', desc: 'Faille trace les lignes de fracture d\'une surface géologique : des fils noirs fins sur ivoire, qui dessinent deux masses opposées séparées par un vide central. La tension est maximale, l\'exécution d\'une retenue absolue.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'Two plateaus separated by silence.', desc: 'Faille traces the fracture lines of a geological surface — fine black threads on ivory, drawing two opposing masses separated by a central void. Maximum tension, executed with absolute restraint.', mat: '100% New Zealand Wool' }, }, ]; /* ════════════════════════════════════════════════════════════════ COLLECTION II — MÉRIDIENNE (eight painterly landscapes) Each piece carries its flat design shot + its in-situ / detail photograph, paired in the same article. ════════════════════════════════════════════════════════════════ */ const MS_MERIDIENNE = [ { id: 'solstice', image: 'media/meridienne-solstice.jpg', room: 'media/meridienne-solstice-room.jpg', roomKind: 'room', name: 'Solstice', fr: { line: 'Midi en plein été — la lumière à son point le plus haut.', desc: 'Solstice traduit la chaleur du soleil au zénith en lignes de niveau. Des ors, des ambres et des sables s\'écoulent autour de rivières bleu pâle, comme une vallée vue du ciel à l\'heure la plus claire. Le velours de laine et de soie capte la lumière et la restitue, mouvante, au fil du jour.', mat: '70% Laine de Nouvelle-Zélande · 30% Soie pure de Chine' }, en: { line: 'High summer noon — light at its highest point.', desc: 'Solstice translates the heat of the zenith sun into contour lines. Gold, amber and sand flow around pale-blue rivers, like a valley seen from above at the brightest hour. The wool-and-silk velvet catches the light and gives it back, shifting through the day.', mat: '70% New Zealand Wool · 30% Pure Chinese Silk' }, }, { id: 'strate', image: 'media/meridienne-strate.jpg', room: 'media/meridienne-strate-room.jpg', roomKind: 'detail', name: 'Strate', fr: { line: 'Les couches de la terre, lues comme une coupe géologique.', desc: 'Strate empile les âges du sol : ivoire, terracotta, lie-de-vin et bleu de roche se déposent en bandes fluides, séparées par un fin contour clair. La composition se lit comme une falaise sédimentaire — chaque strate un temps, chaque couleur une matière. À distance, un paysage ; de près, une coulée de couleur.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie pure de Chine' }, en: { line: 'The layers of the earth, read as a geological section.', desc: 'Strate stacks the ages of the ground: ivory, terracotta, wine and rock-blue settle in fluid bands divided by a fine pale outline. It reads like a sedimentary cliff — each stratum a time, each colour a matter. At distance, a landscape; up close, a flow of colour.', mat: '80% New Zealand Wool · 20% Pure Chinese Silk' }, }, { id: 'dedale', image: 'media/meridienne-dedale.jpg', room: 'media/meridienne-dedale-room.jpg', roomKind: 'room', name: 'Dédale', fr: { line: 'Un seul chemin, qui ne mène qu\'au centre.', desc: 'Dédale enroule un labyrinthe de carrés concentriques dans un vert profond strié d\'ivoire. Le tracé, parfaitement régulier, conduit l\'œil vers un cœur unique — une méditation autant qu\'un motif. Le velours teinté à la main vibre comme une pierre verte, mat et lumineux à la fois.', mat: '85% Laine de Nouvelle-Zélande · 15% Soie pure de Chine' }, en: { line: 'A single path, leading only to the centre.', desc: 'Dédale coils a labyrinth of concentric squares in a deep green streaked with ivory. The perfectly regular line draws the eye toward a single heart — as much a meditation as a motif. The hand-dyed velvet shimmers like green stone, matte and luminous at once.', mat: '85% New Zealand Wool · 15% Pure Chinese Silk' }, }, { id: 'nocturne', image: 'media/meridienne-nocturne.jpg', room: 'media/meridienne-nocturne-room.jpg', roomKind: 'detail', name: 'Nocturne', fr: { line: 'L\'eau qui coule encore, longtemps après la nuit tombée.', desc: 'Nocturne fait courir des rubans ondulants — bleu ciel, sable et ivoire — sur un fond bleu nuit profond. Les courants se croisent et se nouent comme des rivières vues sous la lune. La densité du fond sombre fait ressortir chaque ligne avec l\'éclat d\'un reflet sur l\'eau.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie pure de Chine' }, en: { line: 'Water still flowing, long after nightfall.', desc: 'Nocturne runs undulating ribbons — sky blue, sand and ivory — across a deep midnight ground. Currents cross and knot like rivers seen by moonlight. The density of the dark field lifts every line with the gleam of a reflection on water.', mat: '80% New Zealand Wool · 20% Pure Chinese Silk' }, }, { id: 'helianthe', image: 'media/meridienne-helianthe.jpg', room: 'media/meridienne-helianthe-room.jpg', roomKind: 'detail', name: 'Hélianthe', fr: { line: 'Deux soleils, l\'un clair, l\'autre brûlé.', desc: 'Hélianthe partage le champ en deux : sur l\'ivoire, une fleur d\'or s\'ouvre ; sur l\'orange brûlé, sa jumelle terracotta lui répond. Au centre, un point rouge — le cœur commun. Le motif emprunte au tournesol son geste rayonnant et le fige dans la laine, à la frontière de l\'abstraction.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'Two suns — one bright, one burnt.', desc: 'Hélianthe splits the field in two: on ivory, a golden flower opens; on burnt orange, its terracotta twin answers. At the centre, a single red point — the shared heart. The motif borrows the sunflower\'s radiant gesture and holds it in wool, at the edge of abstraction.', mat: '100% New Zealand Wool' }, }, { id: 'tresse', image: 'media/meridienne-tresse.jpg', room: 'media/meridienne-tresse-room.jpg', roomKind: 'detail', name: 'Tresse', fr: { line: 'Le geste du tissage, agrandi jusqu\'à devenir motif.', desc: 'Tresse décline un entrelacs de capsules caramel et bleu pâle, décalées rang après rang comme les mailles d\'un tressage. Le rythme est hypnotique, presque musical — une trame qui célèbre le geste même du métier. Deux teintes, une infinité de croisements.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'The gesture of weaving, magnified into pattern.', desc: 'Tresse lays an interlace of caramel and pale-blue capsules, offset row by row like the loops of a braid. The rhythm is hypnotic, almost musical — a weave that celebrates the craft\'s own gesture. Two tones, an infinity of crossings.', mat: '100% New Zealand Wool' }, }, { id: 'halo', image: 'media/meridienne-halo.jpg', room: 'media/meridienne-halo-room.jpg', roomKind: 'room', name: 'Halo', fr: { line: 'Un centre, et tout ce qui rayonne autour.', desc: 'Halo organise le champ terracotta en deux mouvements concentriques : un cadre de cadres rectangulaires, et en son cœur un disque cerclé de vert et d\'ivoire. L\'œil va du bord au centre et revient, pris dans une géométrie solaire. Une cible apaisée, un soleil domestique.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'A centre, and all that radiates around it.', desc: 'Halo orders the terracotta field into two concentric movements: a frame of rectangular frames, and at its heart a disc ringed in green and ivory. The eye travels from edge to centre and back, caught in a solar geometry. A calmed target, a domestic sun.', mat: '100% New Zealand Wool' }, }, { id: 'nenuphar', image: 'media/meridienne-nenuphar.jpg', room: 'media/meridienne-nenuphar-room.jpg', roomKind: 'detail', name: 'Nénuphar', fr: { line: 'Deux fleurs posées sur l\'eau, libres de tout cadre.', desc: 'Nénuphar abandonne le rectangle : le tapis épouse une silhouette de nuage, sage et organique. Sur ce galet de laine, deux corolles rayonnent — l\'une dorée, l\'autre cuivrée — autour de cœurs verts, comme deux fleurs flottant à la surface d\'un bassin. La forme découpée fait du sol une mare de lumière.', mat: 'Forme libre · 90% Laine de Nouvelle-Zélande · 10% Soie' }, en: { line: 'Two flowers resting on water, free of any frame.', desc: 'Nénuphar abandons the rectangle: the rug takes the silhouette of a cloud, soft and organic. On this pebble of wool, two corollas radiate — one golden, one copper — around green hearts, like flowers floating on a pond. The cut shape turns the floor into a pool of light.', mat: 'Free form · 90% New Zealand Wool · 10% Silk' }, }, { id: 'ember', image: 'media/ember.jpg', name: 'Ember', fr: { line: 'La lente géologie d\'un escarpement, où la chaleur monte au crépuscule.', desc: 'Ember déploie la chaleur d\'une terre minérale réchauffée par le soleil — une douce topographie de plateaux et de creux qui se révèle à mesure que le jour traverse la pièce. Le velours, sculpté à la main, retient la lumière basse comme une braise.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie de mûrier' }, en: { line: 'The slow geology of an escarpment, where warmth rises at dusk.', desc: 'Ember unfolds the warmth of sun-warmed mineral earth — a soft topography of plateaus and hollows revealed as the day crosses the room. The hand-sculpted pile holds low light like a banked ember.', mat: '80% New Zealand Wool · 20% Mulberry Silk' }, }, { id: 'aurelian', image: 'media/aurelian.jpg', name: 'Aurelian', fr: { line: 'Une présence minérale, traversée par une veine de lumière.', desc: 'Aurelian pose une unique veine de marbre le long d\'un champ ivoire — discrète, jusqu\'à ce que la lumière bouge et que la soie révèle son lustre directionnel. Tout l\'éclat est dans le fil de soie.', mat: '70% Laine · 30% Soie de mûrier' }, en: { line: 'A mineral presence, crossed by a single vein of light.', desc: 'Aurelian sets a single marble vein along an ivory field — quiet, until the light moves and the silk reveals its directional sheen. All the lustre lives in the silk thread.', mat: '70% Wool · 30% Mulberry Silk' }, }, ]; /* Disposition pensée pour la couleur : chaque rangée (grille 3 col.) mêle un ancrage sombre, une lumière et un chaud — lecture vibrante au défilement. Rang 1 : Solstice (or) · Nocturne (nuit) · Strate (terre) Rang 2 : Dédale (vert) · Hélianthe (vif) · Tresse (caramel) Rang 3 : Halo (terracotta) · Nénuphar (sauge) */ const MS_MERIDIENNE_ORDER = ['solstice', 'nocturne', 'strate', 'dedale', 'helianthe', 'tresse', 'halo', 'nenuphar']; const MS_MERIDIENNE_SORTED = MS_MERIDIENNE_ORDER.map((id) => MS_MERIDIENNE.find((p) => p.id === id)); /* ════════════════════════════════════════════════════════════════ COLLECTION III — SONGE (sculpted reliefs: the wave & the round pebbles) ════════════════════════════════════════════════════════════════ */ const MS_SONGE = [ { id: 'albatre', image: 'media/albatre.jpg', room: 'media/albatre-zoom.jpg', roomKind: 'detail', shape: 'round', name: 'Albâtre', fr: { line: 'Un galet d\'albâtre, veiné d\'or.', desc: 'Albâtre compose un paysage de galets crème en relief, parcouru de fines lignes d\'or. Les plages de velours mat et les zones bouclées se répondent en camaïeu ; l\'or n\'apparaît qu\'au mouvement de la lumière.', mat: '90% Laine de Nouvelle-Zélande · 10% fil d\'or' }, en: { line: 'A pebble of alabaster, veined with gold.', desc: 'Albâtre composes a landscape of cream pebbles in relief, run through with fine gold lines. Matte velvet plains answer looped zones in close tone; the gold shows only as the light moves.', mat: '90% New Zealand Wool · 10% gold thread' }, }, { id: 'minuit', image: 'media/minuit.jpg', room: 'media/minuit-zoom.jpg', roomKind: 'detail', shape: 'round', name: 'Minuit', fr: { line: 'La nuit bleue, segmentée d\'or.', desc: 'Minuit découpe un cercle de bleu nuit en plateaux de relief — velours ras, bouclé, côtelé — séparés par des coutures d\'or. Une géométrie nocturne, grave et précieuse, qui se lit comme une carte du ciel.', mat: '90% Laine de Nouvelle-Zélande · 10% fil d\'or' }, en: { line: 'Blue night, segmented in gold.', desc: 'Minuit cuts a circle of midnight blue into plateaus of relief — sheared velvet, loop and rib — parted by seams of gold. A nocturnal geometry, grave and precious, read like a chart of the sky.', mat: '90% New Zealand Wool · 10% gold thread' }, }, { id: 'grenat', image: 'media/grenat.jpg', room: 'media/grenat-zoom.jpg', roomKind: 'detail', shape: 'round', name: 'Grenat', fr: { line: 'Le grenat et l\'écru, taillés en plateaux.', desc: 'Grenat oppose le rouge profond du grenat à l\'écru, en larges plateaux de relief aux textures contraires. Les coutures claires dessinent une géologie douce ; la pièce tient la chaleur d\'un soir d\'hiver.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'Garnet and ecru, cut into plateaus.', desc: 'Grenat sets deep garnet red against ecru in broad plateaus of relief with opposing textures. Pale seams trace a soft geology; the piece holds the warmth of a winter evening.', mat: '100% New Zealand Wool' }, }, ]; /* ════════════════════════════════════════════════════════════════ COLLECTION IV — SINGULIÈRES (singular pieces, chosen one by one) ════════════════════════════════════════════════════════════════ */ const MS_SOLITAIRE = [ { id: 'ember', image: 'media/ember.jpg', shape: 'rect', name: 'Ember', fr: { line: 'La lente géologie d\'un escarpement, où la chaleur monte au crépuscule.', desc: 'Ember déploie la chaleur d\'une terre minérale réchauffée par le soleil — une douce topographie de plateaux et de creux qui se révèle à mesure que le jour traverse la pièce. Le velours, sculpté à la main, retient la lumière basse comme une braise.', mat: '80% Laine de Nouvelle-Zélande · 20% Soie de mûrier' }, en: { line: 'The slow geology of an escarpment, where warmth rises at dusk.', desc: 'Ember unfolds the warmth of sun-warmed mineral earth — a soft topography of plateaus and hollows revealed as the day crosses the room. The hand-sculpted pile holds low light like a banked ember.', mat: '80% New Zealand Wool · 20% Mulberry Silk' }, }, { id: 'aurelian', image: 'media/aurelian.jpg', shape: 'rect', name: 'Aurelian', fr: { line: 'Une présence minérale, traversée par une veine de lumière.', desc: 'Aurelian pose une unique veine de marbre le long d\'un champ ivoire — discrète, jusqu\'à ce que la lumière bouge et que la soie révèle son lustre directionnel. Tout l\'éclat est dans le fil de soie.', mat: '70% Laine · 30% Soie de mûrier' }, en: { line: 'A mineral presence, crossed by a single vein of light.', desc: 'Aurelian sets a single marble vein along an ivory field — quiet, until the light moves and the silk reveals its directional sheen. All the lustre lives in the silk thread.', mat: '70% Wool · 30% Mulberry Silk' }, }, { id: 'aurore', image: 'media/aurore.jpg', room: 'media/aurore-zoom.jpg', roomKind: 'detail', shape: 'rect', name: 'Aurore', fr: { line: 'L\'onde qui monte — lavande, sable et ambre.', desc: 'Aurore fait courir de longues ondulations en bas-relief : des rubans de laine lavande, ivoire et ambre qui s\'élèvent côte à côte comme la lumière du matin sur l\'eau. Le relief, sculpté à la main, capte le jour et le déplace, heure après heure.', mat: '100% Laine de Nouvelle-Zélande' }, en: { line: 'The rising wave — lavender, sand and amber.', desc: 'Aurore runs long undulations in bas-relief: ribbons of lavender, ivory and amber wool rising side by side like morning light on water. The hand-sculpted relief catches the day and moves it, hour by hour.', mat: '100% New Zealand Wool' }, }, ]; /* ── Collections registry ───────────────────────────────────────── */ const MS_COLLECTIONS = [ { id: 'epure', name: 'Épure', cover: 'media/tufted-02.jpg', pieces: MS_EPURE, fr: { kicker: 'Collection I', teaser: 'L\'encre et l\'ivoire. Dix études géométriques, réduites à l\'essentiel.', sub: 'Le trait, l\'arc, la faille', intro: 'Épure réunit dix gestes graphiques tuftés à la main — la ligne, l\'arc, la faille. Ici, le motif se réduit à l\'essentiel : l\'encre et l\'ivoire, le vide et la matière.', intro2: 'Chaque pièce est une étude d\'architecture posée au sol, héritière du Bauhaus et du constructivisme, tempérée par la chaleur de la laine. Rien de superflu ; tout est tension, intervalle, retenue.', palette: 'Encre · Ivoire · Pierre', }, en: { kicker: 'Collection I', teaser: 'Ink and ivory. Ten geometric studies, reduced to the essential.', sub: 'The line, the arc, the fault', intro: 'Épure gathers ten graphic gestures, hand-tufted — the line, the arc, the fault. Here the motif is reduced to its essence: ink and ivory, void and matter.', intro2: 'Each piece is a study in architecture laid on the floor, heir to the Bauhaus and to constructivism, tempered by the warmth of wool. Nothing superfluous; everything is tension, interval, restraint.', palette: 'Ink · Ivory · Stone', }, }, { id: 'meridienne', name: 'Méridienne', cover: 'media/meridienne-solstice-room.jpg', pieces: MS_MERIDIENNE_SORTED, fr: { kicker: 'Collection II', teaser: 'La couleur à son zénith. Huit paysages peints à la laine — soleil, eau, terre.', sub: 'Soleil · Eau · Terre', intro: 'Méridienne est une collection de paysages. Huit créations tuftées main où la couleur atteint son zénith — le soleil de midi, le courant de l\'eau, la strate de la terre, l\'éclosion d\'une fleur.', intro2: 'Là où Épure retient, Méridienne s\'abandonne : les lignes de niveau ondulent, les teintes se fondent dans l\'épaisseur du velours de laine et de soie. Chaque tapis est une peinture que l\'on foule, un fragment de lumière méditerranéenne arrêté dans la matière.', palette: 'Or · Terracotta · Bleu de roche', }, en: { kicker: 'Collection II', teaser: 'Colour at its zenith. Eight landscapes painted in wool — sun, water, earth.', sub: 'Sun · Water · Earth', intro: 'Méridienne is a collection of landscapes. Eight hand-tufted creations where colour reaches its zenith — the noon sun, the current of water, the strata of the earth, the blooming of a flower.', intro2: 'Where Épure restrains, Méridienne lets go: contour lines undulate, hues melt into the depth of wool-and-silk velvet. Each rug is a painting underfoot, a fragment of Mediterranean light held in matter.', palette: 'Gold · Terracotta · Rock blue', }, }, { id: 'songe', name: 'Songe', cover: 'media/minuit.jpg', pieces: MS_SONGE, fr: { kicker: 'Collection III', teaser: 'Des reliefs sculptés à la main — l\'onde, le galet, le cercle.', sub: 'Forme · Relief · Lumière', intro: 'Songe réunit des pièces où la forme devient le sujet : des ondes de laine en bas-relief et des galets ronds veinés d\'or. La matière se sculpte, la lumière y circule.', intro2: 'De l\'onde au cercle parfait, chaque pièce est tuftée et sculptée à la main, puis ciselée pour que le relief projette sa propre ombre.', palette: 'Or · Albâtre · Grenat · Nuit', }, en: { kicker: 'Collection III', teaser: 'Hand-sculpted reliefs — the wave, the pebble, the circle.', sub: 'Form · Relief · Light', intro: 'Songe gathers pieces where form becomes the subject: wool waves in bas-relief and round pebbles veined with gold. The matter is sculpted; light moves across it.', intro2: 'From the wave to the perfect circle, each piece is hand-tufted and sculpted, then carved so the relief casts its own shadow.', palette: 'Gold · Alabaster · Garnet · Night', }, }, { id: 'singulieres', name: 'Singulières', cover: 'media/ember.jpg', pieces: MS_SOLITAIRE, fr: { kicker: 'Collection IV', teaser: 'Trois pièces à part — chacune sa matière, chacune son geste.', sub: 'Pièces singulières', intro: 'Singulières rassemble des pièces qui ne tiennent dans aucune série : un escarpement de laine et de soie, une veine de marbre, une onde lavande. Trois gestes, trois mondes.', intro2: 'Réunies pour leur seule présence, ces pièces se choisissent à l\'unité — nouées ou tuftées à la main, façonnées sur commande à vos dimensions.', palette: 'Sienne · Ivoire · Lavande', }, en: { kicker: 'Collection IV', teaser: 'Three pieces apart — each its own matter, each its own gesture.', sub: 'Singular pieces', intro: 'Singulières gathers pieces that fit no series: an escarpment of wool and silk, a vein of marble, a lavender wave. Three gestures, three worlds.', intro2: 'Brought together for their presence alone, these pieces are chosen one by one — hand-knotted or hand-tufted, made to order to your dimensions.', palette: 'Sienna · Ivory · Lavender', }, }, ]; const MS_TUFTED_PAY = {}; /* { pieceId: { xs,s,m,l } } — paste SumUp/Stripe links to enable direct checkout */ /* Full online payment for Tufted — Stripe Checkout via a Netlify function. The server recomputes the price from the dimensions (never trusts the browser), so the amount is always our own rule. If Stripe is not yet configured (or offline), it falls back to the enquiry form so the site still works. Worldwide cards + Apple/Google Pay are handled by Stripe. */ async function msTuftedCheckout(payload, fallback) { try { const res = await fetch('/.netlify/functions/create-checkout', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); if (!res.ok) throw new Error('checkout ' + res.status); const data = await res.json(); if (data && data.url) { window.location.href = data.url; return; } throw new Error('no url'); } catch (e) { if (fallback) fallback(); } } /* ════════════════════════════════════════════════════════════════ CARD — flat design shot + in-situ / detail photo in one article ════════════════════════════════════════════════════════════════ */ function TuftedCard({ piece, onNav }) { const [size, setSize] = React.useState('m'); const [bespoke, setBespoke] = React.useState(false); const [bw, setBw] = React.useState(200); const [bl, setBl] = React.useState(300); const [hover, setHover] = React.useState(false); const [peek, setPeek] = React.useState(false); /* touch: tap the image to reveal the in-situ shot */ const [open, setOpen] = React.useState(false); const lang = window.__MS_LANG || 'en'; const tx = piece[lang]; const isSilk = tx.mat.includes('Silk') || tx.mat.includes('Soie'); const isRound = piece.shape === 'round'; const sizes = isRound ? MS_TUFTED_ROUND_SIZES : MS_TUFTED_SIZES; const active = Object.assign({}, sizes.find((s) => s.key === size) || sizes[1]); const bArea = Math.max(0, msTuftedArea(bw, bl, isRound ? 'round' : 'rect')); const bValid = isRound ? (bw >= 80) : (bw >= 80 && bl >= 80); /* floor: 80 cm */ const hasSecond = !!piece.room; const secondLabel = piece.roomKind === 'room' ? (lang === 'fr' ? 'En situation' : 'In situ') : (lang === 'fr' ? 'Détail de la matière' : 'Material detail'); return (
MS_CAN_HOVER && setHover(true)} onMouseLeave={() => MS_CAN_HOVER && setHover(false)}> {/* Primary image — flat design; on hover (desktop) or tap (touch), cross-fades to the in-situ / detail shot */} {(() => { const reveal = hasSecond && (hover || peek); return (
setPeek((p) => !p) : undefined} style={{ position: 'relative', aspectRatio: '4/5', overflow: 'hidden', background: C('stone-200'), cursor: hasSecond && !MS_CAN_HOVER ? 'pointer' : 'default' }}>
{hasSecond && (
)} {hasSecond && (
{secondLabel}
)} {/* Touch affordance: a tap hint shown only on touch devices, hidden once revealed */} {hasSecond && !MS_CAN_HOVER && (
{piece.roomKind === 'room' ? (lang === 'fr' ? 'Voir en situation' : 'See in situ') : (lang === 'fr' ? 'Voir le détail' : 'See detail')}
)}
); })()} {/* Info */}

{piece.name}

{tx.line}

{/* The work — artistic statement + the paired photograph */} {open && (

{tx.desc}

{hasSecond && (
{secondLabel}
)}
)}
{tx.mat}
{lang === 'fr' ? 'Fabriqué sur commande' : 'Made to order'}
{/* Size selector */}
{sizes.map((s) => ( ))}
{/* Order — by enquiry (no price shown; made to order) */} {/* Bespoke — choose any dimensions, priced by the square metre */}
{bespoke && ReactDOM.createPortal((
setBespoke(false)} style={{ position: 'fixed', inset: 0, zIndex: 9999, background: 'rgba(21,17,12,0.55)', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '6vw', WebkitBackdropFilter: 'blur(2px)', backdropFilter: 'blur(2px)', }}>
e.stopPropagation()} style={{ background: C('canvas'), maxWidth: 470, width: '100%', padding: 'clamp(30px,4vw,46px)', position: 'relative', boxShadow: '0 30px 90px rgba(21,17,12,0.32)', }}>
{lang === 'fr' ? 'Sur mesure' : 'Made to measure'}

{piece.name}

{tx.mat}
{isRound ? (
) : (
×
)}
{bArea.toFixed(2)} m²
{bValid ? (

{lang === 'fr' ? 'Fabrication à la main' : 'Handmade to order'}

) : (
{lang === 'fr' ? 'Format minimum' : 'Minimum format'}

{lang === 'fr' ? 'Nos pièces sur mesure ne sont jamais réalisées en deçà de 80 × 80 cm — le plus intime des formats que façonne l’atelier, sous lequel l’équilibre du dessin ne saurait être tenu.' : 'Our bespoke pieces are never made below 80 × 80 cm — the most intimate format the atelier will craft, beneath which the balance of the design cannot be honoured.'}

{lang === 'fr' ? 'Commander' : 'Order'}
)}
), document.body)}
); } /* ════════════════════════════════════════════════════════════════ LANDING — the two collections, presented as full-width chapters ════════════════════════════════════════════════════════════════ */ function TuftedLanding({ onOpen, onNav }) { const lang = window.__MS_LANG || 'en'; return (
{/* Hero */}
Maison Silya · Atelier

{lang === 'fr' ? 'Tufted' : 'Tufted'}

{lang === 'fr' ? 'Le tufté est le terrain d\'expérimentation de la maison : la laine de Nouvelle-Zélande, parfois rehaussée de soie, tirée à la main pour donner corps au motif. Deux collections en explorent les extrêmes — la retenue graphique d\'Épure, la couleur abondante de Méridienne.' : 'Tufting is the house\'s field of experiment: New Zealand wool, sometimes raised with silk, hand-pulled to give the motif body. Two collections explore its extremes — the graphic restraint of Épure, the abundant colour of Méridienne.'}

{/* Collection chapters */}
{MS_COLLECTIONS.map((coll, i) => { const ct = coll[lang]; return ( ); })}
); } /* ════════════════════════════════════════════════════════════════ COLLECTION VIEW — artistic statement + the pieces ════════════════════════════════════════════════════════════════ */ function TuftedCollection({ coll, onBack, onNav }) { const lang = window.__MS_LANG || 'en'; const ct = coll[lang]; return (
{/* Hero — the collection's artistic statement */}
{ct.kicker} · {coll.pieces.length} {lang === 'fr' ? 'pièces' : 'pieces'}

{coll.name}

{ct.intro}

{ct.intro2}

{[ [lang === 'fr' ? 'Construction' : 'Construction', lang === 'fr' ? 'Tufted main' : 'Hand-tufted'], [lang === 'fr' ? 'Palette' : 'Palette', ct.palette], ].map(([k, v]) => (
{k} {v}
))}
{/* Divider */}
{/* Grid */}
{coll.pieces.map((p) => )}
{/* CTA */}
{lang === 'fr' ? 'Sur mesure' : 'Bespoke'}

{lang === 'fr' ? 'Chaque pièce existe en dimensions et coloris sur mesure.' : 'Every piece is available in bespoke dimensions and colourways.'}

{lang === 'fr' ? 'La maison travaille avec les architectes d\'intérieur et les particuliers pour adapter chaque motif à l\'espace.' : 'The house works with interior architects and private clients to adapt each motif to the space.'}

onNav('contact')}> {lang === 'fr' ? 'Écrire au studio' : 'Write to the studio'}
); } /* ════════════════════════════════════════════════════════════════ SCREEN — landing ⇄ collection (internal state; route stays "tufted") ════════════════════════════════════════════════════════════════ */ function TuftedScreen({ onNav }) { const [openId, setOpenId] = React.useState(() => { const m = (location.hash || '').match(/tufted[:/](\w+)/); return m ? m[1] : null; }); const coll = MS_COLLECTIONS.find((c) => c.id === openId) || null; // Keep internal view in sync with the hash (e.g. header "Tufted" → back to landing). React.useEffect(() => { const onHash = () => { const m = (location.hash || '').match(/tufted[:/](\w+)/); setOpenId(m ? m[1] : null); }; window.addEventListener('hashchange', onHash); return () => window.removeEventListener('hashchange', onHash); }, []); const goTo = (id) => { setOpenId(id); if (id) { if (location.hash !== '#tufted/' + id) location.hash = 'tufted/' + id; } else if (location.hash !== '#tufted') location.hash = 'tufted'; const sc = document.getElementById('ms-scroll'); requestAnimationFrame(() => { if (sc) sc.scrollTop = 0; }); }; return coll ? goTo(null)} onNav={onNav} /> : ; } Object.assign(window, { TuftedScreen, TuftedLanding, TuftedCollection, TuftedCard });