House Dye Yarns Wholesale Portal House Dye Yarns Wholesale Portal

Home

Yarn

Knit for the Girls & Guys Exclusive - Pink Ladies (Fade 2) - Stirling 4ply

SKU THDST4083

Pink Ladies is colourway 2 in Skein Machine's exclusive Knit for the Girls & Guys (KFTG) charity fade-pack — a limited Australian hand-dyed yarn where 20% of every sale goes directly to cancer research (10% to the Breast Cancer Foundation, 10% to the Prostate Cancer Foundation of Australia).
<?php// Generate the corrected HTML with centered SVG canvas and dynamic polygons$html = '<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width,    initial-scale=1.0">    <title>Interactive SVG Workspace</title>    <style>        * {            margin:    0;            padding:    0;            box-sizing:    border-box;            font-family:    "Segoe UI",    Tahoma,    Geneva,    Verdana,    sans-serif;        }                body {            background:    #ffffff;            color:    #333;            min-height:    100vh;            overflow:    hidden;        }                .workspace-container {            display:    flex;            height:    100vh;            width:    100vw;        }                .workspace-panel {            flex:    1;            position:    relative;            background:    #ffffff;            overflow:    hidden;        }                .workspace-header {            position:    absolute;            top:    15px;            left:    15px;            z-index:    10;            background:    rgba(255,    255,    255,    0.8);            border-radius:    50px;            padding:    8px 15px;            display:    flex;            align-items:    center;            gap:    10px;            box-shadow:    0 2px 10px rgba(0,    0,    0,    0.1);        }                .reset-btn {            background:    #ff6b6b;            border:    none;            border-radius:    50%;            width:    40px;            height:    40px;            cursor:    pointer;            display:    flex;            align-items:    center;            justify-content:    center;            transition:    all 0.3s ease;            box-shadow:    0 2px 5px rgba(0,    0,    0,    0.2);        }                .reset-btn:hover {            background:    #ff5252;            transform:    scale(1.1);        }                .reset-btn svg {            width:    20px;            height:    20px;        }                .zoom-info {            font-size:    0.9rem;            padding:    0 10px;            color:    #333;        }                #workspace {            width:    100%;            height:    100%;            cursor:    grab;            background-color:    #ffffff;        }                #workspace:active {            cursor:    grabbing;        }                .config-panel {            width:    300px;            background:    #f8f9fa;            border-left:    1px solid #e0e0e0;            display:    flex;            flex-direction:    column;            transition:    all 0.3s ease;            box-shadow:    -2px 0 5px rgba(0,    0,    0,    0.05);        }                .panel-header {            display:    flex;            background:    #ffffff;            border-bottom:    1px solid #e0e0e0;        }                .tab {            flex:    1;            padding:    15px;            text-align:    center;            cursor:    pointer;            font-weight:    600;            transition:    all 0.3s ease;            border-bottom:    3px solid transparent;            color:    #666;        }                .tab.active {            background:    #e3f2fd;            border-bottom:    3px solid #2196f3;            color:    #2196f3;        }                .tab:hover:not(.active) {            background:    #f5f5f5;        }                .panel-content {            padding:    25px;            overflow-y:    auto;            flex:    1;        }                .setting-group {            margin-bottom:    25px;        }                .setting-label {            display:    flex;            justify-content:    space-between;            margin-bottom:    10px;            font-weight:    500;            color:    #555;        }                .slider-container {            background:    #ffffff;            padding:    15px;            border-radius:    10px;            box-shadow:    0 2px 5px rgba(0,    0,    0,    0.05);        }                .slider {            width:    100%;            height:    10px;            -webkit-appearance:    none;            background:    linear-gradient(to right,    #4285f4,    #34a853,    #fbbc05,    #ea4335);            border-radius:    5px;            outline:    none;        }                .slider::-webkit-slider-thumb {            -webkit-appearance:    none;            width:    22px;            height:    22px;            border-radius:    50%;            background:    white;            cursor:    pointer;            box-shadow:    0 0 5px rgba(0,    0,    0,    0.5);        }                .value-display {            text-align:    center;            font-size:    1.8rem;            font-weight:    700;            margin:    15px 0;            color:    #2196f3;        }                .toggle-panel {            position:    absolute;            top:    50%;            right:    -30px;            transform:    translateY(-50%);            background:    #f8f9fa;            border:    1px solid #e0e0e0;            border-left:    none;            border-radius:    0 5px 5px 0;            width:    30px;            height:    60px;            cursor:    pointer;            display:    flex;            align-items:    center;            justify-content:    center;            box-shadow:    3px 0 5px rgba(0,    0,    0,    0.1);            z-index:    100;        }                .toggle-panel svg {            width:    15px;            height:    15px;            transition:    transform 0.3s ease;        }                .collapsed .config-panel {            width:    0;            opacity:    0;            overflow:    hidden;        }                .collapsed .toggle-panel svg {            transform:    rotate(180deg);        }                .collapsed .workspace-panel {            flex:    1;        }                @media (max-width:    768px) {            .config-panel {                width:    250px;            }        }    </style></head><body>    <div class="workspace-container">        <div class="workspace-panel">            <div class="workspace-header">                <button class="reset-btn" id="resetBtn" title="Reset View">                    <svg viewBox="0 0 24 24" fill="white">                        <path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/>                    </svg>                </button>                <div class="zoom-info">Zoom:    <span id="zoomValue">100%</span></div>            </div>            <svg id="workspace" xmlns="http://www.w3.org/2000/svg" viewBox="-500 -500 1000 1000">                <!-- Polygon elements will be added dynamically -->            </svg>        </div>                <div class="config-panel">            <div class="panel-header">                <div class="tab active" data-tab="S">S</div>                <div class="tab" data-tab="M">M</div>                <div class="tab" data-tab="L">L</div>            </div>                        <div class="panel-content">                <div class="setting-group">                    <div class="setting-label">                        <span>Rows</span>                        <span id="rowsValue">5</span>                    </div>                    <div class="slider-container">                        <input type="range" min="1" max="250" value="5" class="slider" id="rowsSlider">                    </div>                    <div class="value-display" id="rowsDisplay">5</div>                </div>                                <div class="setting-group">                    <div class="setting-label">                        <span>Cols (Points)</span>                        <span id="colsValue">12</span>                    </div>                    <div class="slider-container">                        <input type="range" min="12" max="200" value="12" class="slider" id="colsSlider">                    </div>                    <div class="value-display" id="colsDisplay">12</div>                </div>                                <div class="setting-group">                    <div class="setting-label">                        <span>Increase Rows</span>                        <span id="increaseRowsValue">1</span>                    </div>                    <div class="slider-container">                        <input type="range" min="1" max="20" value="1" class="slider" id="increaseRowsSlider">                    </div>                    <div class="value-display" id="increaseRowsDisplay">1</div>                </div>                                <div class="setting-group">                    <div class="setting-label">                        <span>Increase Amount</span>                        <span id="increaseAmountValue">2</span>                    </div>                    <div class="slider-container">                        <input type="range" min="1" max="10" value="2" class="slider" id="increaseAmountSlider">                    </div>                    <div class="value-display" id="increaseAmountDisplay">2</div>                </div>                                <div class="setting-group">                    <div class="setting-label">                        <span>Border Width</span>                        <span id="borderValue">2px</span>                    </div>                    <div class="slider-container">                        <input type="range" min="1" max="10" value="2" class="slider" id="borderSlider">                    </div>                    <div class="value-display" id="borderDisplay">2px</div>                </div>            </div>        </div>                <button class="toggle-panel" id="togglePanel">            <svg viewBox="0 0 24 24" fill="#666">                <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>            </svg>        </button>    </div>
    <script>        // DOM Elements        const workspace = document.getElementById("workspace");        const rowsSlider = document.getElementById("rowsSlider");        const rowsValue = document.getElementById("rowsValue");        const rowsDisplay = document.getElementById("rowsDisplay");        const colsSlider = document.getElementById("colsSlider");        const colsValue = document.getElementById("colsValue");        const colsDisplay = document.getElementById("colsDisplay");        const increaseRowsSlider = document.getElementById("increaseRowsSlider");        const increaseRowsValue = document.getElementById("increaseRowsValue");        const increaseRowsDisplay = document.getElementById("increaseRowsDisplay");        const increaseAmountSlider = document.getElementById("increaseAmountSlider");        const increaseAmountValue = document.getElementById("increaseAmountValue");        const increaseAmountDisplay = document.getElementById("increaseAmountDisplay");        const borderSlider = document.getElementById("borderSlider");        const borderValue = document.getElementById("borderValue");        const borderDisplay = document.getElementById("borderDisplay");        const resetBtn = document.getElementById("resetBtn");        const zoomValue = document.getElementById("zoomValue");        const tabs = document.querySelectorAll(".tab");        const togglePanel = document.getElementById("togglePanel");        const container = document.querySelector(".workspace-container");                // State variables        let currentTab = "S";        let presets = {            S:    { rows: 5, cols:    12,    increaseRows:    1,    increaseAmount:    2,    borderWidth:    2 },                     M:    { rows: 5, cols:    24,    increaseRows:    2,    increaseAmount:    3,    borderWidth:    2 },                     L:    { rows: 5, cols:    48,    increaseRows:    3,    increaseAmount:    4,    borderWidth:    2 }        };                // ViewBox state for SVG zoom/pan (centered at origin)        let viewState = {            x:    -500,                     y:    -500,                     w:    1000,                     h:    1000,                     isPanning:    false,                     startPoint:    { x:    0,    y:    0 }        };                // Store original viewbox settings for reset        const originalViewBox = {            x: -500,            y: -500,            w: 1000,            h: 1000        };                // Polygon points tracking        let polygonPoints = {}; // Store points for each polygon by ID        let polygonPointData = {}; // Store detailed point data with decimal naming                // Initialize the workspace        function initWorkspace() {            // Set initial view            resetView();                        // Create the polygon elements            createPolygons();                        // Set up event listeners            setupEventListeners();                        // Apply initial preset            applyPreset(currentTab);        }                // Create the polygon elements        function createPolygons() {            // Clear existing polygons and lines            const existingElements = document.querySelectorAll(".dynamicPolygon,   .connectionLine, .increaseLine");            existingElements.forEach(element => element.remove());                        // Create new polygons            updatePolygons();        }                // Generate points for a polygon with specified number of sides        function generatePolygonPoints(sides,   radius,   centerX = 0,   centerY = 0) {            const points = [];                        for (let i = 0; i < sides; i++) {                const angle = (i * 2 * Math.PI) / sides - Math.PI / 2; // Start from top                const x = centerX + radius * Math.cos(angle);                const y = centerY + radius * Math.sin(angle);                points.push([x,   y]);            }                        return points;        }                // Update polygons based on current settings        function updatePolygons() {            // Clear existing polygons and lines            const existingElements = document.querySelectorAll(".dynamicPolygon,   .connectionLine, .increaseLine");            existingElements.forEach(element => element.remove());                        const rows = presets[currentTab].rows;            const cols = presets[currentTab].cols;            const increaseRows = presets[currentTab].increaseRows;            const increaseAmount = presets[currentTab].increaseAmount;            const borderWidth = presets[currentTab].borderWidth;                        // Base radius (half of workspace width)            const baseRadius = 500 * 0.5; // Half of 1000 (workspace width)                        // Clear previous points tracking            polygonPoints = {};            polygonPointData = {};                        // Create base polygons (scaled up from original)            for (let i = 0; i < rows; i++) {                const polygon = document.createElementNS("http://www.w3.org/2000/svg",    "polygon");                polygon.classList.add("dynamicPolygon");                polygon.setAttribute("fill",    "transparent");                polygon.setAttribute("stroke",    "black");                polygon.setAttribute("stroke-width",    borderWidth);                                // Calculate radius for this polygon (scaled up)                const scaleFactor = 1 + (i * 0.2); // Scale up by 20% per row                const radius = baseRadius * scaleFactor;                                // Generate base points for this polygon                let points = generatePolygonPoints(cols,   radius,   0,   0);                                // Initialize point data with original indices                polygonPointData[`polygon-${i}`] = {};                for (let j = 0; j < points.length; j++) {                    polygonPointData[`polygon-${i}`][j] = {                        x: points[j][0],                        y: points[j][1],                        isIncrement: false                    };                }                                // Store points for this polygon                polygonPoints[`polygon-${i}`] = points;                                // Convert points to string format                const pointsString = points.map(point => point.join(",  ")).join(" ");                polygon.setAttribute("points",    pointsString);                                workspace.appendChild(polygon);            }                        // Create increase lines for specified rows            if (increaseRows > 0 && rows > 1 && increaseAmount > 0) {                createIncreaseLines();            }                        // Create connection lines if we have at least 2 polygons            if (rows >= 2) {                // Get points from first and last polygons                const firstPolygonPoints = polygonPoints["polygon-0"];                const lastPolygonPoints = polygonPoints[`polygon-${rows-1}`];                                // Create lines for each point                const maxPoints = Math.max(firstPolygonPoints.length,   lastPolygonPoints.length);                                for (let i = 0; i < maxPoints; i++) {                    const line = document.createElementNS("http://www.w3.org/2000/svg",    "line");                    line.classList.add("connectionLine");                    line.setAttribute("stroke",    "black");                    line.setAttribute("stroke-width",    borderWidth * 0.5); // Thinner lines                                        // Get points (wrap around if needed)                    const firstPointIndex = i % firstPolygonPoints.length;                    const lastPointIndex = i % lastPolygonPoints.length;                                        const firstPoint = firstPolygonPoints[firstPointIndex];                    const lastPoint = lastPolygonPoints[lastPointIndex];                                        line.setAttribute("x1",    firstPoint[0]);                    line.setAttribute("y1",    firstPoint[1]);                    line.setAttribute("x2",    lastPoint[0]);                    line.setAttribute("y2",    lastPoint[1]);                                        workspace.appendChild(line);                }            }        }                // Create increase lines based on new logic with decimal naming        function createIncreaseLines() {            const rows = presets[currentTab].rows;            const increaseRows = presets[currentTab].increaseRows;            const increaseAmount = presets[currentTab].increaseAmount;            const borderWidth = presets[currentTab].borderWidth;                        // For each row that should be increased (every increaseRows-th row starting from row 1)            for (let i = 1; i < rows; i++) {                if (increaseRows > 1 && (i + 1) % increaseRows !== 0) continue;                                const polygonPointsCurrent = polygonPoints[`polygon-${i}`];                const pointData = polygonPointData[`polygon-${i}`];                if (!polygonPointsCurrent) continue;                                // Determine which points to use based on increaseAmount                const step = Math.max(1, Math.floor(polygonPointsCurrent.length / increaseAmount));                                // Keep track of new points to add after processing                const newPointsToAdd = [];                                // Create lines for selected points                for (let j = 0; j < increaseAmount; j++) {                    const pointIndex = j * step;                    if (pointIndex >= polygonPointsCurrent.length) break;                                        // Get current point and next point                    const currentPoint = polygonPointsCurrent[pointIndex];                    const nextPointIndex = (pointIndex + 1) % polygonPointsCurrent.length;                    const nextPoint = polygonPointsCurrent[nextPointIndex];                                        // Calculate midpoint between current and next point                    const midX = (currentPoint[0] + nextPoint[0]) / 2;                    const midY = (currentPoint[1] + nextPoint[1]) / 2;                                        // Find corresponding point on outermost polygon                    const outerPolygonPoints = polygonPoints[`polygon-${rows-1}`];                    let closestOuterPoint = outerPolygonPoints[0];                    let minDistance = Number.MAX_VALUE;                                        // Find the closest point on the outer polygon                    for (let k = 0; k < outerPolygonPoints.length; k++) {                        const outerPoint = outerPolygonPoints[k];                        const distance = Math.sqrt(                            Math.pow(outerPoint[0] - midX, 2) +                             Math.pow(outerPoint[1] - midY, 2)                        );                                                if (distance < minDistance) {                            minDistance = distance;                            closestOuterPoint = outerPoint;                        }                    }                                        // Create line from midpoint to closest outer point                    const line = document.createElementNS("http://www.w3.org/2000/svg", "line");                    line.classList.add("increaseLine");                    line.setAttribute("stroke", "red");                    line.setAttribute("stroke-width", borderWidth);                    line.setAttribute("x1", midX);                    line.setAttribute("y1", midY);                    line.setAttribute("x2", closestOuterPoint[0]);                    line.setAttribute("y2", closestOuterPoint[1]);                                        workspace.appendChild(line);                                        // Add the midpoint as a new point with decimal naming                    const decimalName = pointIndex + 0.5;                    newPointsToAdd.push({                        index: pointIndex + 1,                        point: [midX, midY],                        decimalName: decimalName                    });                                        // Store point data with decimal naming                    polygonPointData[`polygon-${i}`][decimalName] = {                        x: midX,                        y: midY,                        isIncrement: true                    };                }                                // Add new points to the polygon in order to maintain sequence                let insertedCount = 0;                for (const newPoint of newPointsToAdd) {                    polygonPoints[`polygon-${i}`].splice(newPoint.index + insertedCount, 0, newPoint.point);                    insertedCount++;                }                                // Update the polygon with new points                const polygonElements = document.querySelectorAll(".dynamicPolygon");                if (polygonElements[i]) {                    const pointsString = polygonPoints[`polygon-${i}`].map(point => point.join(",  ")).join(" ");                    polygonElements[i].setAttribute("points", pointsString);                }            }        }                // Reset view to default (centered at origin)        function resetView() {            viewState = {                x: originalViewBox.x,                y: originalViewBox.y,                w: originalViewBox.w,                h: originalViewBox.h,                isPanning: false,                startPoint: { x: 0, y: 0 }            };            workspace.setAttribute("viewBox", `${viewState.x} ${viewState.y} ${viewState.w} ${viewState.h}`);            zoomValue.textContent = "100%";        }                // Apply preset settings        function applyPreset(tab) {            const preset = presets[tab];                        rowsSlider.value = preset.rows;            rowsValue.textContent = `${preset.rows}`;            rowsDisplay.textContent = `${preset.rows}`;                        colsSlider.value = preset.cols;            colsValue.textContent = `${preset.cols}`;            colsDisplay.textContent = `${preset.cols}`;                        increaseRowsSlider.value = preset.increaseRows;            increaseRowsValue.textContent = `${preset.increaseRows}`;            increaseRowsDisplay.textContent = `${preset.increaseRows}`;                        increaseAmountSlider.value = preset.increaseAmount;            increaseAmountValue.textContent = `${preset.increaseAmount}`;            increaseAmountDisplay.textContent = `${preset.increaseAmount}`;                        borderSlider.value = preset.borderWidth;            borderValue.textContent = `${preset.borderWidth}px`;            borderDisplay.textContent = `${preset.borderWidth}px`;                        updatePolygons();        }                // Helper function to convert screen coordinates to SVG coordinates        function getSVGPoint(e) {            const p = workspace.createSVGPoint();            p.x = e.clientX;            p.y = e.clientY;            return p.matrixTransform(workspace.getScreenCTM().inverse());        }                // Set up event listeners        function setupEventListeners() {            // Tab switching            tabs.forEach(tab => {                tab.addEventListener("click", () => {                    // Update active tab                    tabs.forEach(t => t.classList.remove("active"));                    tab.classList.add("active");                                        // Apply preset                    currentTab = tab.dataset.tab;                    applyPreset(currentTab);                });            });                        // Rows slider input            rowsSlider.addEventListener("input", () => {                const value = parseInt(rowsSlider.value);                presets[currentTab].rows = value;                rowsValue.textContent = `${value}`;                rowsDisplay.textContent = `${value}`;                updatePolygons();            });                        // Cols slider input            colsSlider.addEventListener("input", () => {                const value = parseInt(colsSlider.value);                presets[currentTab].cols = value;                colsValue.textContent = `${value}`;                colsDisplay.textContent = `${value}`;                updatePolygons();            });                        // Increase rows slider input            increaseRowsSlider.addEventListener("input", () => {                const value = parseInt(increaseRowsSlider.value);                presets[currentTab].increaseRows = value;                increaseRowsValue.textContent = `${value}`;                increaseRowsDisplay.textContent = `${value}`;                updatePolygons();            });                        // Increase amount slider input            increaseAmountSlider.addEventListener("input", () => {                const value = parseInt(increaseAmountSlider.value);                presets[currentTab].increaseAmount = value;                increaseAmountValue.textContent = `${value}`;                increaseAmountDisplay.textContent = `${value}`;                updatePolygons();            });                        // Border width slider input            borderSlider.addEventListener("input", () => {                const value = parseInt(borderSlider.value);                presets[currentTab].borderWidth = value;                borderValue.textContent = `${value}px`;                borderDisplay.textContent = `${value}px`;                updatePolygons();            });                        // Reset button            resetBtn.addEventListener("click", resetView);                        // Toggle panel            togglePanel.addEventListener("click", () => {                container.classList.toggle("collapsed");            });                        // Zoom with mouse wheel            workspace.addEventListener("wheel", (e) => {                e.preventDefault();                                // Determine zoom factor                const zoomFactor = e.deltaY < 0 ? 0.9 : 1.1;                                // Don\'t let it get too small or large                if (viewState.w * zoomFactor > 5000 || viewState.w * zoomFactor < 100) return;                                // Get the mouse position relative to the SVG internal space                const mouseSVGPoint = getSVGPoint(e);                                // Calculate new width and height                const newW = viewState.w * zoomFactor;                const newH = viewState.h * zoomFactor;                                // Adjust X and Y so the mouse pointer remains the anchor center of the zoom                const newX = mouseSVGPoint.x - (mouseSVGPoint.x - viewState.x) * zoomFactor;                const newY = mouseSVGPoint.y - (mouseSVGPoint.y - viewState.y) * zoomFactor;                                // Update state and DOM                viewState.x = newX;                viewState.y = newY;                viewState.w = newW;                viewState.h = newH;                                workspace.setAttribute("viewBox", `${viewState.x} ${viewState.y} ${viewState.w} ${viewState.h}`);                zoomValue.textContent = `${Math.round(1000 / viewState.w * 100)}%`;            });                        // Pan with middle mouse button            workspace.addEventListener("pointerdown", (e) => {                if (e.button === 1) { // Middle mouse button                    viewState.isPanning = true;                    // Store the exact SVG coordinate where the user clicked                    viewState.startPoint = getSVGPoint(e);                    workspace.style.cursor = "grabbing";                    e.preventDefault();                }            });                        workspace.addEventListener("pointermove", (e) => {                if (!viewState.isPanning) return;                                // Get the current mouse position in SVG coordinates                const currentPoint = getSVGPoint(e);                                // Calculate how much the mouse moved inside the SVG space                const dx = viewState.startPoint.x - currentPoint.x;                const dy = viewState.startPoint.y - currentPoint.y;                                // Shift the viewBox by the delta movement                viewState.x += dx;                viewState.y += dy;                                workspace.setAttribute("viewBox", `${viewState.x} ${viewState.y} ${viewState.w} ${viewState.h}`);            });                        workspace.addEventListener("pointerup", () => {                if (viewState.isPanning) {                    viewState.isPanning = false;                    workspace.style.cursor = "grab";                }            });                        workspace.addEventListener("pointerleave", () => {                if (viewState.isPanning) {                    viewState.isPanning = false;                    workspace.style.cursor = "grab";                }            });                        // Handle window resize            window.addEventListener("resize", () => {                updatePolygons();            });        }                // Initialize when page loads        window.addEventListener("DOMContentLoaded", initWorkspace);    </script></body></html>';
