overhaul
This commit is contained in:
+14
-15
@@ -1,21 +1,14 @@
|
||||
@font-face {
|
||||
font-family: "Instrument Serif";
|
||||
src: url("/fonts/instrument-serif-regular.ttf") format("truetype");
|
||||
font-weight: 400;
|
||||
font-family: "Roboto Condensed";
|
||||
src: url("/fonts/roboto-condensed.woff2") format("woff2");
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Instrument Serif";
|
||||
src: url("/fonts/instrument-serif-italic.ttf") format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "DM Sans";
|
||||
src: url("/fonts/dm-sans.woff2") format("woff2");
|
||||
font-weight: 100 1000;
|
||||
font-family: "Noto Sans";
|
||||
src: url("/fonts/noto-sans.woff2") format("woff2");
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@@ -26,8 +19,10 @@
|
||||
--line: #d9d9cf;
|
||||
--wash: #ecebe4;
|
||||
--accent: #8f725c;
|
||||
--serif: "Instrument Serif", Georgia, serif;
|
||||
--sans: "DM Sans", Arial, sans-serif;
|
||||
--industrial: #496678;
|
||||
--industrial-deep: #273f4d;
|
||||
--serif: "Roboto Condensed", "Arial Narrow", sans-serif;
|
||||
--sans: "Noto Sans", Arial, sans-serif;
|
||||
--mono: "Courier New", monospace;
|
||||
--page-gutter: clamp(20px, 4vw, 72px);
|
||||
color-scheme: light;
|
||||
@@ -48,6 +43,10 @@ body {
|
||||
margin: 0;
|
||||
min-width: 320px;
|
||||
}
|
||||
em {
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
}
|
||||
button,
|
||||
input,
|
||||
textarea,
|
||||
|
||||
@@ -10,13 +10,15 @@ export default function Gallery({ preview = false }) {
|
||||
<section className="gallery" id="developments" tabIndex={-1}>
|
||||
<SectionHeading
|
||||
centered
|
||||
label="Selected developments"
|
||||
label={
|
||||
preview ? "Featured fabric developments" : "Selected developments"
|
||||
}
|
||||
title={
|
||||
preview ? (
|
||||
<>
|
||||
Structure changes
|
||||
What we make.
|
||||
<br />
|
||||
<em>everything.</em>
|
||||
<em>What we can develop.</em>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
@@ -29,12 +31,12 @@ export default function Gallery({ preview = false }) {
|
||||
>
|
||||
<p className="gallery__intro">
|
||||
{preview
|
||||
? "From subtle surface structures to more expressive knitted textures, different yarn combinations and machine setups produce entirely different fabric characteristics."
|
||||
? "A selection of knitted structures showing how yarn, composition and machine setup shape the final fabric character."
|
||||
: "Selected developments are processed separately as reference samples to explore how a construction can translate after dyeing and finishing. RRS commercially manufactures greige fabric only."}
|
||||
</p>
|
||||
{preview && (
|
||||
<Action to="/fabrics#developments" variant="outline">
|
||||
View developments
|
||||
Explore all fabrics
|
||||
</Action>
|
||||
)}
|
||||
</SectionHeading>
|
||||
|
||||
+13
-30
@@ -31,7 +31,9 @@
|
||||
top: 10px;
|
||||
}
|
||||
.site-header {
|
||||
border-top: 4px solid var(--industrial);
|
||||
border-bottom: 1px solid var(--line);
|
||||
background: #faf9f5;
|
||||
}
|
||||
.site-header__inner {
|
||||
display: flex;
|
||||
@@ -44,27 +46,11 @@
|
||||
.brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
text-decoration: none;
|
||||
color: var(--ink);
|
||||
}
|
||||
.brand__mark {
|
||||
font-family: var(--serif);
|
||||
font-size: 42px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.065em;
|
||||
}
|
||||
.brand__period {
|
||||
color: var(--accent);
|
||||
}
|
||||
.brand__name {
|
||||
border-left: 1px solid var(--line);
|
||||
padding-left: 16px;
|
||||
font-size: 9px;
|
||||
line-height: 1.65;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.12em;
|
||||
.brand__logo {
|
||||
display: block;
|
||||
width: 92px;
|
||||
height: auto;
|
||||
}
|
||||
.site-nav {
|
||||
display: flex;
|
||||
@@ -100,15 +86,15 @@
|
||||
gap: 30px;
|
||||
margin-left: 45px;
|
||||
padding: 12px 20px;
|
||||
border: 1px solid var(--ink);
|
||||
border: 1px solid var(--industrial-deep);
|
||||
border-radius: 30px;
|
||||
color: var(--ink);
|
||||
background: var(--industrial-deep);
|
||||
color: var(--paper);
|
||||
text-decoration: none;
|
||||
font-size: 11px;
|
||||
}
|
||||
.site-nav__contact:hover {
|
||||
background: var(--ink);
|
||||
color: var(--paper);
|
||||
background: var(--industrial);
|
||||
}
|
||||
.site-header__toggle {
|
||||
display: none;
|
||||
@@ -209,7 +195,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 420px;
|
||||
background: var(--ink);
|
||||
background: var(--industrial-deep);
|
||||
color: var(--paper);
|
||||
padding: 64px;
|
||||
border-radius: 6px;
|
||||
@@ -282,11 +268,8 @@
|
||||
flex-wrap: wrap;
|
||||
gap: 0;
|
||||
}
|
||||
.brand__mark {
|
||||
font-size: 35px;
|
||||
}
|
||||
.brand__name {
|
||||
font-size: 8px;
|
||||
.brand__logo {
|
||||
width: 78px;
|
||||
}
|
||||
.site-header__toggle {
|
||||
display: flex;
|
||||
|
||||
@@ -7,14 +7,13 @@ import "./Layout.css";
|
||||
function Brand() {
|
||||
return (
|
||||
<Link className="brand" to="/" aria-label="RRS home">
|
||||
<span className="brand__mark">
|
||||
RRS<span className="brand__period">.</span>
|
||||
</span>
|
||||
<span className="brand__name">
|
||||
Radhe Radhe
|
||||
<br />
|
||||
Synthetics
|
||||
</span>
|
||||
<img
|
||||
className="brand__logo"
|
||||
src="/images/RRSLOGO.png"
|
||||
alt="Radhe Radhe Synthetics"
|
||||
width="1024"
|
||||
height="809"
|
||||
/>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
@@ -68,7 +67,7 @@ function Header() {
|
||||
to="/contact#whatsapp"
|
||||
onClick={closeMenu}
|
||||
>
|
||||
Let's talk <Arrow diagonal />
|
||||
Request a quote <Arrow diagonal />
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
@@ -93,7 +92,7 @@ function Footer() {
|
||||
))}
|
||||
</nav>
|
||||
<div className="site-footer__contact">
|
||||
<span className="site-footer__label">Start a conversation</span>
|
||||
<span className="site-footer__label">Commercial enquiries</span>
|
||||
<Link className="site-footer__link" to="/contact#whatsapp">
|
||||
WhatsApp <Arrow diagonal />
|
||||
</Link>
|
||||
|
||||
+185
-62
@@ -2,76 +2,124 @@
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
overflow: hidden;
|
||||
padding: clamp(24px, 3.5vw, 56px);
|
||||
color: #f5f3ee;
|
||||
background: #24231e;
|
||||
transition:
|
||||
opacity 650ms cubic-bezier(0.76, 0, 0.24, 1),
|
||||
clip-path 650ms cubic-bezier(0.76, 0, 0.24, 1);
|
||||
clip-path: inset(0);
|
||||
color: var(--ink);
|
||||
background: var(--paper);
|
||||
}
|
||||
.loader--closing {
|
||||
opacity: 0;
|
||||
clip-path: inset(0 0 100% 0);
|
||||
pointer-events: none;
|
||||
}
|
||||
.loader__canvas,
|
||||
.loader__veil {
|
||||
.loader__scene {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.loader__canvas {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
transition: opacity 180ms ease-out;
|
||||
}
|
||||
.loader__canvas[data-ready="true"] {
|
||||
opacity: 1;
|
||||
}
|
||||
.loader__veil {
|
||||
background: linear-gradient(90deg, #17171238, transparent 45%, #17171238);
|
||||
}
|
||||
.loader__topline,
|
||||
.loader__center {
|
||||
position: relative;
|
||||
.loader__yarns {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
width: min(72vw, 920px);
|
||||
height: 34%;
|
||||
overflow: visible;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.loader__topline {
|
||||
.loader__yarns path {
|
||||
fill: none;
|
||||
stroke: var(--industrial);
|
||||
stroke-width: 5;
|
||||
stroke-linecap: round;
|
||||
vector-effect: non-scaling-stroke;
|
||||
opacity: 0;
|
||||
stroke-dasharray: 1200;
|
||||
stroke-dashoffset: 1200;
|
||||
animation: yarn-feed 780ms 480ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
||||
}
|
||||
.loader__yarns path:nth-child(2),
|
||||
.loader__yarns path:nth-child(6) {
|
||||
stroke: var(--accent);
|
||||
animation-delay: 580ms;
|
||||
}
|
||||
.loader__yarns path:nth-child(3),
|
||||
.loader__yarns path:nth-child(5) {
|
||||
animation-delay: 660ms;
|
||||
}
|
||||
.loader__yarns path:nth-child(4) {
|
||||
stroke: var(--ink);
|
||||
stroke-width: 6;
|
||||
animation-delay: 540ms;
|
||||
}
|
||||
.loader__machine {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
inset: 5% 0 7%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
clip-path: inset(0 0 100%);
|
||||
animation: machine-reveal 900ms 680ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
||||
}
|
||||
.loader__machine-image {
|
||||
display: block;
|
||||
width: auto;
|
||||
height: min(84vh, 1050px);
|
||||
max-width: 84vw;
|
||||
object-fit: contain;
|
||||
filter: grayscale(1) contrast(1.08);
|
||||
transform: scale(1.04);
|
||||
animation: machine-colour 850ms 1050ms ease-out forwards;
|
||||
}
|
||||
.loader__brand {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
left: 50%;
|
||||
bottom: clamp(18px, 2.2vw, 36px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 18px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.16em;
|
||||
text-transform: uppercase;
|
||||
padding: 10px 18px;
|
||||
border: 1px solid #282a2324;
|
||||
border-radius: 999px;
|
||||
background: #f5f3eee8;
|
||||
backdrop-filter: blur(8px);
|
||||
opacity: 0;
|
||||
transform: translate(-50%, 14px);
|
||||
animation: brand-arrive 450ms 1500ms ease-out forwards;
|
||||
}
|
||||
.loader__center {
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
text-align: center;
|
||||
.loader__logo {
|
||||
width: 82px;
|
||||
height: auto;
|
||||
}
|
||||
.loader__eyebrow {
|
||||
margin: 0 0 18px;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.loader__title {
|
||||
.loader__message {
|
||||
margin: 0;
|
||||
padding-left: 18px;
|
||||
border-left: 1px solid var(--line);
|
||||
font-family: var(--serif);
|
||||
font-size: clamp(58px, 8.5vw, 132px);
|
||||
font-weight: 400;
|
||||
line-height: 0.84;
|
||||
letter-spacing: -0.055em;
|
||||
font-size: 18px;
|
||||
line-height: 1.1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.loader__title em {
|
||||
font-weight: 400;
|
||||
.loader__handoff {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
inset: 0;
|
||||
background:
|
||||
repeating-linear-gradient(115deg, transparent 0 8px, #f5f3ee13 8px 9px),
|
||||
var(--industrial-deep);
|
||||
transform: translateX(-101%);
|
||||
will-change: transform;
|
||||
}
|
||||
.loader--covering {
|
||||
pointer-events: none;
|
||||
}
|
||||
.loader--covering .loader__handoff {
|
||||
animation: handoff-cover 450ms cubic-bezier(0.76, 0, 0.24, 1) forwards;
|
||||
}
|
||||
.loader--revealing {
|
||||
background: transparent;
|
||||
pointer-events: none;
|
||||
}
|
||||
.loader--revealing .loader__scene {
|
||||
opacity: 0;
|
||||
}
|
||||
.loader--revealing .loader__handoff {
|
||||
transform: translateX(0);
|
||||
animation: handoff-reveal 600ms cubic-bezier(0.76, 0, 0.24, 1) forwards;
|
||||
}
|
||||
.loader__announcement {
|
||||
position: absolute;
|
||||
@@ -81,16 +129,91 @@
|
||||
clip-path: inset(50%);
|
||||
white-space: nowrap;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.loader__title {
|
||||
font-size: clamp(54px, 19vw, 86px);
|
||||
@keyframes yarn-feed {
|
||||
0% {
|
||||
opacity: 0;
|
||||
stroke-dashoffset: 1200;
|
||||
}
|
||||
.loader__topline span:last-child {
|
||||
display: none;
|
||||
4% {
|
||||
opacity: 0.82;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.82;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
@keyframes machine-reveal {
|
||||
to {
|
||||
clip-path: inset(0);
|
||||
}
|
||||
}
|
||||
@keyframes machine-colour {
|
||||
to {
|
||||
filter: grayscale(0) contrast(1);
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
@keyframes brand-arrive {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
}
|
||||
@keyframes handoff-cover {
|
||||
to {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
@keyframes handoff-reveal {
|
||||
to {
|
||||
transform: translateX(101%);
|
||||
}
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.loader__yarns {
|
||||
width: 108vw;
|
||||
height: 32%;
|
||||
}
|
||||
.loader__machine {
|
||||
inset: 9% 0 12%;
|
||||
}
|
||||
.loader__machine-image {
|
||||
width: 98vw;
|
||||
height: auto;
|
||||
max-width: none;
|
||||
}
|
||||
.loader__brand {
|
||||
bottom: 22px;
|
||||
gap: 11px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
.loader__logo {
|
||||
width: 66px;
|
||||
}
|
||||
.loader__message {
|
||||
padding-left: 11px;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.loader {
|
||||
transition: none;
|
||||
.loader__yarns,
|
||||
.loader__handoff {
|
||||
display: none;
|
||||
}
|
||||
.loader__machine,
|
||||
.loader__machine-image,
|
||||
.loader__brand {
|
||||
animation: none;
|
||||
}
|
||||
.loader__machine {
|
||||
clip-path: inset(0);
|
||||
}
|
||||
.loader__machine-image {
|
||||
filter: none;
|
||||
transform: none;
|
||||
}
|
||||
.loader__brand {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+46
-80
@@ -1,106 +1,72 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import weaveShader from "../shaders/loader.wgsl?raw";
|
||||
import { useEffect, useState } from "react";
|
||||
import "./Loader.css";
|
||||
|
||||
export default function Loader() {
|
||||
const canvasRef = useRef(null);
|
||||
const [phase, setPhase] = useState("active");
|
||||
|
||||
useEffect(() => {
|
||||
const reducedMotion = window.matchMedia(
|
||||
"(prefers-reduced-motion: reduce)",
|
||||
).matches;
|
||||
const closeTimer = window.setTimeout(
|
||||
() => setPhase("closing"),
|
||||
reducedMotion ? 0 : 1900,
|
||||
const coveringTimer = window.setTimeout(
|
||||
() => setPhase("covering"),
|
||||
reducedMotion ? 0 : 2100,
|
||||
);
|
||||
const revealTimer = window.setTimeout(
|
||||
() => setPhase("revealing"),
|
||||
reducedMotion ? 25 : 2550,
|
||||
);
|
||||
const removeTimer = window.setTimeout(
|
||||
() => setPhase("hidden"),
|
||||
reducedMotion ? 50 : 2550,
|
||||
reducedMotion ? 50 : 3150,
|
||||
);
|
||||
return () => {
|
||||
window.clearTimeout(closeTimer);
|
||||
window.clearTimeout(coveringTimer);
|
||||
window.clearTimeout(revealTimer);
|
||||
window.clearTimeout(removeTimer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (phase !== "active") return undefined;
|
||||
let active = true;
|
||||
let gpu;
|
||||
let loop;
|
||||
let unsubscribeResize;
|
||||
|
||||
async function renderWeave() {
|
||||
try {
|
||||
const { clock, effect, frameLoop, init, surface } = await import(
|
||||
"vgpu"
|
||||
);
|
||||
gpu = await init({ powerPreference: "low-power" });
|
||||
if (!active) return gpu.dispose();
|
||||
|
||||
const target = surface(gpu, canvasRef.current, { dpr: [1, 1.5] });
|
||||
const weave = effect(gpu, weaveShader, {
|
||||
set: { params: { time: 0, progress: 0, aspect: 1, padding: 0 } },
|
||||
});
|
||||
const timer = clock(gpu);
|
||||
unsubscribeResize = target.onResize(({ width, height }) => {
|
||||
weave.set({ params: { aspect: width / height } });
|
||||
});
|
||||
let presented = false;
|
||||
loop = frameLoop(
|
||||
gpu,
|
||||
(frame) => {
|
||||
weave.set({
|
||||
params: {
|
||||
time: timer.time,
|
||||
progress: Math.min(1.2, timer.time / 1.8),
|
||||
},
|
||||
});
|
||||
frame.pass(target, weave);
|
||||
if (!presented) {
|
||||
presented = true;
|
||||
requestAnimationFrame(() => {
|
||||
if (active) canvasRef.current.dataset.ready = "true";
|
||||
});
|
||||
}
|
||||
},
|
||||
{ fps: 30 },
|
||||
);
|
||||
} catch {
|
||||
// A flat background remains when WebGPU is unavailable.
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.matchMedia("(prefers-reduced-motion: reduce)").matches)
|
||||
renderWeave();
|
||||
|
||||
return () => {
|
||||
active = false;
|
||||
loop?.stop();
|
||||
unsubscribeResize?.();
|
||||
gpu?.dispose();
|
||||
};
|
||||
}, [phase]);
|
||||
|
||||
if (phase === "hidden") return null;
|
||||
|
||||
return (
|
||||
<div className={`loader loader--${phase}`} aria-live="polite">
|
||||
<canvas className="loader__canvas" ref={canvasRef} aria-hidden="true" />
|
||||
<div className="loader__veil" aria-hidden="true" />
|
||||
<div className="loader__topline">
|
||||
<span>RRS / 1987</span>
|
||||
<span>Surat, India</span>
|
||||
</div>
|
||||
<div className="loader__center">
|
||||
<p className="loader__eyebrow">Preparing the loom</p>
|
||||
<p className="loader__title">
|
||||
From yarn
|
||||
<br />
|
||||
<em>to structure.</em>
|
||||
</p>
|
||||
<div className="loader__scene">
|
||||
<svg
|
||||
className="loader__yarns"
|
||||
viewBox="0 0 1000 430"
|
||||
preserveAspectRatio="none"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path pathLength="1" d="M60 0 C90 150 120 285 180 430" />
|
||||
<path pathLength="1" d="M205 0 C230 155 255 310 285 430" />
|
||||
<path pathLength="1" d="M350 0 C365 170 380 320 395 430" />
|
||||
<path pathLength="1" d="M500 0 L500 430" />
|
||||
<path pathLength="1" d="M650 0 C635 170 620 320 605 430" />
|
||||
<path pathLength="1" d="M795 0 C770 155 745 310 715 430" />
|
||||
<path pathLength="1" d="M940 0 C910 150 880 285 820 430" />
|
||||
</svg>
|
||||
<div className="loader__machine" aria-hidden="true">
|
||||
<img
|
||||
className="loader__machine-image"
|
||||
src="/images/knitting-machine.webp"
|
||||
alt=""
|
||||
width="1113"
|
||||
height="1316"
|
||||
/>
|
||||
</div>
|
||||
<div className="loader__brand">
|
||||
<img
|
||||
className="loader__logo"
|
||||
src="/images/RRSLOGO.png"
|
||||
alt="Radhe Radhe Synthetics"
|
||||
width="1024"
|
||||
height="809"
|
||||
/>
|
||||
<p className="loader__message">From yarn to repeat production.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="loader__handoff" aria-hidden="true" />
|
||||
<span className="loader__announcement">
|
||||
Loading Radhe Radhe Synthetics
|
||||
</span>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 32px;
|
||||
border-block: 1px solid var(--line);
|
||||
padding: 42px 0;
|
||||
margin-top: 78px;
|
||||
padding: 38px 0 42px;
|
||||
margin-top: 42px;
|
||||
}
|
||||
.stats__item {
|
||||
min-width: 0;
|
||||
@@ -14,7 +14,7 @@
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 1.6;
|
||||
color: var(--muted);
|
||||
color: var(--industrial);
|
||||
}
|
||||
.stats__value {
|
||||
font-family: var(--serif);
|
||||
|
||||
+15
-10
@@ -12,25 +12,30 @@ export const company = Object.freeze({
|
||||
export const navigation = [
|
||||
{ to: "/", label: "Home" },
|
||||
{ to: "/fabrics", label: "Fabrics" },
|
||||
{ to: "/about", label: "About" },
|
||||
{ to: "/about", label: "Manufacturing" },
|
||||
{ to: "/contact", label: "Contact" },
|
||||
];
|
||||
|
||||
export const capabilities = [
|
||||
{
|
||||
title: "Develop",
|
||||
subtitle: "Continuous fabric development",
|
||||
text: "Different structures call for different yarns, blends and machine configurations. RRS continually develops new knitted constructions for evolving apparel requirements.",
|
||||
title: "01 · Develop",
|
||||
subtitle: "Define the construction",
|
||||
text: "The requirement begins with the intended application, yarn, blend, structure and fabric character.",
|
||||
},
|
||||
{
|
||||
title: "Repeat",
|
||||
subtitle: "Consistency in bulk production",
|
||||
text: "A successful development must remain dependable when production scales. RRS focuses on maintaining repeatability and quality across bulk manufacturing.",
|
||||
title: "02 · Configure",
|
||||
subtitle: "Match yarn to machine",
|
||||
text: "Machine configuration and yarn selection are aligned to the construction being developed.",
|
||||
},
|
||||
{
|
||||
title: "Manufacture",
|
||||
subtitle: "Extensive circular-knitting capability",
|
||||
text: "A broad range of circular-knitting configurations allows RRS to work across different structures, materials and fabric characteristics.",
|
||||
title: "03 · Manufacture",
|
||||
subtitle: "Circular knitting at scale",
|
||||
text: "The approved construction moves into greige production across the appropriate circular-knitting setup.",
|
||||
},
|
||||
{
|
||||
title: "04 · Repeat",
|
||||
subtitle: "Maintain bulk consistency",
|
||||
text: "Successful developments are reproduced with repeatability across commercial manufacturing quantities.",
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
+5
-5
@@ -81,12 +81,12 @@ export default function About() {
|
||||
return (
|
||||
<>
|
||||
<PageHero
|
||||
label="About RRS"
|
||||
label="Manufacturing at RRS"
|
||||
title={
|
||||
<>
|
||||
Built around
|
||||
<br />
|
||||
<em>the fabric.</em>
|
||||
<em>repeatable production.</em>
|
||||
</>
|
||||
}
|
||||
>
|
||||
@@ -100,12 +100,12 @@ export default function About() {
|
||||
<section className="philosophy">
|
||||
<SectionHeading
|
||||
centered
|
||||
label="Our philosophy"
|
||||
label="Our manufacturing discipline"
|
||||
title={
|
||||
<>
|
||||
Consistency
|
||||
Develop with curiosity.
|
||||
<br />
|
||||
<em>and curiosity.</em>
|
||||
<em>Produce with consistency.</em>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -52,19 +52,19 @@ export default function Contact() {
|
||||
return (
|
||||
<>
|
||||
<PageHero
|
||||
label="Contact RRS"
|
||||
label="Request a quote"
|
||||
title={
|
||||
<>
|
||||
Let’s talk
|
||||
Bring us your
|
||||
<br />
|
||||
<em>fabric.</em>
|
||||
<em>fabric requirement.</em>
|
||||
</>
|
||||
}
|
||||
texture="structured"
|
||||
>
|
||||
<p>
|
||||
Whether you’re discussing an existing requirement, bulk production or
|
||||
a new fabric construction, connect directly with RRS.
|
||||
Share an existing requirement, bulk quantity or new construction with
|
||||
RRS and begin a direct manufacturing conversation.
|
||||
</p>
|
||||
</PageHero>
|
||||
<section className="whatsapp" id="whatsapp" tabIndex={-1}>
|
||||
|
||||
+19
-12
@@ -4,9 +4,8 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
min-height: 590px;
|
||||
margin-top: 24px;
|
||||
border-radius: 7px;
|
||||
min-height: 768px;
|
||||
margin-inline: calc(0px - var(--page-gutter));
|
||||
color: var(--paper);
|
||||
background: var(--ink);
|
||||
}
|
||||
@@ -21,11 +20,14 @@
|
||||
.home-hero__shade {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: #1419108f;
|
||||
background:
|
||||
linear-gradient(90deg, #132630e8 0%, #1f3239a8 54%, #17262f73 100%),
|
||||
linear-gradient(0deg, #111b22b5 0%, transparent 45%);
|
||||
}
|
||||
.home-hero__content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 900px;
|
||||
padding: 65px 62px 90px;
|
||||
}
|
||||
.home-hero__title {
|
||||
@@ -51,8 +53,8 @@
|
||||
.home-hero__bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 32px;
|
||||
right: 32px;
|
||||
left: var(--page-gutter);
|
||||
right: var(--page-gutter);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
@@ -128,6 +130,9 @@
|
||||
padding: 58px 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.process__item:nth-child(even) {
|
||||
background: linear-gradient(90deg, transparent, #49667808, transparent);
|
||||
}
|
||||
.process__item:nth-child(even) .process__visual {
|
||||
order: -1;
|
||||
}
|
||||
@@ -137,9 +142,12 @@
|
||||
}
|
||||
.process__verb {
|
||||
margin: 0 0 24px;
|
||||
font-size: 14px;
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: var(--muted);
|
||||
color: var(--industrial);
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.process__title {
|
||||
margin: 0 0 22px;
|
||||
@@ -175,19 +183,18 @@
|
||||
}
|
||||
@media (max-width: 760px) {
|
||||
.home-hero {
|
||||
margin-top: 18px;
|
||||
min-height: 560px;
|
||||
}
|
||||
.home-hero__content {
|
||||
padding: 42px 26px 130px;
|
||||
padding: 42px var(--page-gutter) 130px;
|
||||
}
|
||||
.home-hero__title {
|
||||
font-size: clamp(44px, 8.9vw, 68px);
|
||||
margin-top: 32px;
|
||||
}
|
||||
.home-hero__bottom {
|
||||
left: 26px;
|
||||
right: 26px;
|
||||
left: var(--page-gutter);
|
||||
right: var(--page-gutter);
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 15px 0;
|
||||
|
||||
+23
-31
@@ -1,35 +1,22 @@
|
||||
import { Link } from "react-router-dom";
|
||||
import { capabilities, company } from "../data";
|
||||
import { capabilities } from "../data";
|
||||
import {
|
||||
Action,
|
||||
Arrow,
|
||||
Eyebrow,
|
||||
SectionHeading,
|
||||
Textile,
|
||||
WhatsAppAction,
|
||||
} from "../components/Primitives";
|
||||
import { ContactBanner } from "../components/Layout";
|
||||
import Gallery from "../components/Gallery";
|
||||
import Stats from "../components/Stats";
|
||||
import "./Home.css";
|
||||
|
||||
const processItems = [
|
||||
{
|
||||
...capabilities[0],
|
||||
image: "fine",
|
||||
href: "/fabrics#developments",
|
||||
},
|
||||
{
|
||||
...capabilities[2],
|
||||
image: "structured",
|
||||
href: "/fabrics#circular-knitting",
|
||||
},
|
||||
{
|
||||
...capabilities[1],
|
||||
image: "natural",
|
||||
href: "/fabrics#production",
|
||||
},
|
||||
];
|
||||
const processItems = capabilities.map((capability, index) => ({
|
||||
...capability,
|
||||
image: ["fine", "natural", "structured", "fine"][index],
|
||||
href: index < 2 ? "/fabrics#applications" : "/fabrics#production",
|
||||
}));
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
@@ -45,29 +32,35 @@ export default function Home() {
|
||||
/>
|
||||
<div className="home-hero__shade" />
|
||||
<div className="home-hero__content">
|
||||
<Eyebrow>Circular knitted fabrics · RRS</Eyebrow>
|
||||
<Eyebrow>Specialist circular-knitting manufacturer · RRS</Eyebrow>
|
||||
<h1 className="home-hero__title">
|
||||
Built to develop.
|
||||
<br />
|
||||
<em>Built to repeat.</em>
|
||||
</h1>
|
||||
<p className="home-hero__description">{company.description}</p>
|
||||
<p className="home-hero__description">
|
||||
Greige knitted fabrics developed around yarn, structure and
|
||||
application—then manufactured for consistent commercial supply.
|
||||
</p>
|
||||
<div className="home-hero__actions">
|
||||
<Action to="/fabrics" variant="light">
|
||||
Explore our fabrics
|
||||
</Action>
|
||||
<WhatsAppAction variant="ghost">Talk to RRS</WhatsAppAction>
|
||||
<Action to="/contact#whatsapp" variant="ghost">
|
||||
Request a quote
|
||||
</Action>
|
||||
</div>
|
||||
</div>
|
||||
<div className="home-hero__bottom">
|
||||
<span className="home-hero__tagline">
|
||||
Consistency at scale. Continuous development.
|
||||
Development · Circular knitting · Bulk production
|
||||
</span>
|
||||
<span className="home-hero__image-note">
|
||||
Illustrative texture · Photography to follow
|
||||
Factory photography scheduled for content handover
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
<Stats />
|
||||
<Gallery preview />
|
||||
<section className="home-intro">
|
||||
<div className="home-intro__heading">
|
||||
@@ -98,21 +91,20 @@ export default function Home() {
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
<Stats />
|
||||
<section className="process">
|
||||
<SectionHeading
|
||||
label="How we work"
|
||||
label="Manufacturing process"
|
||||
title={
|
||||
<>
|
||||
Behind the fabric:
|
||||
From requirement
|
||||
<br />
|
||||
<em>our process.</em>
|
||||
<em>to repeat production.</em>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
Development, circular knitting and repeatable bulk production work
|
||||
as one discipline.
|
||||
A direct sequence connects fabric development with dependable
|
||||
commercial manufacturing.
|
||||
</p>
|
||||
</SectionHeading>
|
||||
<div className="process__list">
|
||||
@@ -123,7 +115,7 @@ export default function Home() {
|
||||
<h3 className="process__title">{subtitle}</h3>
|
||||
<p className="process__text">{text}</p>
|
||||
<Link className="process__link" to={href}>
|
||||
Explore this capability <Arrow diagonal />
|
||||
See our capability <Arrow diagonal />
|
||||
</Link>
|
||||
</div>
|
||||
<Textile className="process__visual" kind={image} />
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
struct Params {
|
||||
time: f32,
|
||||
progress: f32,
|
||||
aspect: f32,
|
||||
padding: f32,
|
||||
}
|
||||
|
||||
@group(0) @binding(0) var<uniform> params: Params;
|
||||
|
||||
fn thread(value: f32, width: f32) -> f32 {
|
||||
return pow(0.5 + 0.5 * cos(value), width);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(@location(0) uv: vec2f) -> @location(0) vec4f {
|
||||
let p = vec2f(uv.x * params.aspect, uv.y);
|
||||
let drift = sin(p.y * 18.0 + params.time * 0.42) * 0.018;
|
||||
let warp = thread((p.x + drift) * 310.0, 7.0);
|
||||
let weft = thread((p.y + sin(p.x * 13.0) * 0.006) * 280.0, 8.0);
|
||||
let crossing = step(0.5, fract(floor(p.x * 49.0) * 0.5 + floor(p.y * 46.0) * 0.5));
|
||||
let overUnder = mix(warp * 0.58 + weft, warp + weft * 0.55, crossing);
|
||||
let irregularity = sin(p.x * 127.0 + sin(p.y * 31.0)) * 0.025;
|
||||
|
||||
let revealEdge = params.progress + sin(uv.y * 9.0 + params.time * 0.55) * 0.035;
|
||||
let woven = 1.0 - smoothstep(revealEdge - 0.15, revealEdge + 0.04, uv.x);
|
||||
let looseYarn = thread((p.x + sin(p.y * 8.0 + params.time) * 0.035) * 74.0, 10.0);
|
||||
let wovenMask = smoothstep(0.16, 0.72, overUnder + irregularity);
|
||||
let looseMask = smoothstep(0.24, 0.78, looseYarn);
|
||||
let threadMask = mix(looseMask * 0.72, wovenMask, woven);
|
||||
|
||||
let slider = smoothstep(0.0, 1.0, params.progress);
|
||||
let dyed = 1.0 - smoothstep(slider - 0.025, slider + 0.025, uv.x);
|
||||
let greige = vec3f(0.69, 0.62, 0.51);
|
||||
let madder = vec3f(0.72, 0.24, 0.12);
|
||||
let indigo = vec3f(0.08, 0.34, 0.58);
|
||||
let dyeColor = mix(madder, indigo, smoothstep(0.15, 0.9, uv.x));
|
||||
let threadColor = mix(greige, dyeColor, dyed);
|
||||
let shadow = vec3f(0.105, 0.10, 0.082);
|
||||
let highlight = mix(vec3f(0.90, 0.84, 0.72), dyeColor * 1.35, dyed);
|
||||
var color = mix(shadow, threadColor, threadMask);
|
||||
color += highlight * pow(max(warp, weft), 10.0) * 0.14 * woven;
|
||||
|
||||
let vignette = smoothstep(0.82, 0.28, distance(uv, vec2f(0.5)));
|
||||
color *= 0.7 + vignette * 0.3;
|
||||
return vec4f(color, 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user