// Output the HTMLecho $html;?>
Imagine knitting with the last warm light of a summer evening — deep, moody hues that shift and glow as your project grows. Each skein is hand-dyed in small batches in South Australia.
This colourway is part of a 5-colour fade-pack — buy the full set or individual skeins. See all KFTG&G colourways and bases →
Yarn Specifications


Weight: 4ply / Fingering

Fibre: Singlespun 60% Superwash Merino, 20% Baby Alpaca, 5% Grade A Mullberry Silk

Yardage: 460m per 115g skein

Dyed in: South Australia, Australia

Frequently Asked Questions
What is KFTG? Knit for the Girls is an annual fibre arts community fundraiser raising money for breast cancer research. Skein Machine has partnered with Louie and Lola Yarns to extend donations to the Prostate Cancer Foundation of Australia — so we Knit for the Girls and Guys.
The Yarn? Yes — 60% Superwash Merino makes it machine-washable and soft against the skin, blended with 20% Alpaca and 20% Grade A Mulberry Silk to give a great drape to your project.
Can I buy just one skein from the fade? Absolutely — individual skeins are available. The full 5-colour fade-pack is also available on the KFTG Skein Machine page. This listing is for one skein.
Where is this yarn made? Hand-dyed in South Australia by Skein Machine.

Sign in as a wholesale client to view pricing and order.