SYSTEM / ONLINE

(function () { const field = document.getElementById("transmission-field"); if (!field) return; const words = [ "TRANSMISSION", "SIGNAL", "THOUGHT", "MEMORY", "SYSTEM", "CONNECTION", "PATTERN", "IDEA", "PROCESS", "NETWORK", "DATA", "CONSCIOUSNESS", "FREQUENCY", "LANGUAGE", "INFORMATION", "OBSERVATION", "STRUCTURE", "SIGNAL", "THOUGHT", "MEMORY" ]; const importantWords = [ "TRANSMISSION", "THOUGHT", "CONNECTION", "CONSCIOUSNESS" ]; const amount = 35; for (let i = 0; i < amount; i++) { const word = document.createElement("div"); const text = words[Math.floor(Math.random() * words.length)]; word.className = "transmission-word"; if (importantWords.includes(text)) { word.classList.add("important"); } word.textContent = text; word.style.left = Math.random() * 100 + "%"; word.style.top = Math.random() * 100 + "%"; word.style.animation = "transmissionFloat " + (8 + Math.random() * 14) + "s linear infinite"; word.style.animationDelay = (-Math.random() * 20) + "s"; word.style.fontSize = (10 + Math.random() * 7) + "px"; field.appendChild(word); } })();
CASE FILES
00
SIGNAL
ACTIVE
CHANNEL
OPEN
(function () { var counter = document.querySelector('[data-count]'); if (!counter) return; var target = parseInt(counter.dataset.count, 10); var current = 0; var interval = setInterval(function () { current++; counter.textContent = String(current).padStart(2, "0"); if (current >= target) { clearInterval(interval); } }, 90); })();

ARCHIVE / ACTIVE

SIGNAL ANALYSIS / ACTIVE
01 / 07    SYSTEM ONLINE
SHIROMIYA
(function () { var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; document.querySelectorAll(".glitch-text").forEach(function (el) { var original = el.dataset.text; var running = false; el.addEventListener("mouseenter", function () { if (running) return; running = true; var iteration = 0; var interval = setInterval(function () { el.textContent = original .split("") .map(function (letter, index) { if (index < iteration) { return original[index]; } return letters[ Math.floor(Math.random() * letters.length) ]; }) .join(""); iteration += 0.45; if (iteration >= original.length) { clearInterval(interval); el.textContent = original; running = false; } }, 35); }); }); })();

PROTOCOL / 03

Time4h
Hourly rate750 DKK
ScaleMedium
Quantity1
ComplexityMedium
UrgencyStandard
Estimated price
12.000 DKK
Pricing curveDrag the points
Move the points to change the shape of the project.
(function(){ const root = document.getElementById("shiro-pricing"); if(!root || root.dataset.initialized) return; root.dataset.initialized = "true"; /* ----------------------------- DATA ----------------------------- */ const scaleNames = [ "Tiny", "Small", "Medium", "Large", "Enterprise" ]; const complexityNames = [ "Simple", "Light", "Medium", "Advanced", "Complex" ]; const urgencyNames = [ "Standard", "Priority", "Rush" ]; const scaleMultiplier = [ 0.7, 0.9, 1, 1.25, 1.6 ]; const complexityMultiplier = [ 0.8, 0.95, 1, 1.25, 1.5 ]; const urgencyMultiplier = [ 1, 1.2, 1.5 ]; const stages = [ "Start", "Scope", "Build", "Review", "Polish", "Delivery" ]; /* These values control the draggable curve. 1 = normal Higher = more effort Lower = less effort */ let points = [ 0.75, 1.05, 1.40, 1.10, 0.90, 0.65 ]; let dragging = null; /* ----------------------------- ELEMENTS ----------------------------- */ const timeInput = root.querySelector("#sp-time-input"); const rateInput = root.querySelector("#sp-rate-input"); const scaleInput = root.querySelector("#sp-scale-input"); const quantityInput = root.querySelector("#sp-quantity-input"); const complexityInput = root.querySelector("#sp-complexity-input"); const urgencyInput = root.querySelector("#sp-urgency-input"); const graph = root.querySelector("#sp-graph"); const grid = root.querySelector("#sp-grid"); const curve = root.querySelector("#sp-curve"); const area = root.querySelector("#sp-area"); const pointLayer = root.querySelector("#sp-points"); /* ----------------------------- FORMAT ----------------------------- */ function money(value){ return Math.round(value) .toLocaleString("da-DK") + " DKK"; } /* ----------------------------- BASE PRICE ----------------------------- */ function calculateBase(){ const time = Number(timeInput.value); const rate = Number(rateInput.value); const scale = Number(scaleInput.value); const quantity = Number(quantityInput.value); const complexity = Number(complexityInput.value); const urgency = Number(urgencyInput.value); return ( time * rate * quantity * scaleMultiplier[scale] * complexityMultiplier[complexity] * urgencyMultiplier[urgency] ); } /* ----------------------------- CURVE FACTOR ----------------------------- */ function curveFactor(){ /* Average the draggable points. This means the graph is not decorative: moving it actually affects the final price. */ const average = points.reduce((sum,value) => sum + value,0) / points.length; return average; } /* ----------------------------- UPDATE TEXT ----------------------------- */ function updateLabels(){ const time = Number(timeInput.value); const rate = Number(rateInput.value); const scale = Number(scaleInput.value); const quantity = Number(quantityInput.value); const complexity = Number(complexityInput.value); const urgency = Number(urgencyInput.value); root.querySelector("#sp-time").textContent = time + "h"; root.querySelector("#sp-rate").textContent = rate.toLocaleString("da-DK") + " DKK"; root.querySelector("#sp-scale").textContent = scaleNames[scale]; root.querySelector("#sp-quantity").textContent = quantity; root.querySelector("#sp-complexity").textContent = complexityNames[complexity]; root.querySelector("#sp-urgency").textContent = urgencyNames[urgency]; const finalPrice = calculateBase() * curveFactor(); root.querySelector("#sp-total").textContent = money(finalPrice); } /* ----------------------------- GRAPH COORDINATES ----------------------------- */ const W = 720; const H = 400; const left = 55; const right = 680; const top = 45; const bottom = 315; const graphWidth = right - left; const graphHeight = bottom - top; function pointPosition(index){ const x = left + (graphWidth / (points.length - 1)) * index; /* Convert point value into SVG Y. 0.25 = low 2.5 = high */ const min = 0.25; const max = 2.5; const normalized = (points[index] - min) / (max - min); const y = bottom - normalized * graphHeight; return { x:x, y:y }; } /* ----------------------------- DRAW GRID ----------------------------- */ function drawGrid(){ grid.innerHTML = ""; for(let i=0;i<=5;i++){ const x = left + (graphWidth / 5) * i; grid.insertAdjacentHTML( "beforeend", '' ); } for(let i=0;i<=4;i++){ const y = top + (graphHeight / 4) * i; grid.insertAdjacentHTML( "beforeend", '' ); } } /* ----------------------------- DRAW CURVE ----------------------------- */ function drawGraph(){ let path = ""; let areaPath = ""; points.forEach(function(value,index){ const p = pointPosition(index); if(index === 0){ path = "M " + p.x + " " + p.y; areaPath = "M " + p.x + " " + bottom + " L " + p.x + " " + p.y; }else{ /* Smooth-ish curve using quadratic segments. */ const previous = pointPosition(index - 1); const midX = (previous.x + p.x) / 2; path += " Q " + midX + " " + previous.y + " " + p.x + " " + p.y; areaPath += " Q " + midX + " " + previous.y + " " + p.x + " " + p.y; } }); const last = pointPosition(points.length - 1); areaPath += " L " + last.x + " " + bottom + " Z"; curve.setAttribute("d",path); area.setAttribute("d",areaPath); pointLayer.innerHTML = ""; points.forEach(function(value,index){ const p = pointPosition(index); /* Price percentage */ const percentage = Math.round(value * 100); const circle = document.createElementNS( "http://www.w3.org/2000/svg", "circle" ); circle.setAttribute( "class", "point" ); circle.setAttribute( "cx", p.x ); circle.setAttribute( "cy", p.y ); circle.setAttribute( "r", 8 ); circle.dataset.index = index; pointLayer.appendChild(circle); /* Stage label */ const label = document.createElementNS( "http://www.w3.org/2000/svg", "text" ); label.setAttribute( "class", "stage" ); label.setAttribute( "x", p.x ); label.setAttribute( "y", bottom + 30 ); label.textContent = stages[index]; pointLayer.appendChild(label); /* Value label */ const valueLabel = document.createElementNS( "http://www.w3.org/2000/svg", "text" ); valueLabel.setAttribute( "class", "graph-value" ); valueLabel.setAttribute( "x", p.x ); valueLabel.setAttribute( "y", p.y - 17 ); valueLabel.textContent = percentage + "%"; pointLayer.appendChild(valueLabel); }); } /* ----------------------------- DRAW EVERYTHING ----------------------------- */ function render(){ updateLabels(); drawGrid(); drawGraph(); } /* ----------------------------- SLIDERS ----------------------------- */ [ timeInput, rateInput, scaleInput, quantityInput, complexityInput, urgencyInput ].forEach(function(input){ input.addEventListener( "input", render ); }); /* ----------------------------- DRAGGING ----------------------------- */ function getSVGPoint(event){ const rect = graph.getBoundingClientRect(); return { x: (event.clientX - rect.left) / rect.width * W, y: (event.clientY - rect.top) / rect.height * H }; } graph.addEventListener( "pointerdown", function(event){ const target = event.target; if( !target.classList.contains("point") ){ return; } dragging = Number(target.dataset.index); target.classList.add( "dragging" ); try{ target.setPointerCapture( event.pointerId ); }catch(e){} event.preventDefault(); } ); graph.addEventListener( "pointermove", function(event){ if(dragging === null){ return; } const p = getSVGPoint(event); const normalized = (bottom - p.y) / graphHeight; const min = 0.25; const max = 2.5; let value = min + normalized * (max - min); value = Math.max( min, Math.min(max,value) ); /* Don't allow the user to drag horizontally because the stages stay fixed in order. */ points[dragging] = value; render(); event.preventDefault(); } ); function stopDragging(){ dragging = null; } graph.addEventListener( "pointerup", stopDragging ); graph.addEventListener( "pointercancel", stopDragging ); /* ----------------------------- INITIALISE ----------------------------- */ render(); })();
PRICING MATRIX / PROCESSING
SCOPE / CALCULATING40%STATUS / ACTIVE
SYSTEM CALIBRATING
(function () { var percent = document.getElementById("price-percent"); if (!percent) return; var value = 40; var direction = 1; setInterval(function () { value += direction * (Math.random() * 4 + 1); if (value >= 96) { value = 96; direction = -1; } if (value <= 12) { value = 12; direction = 1; } percent.textContent = Math.round(value) + "%"; }, 180); })();
PRICING / 01

Website Pricing

PackagePrice (DKK)Est. TimePagesBest ForPlatform
Basic4,000–6,0004–7h1–3New / very small businessesCarrd, Framer
Standard7,000–10,0008–15h4–6Small local businessesWordPress, Framer
Professional12,000–18,00015–25h6–10+Established businessesWordPress, Webflow
Custom20,000–40,000+25–50h+CustomComplex requirementsCustom code
SYSTEM / 02

Features

FeatureBasicStandardProfessionalCustom
Responsive design✓✓✓✓
Custom designBasic✓✓✓
Contact information✓✓✓✓
Contact form✓✓✓✓
Google Maps✓✓✓✓
Social links✓✓✓✓
Basic SEO✓✓✓✓
Analytics✓✓✓✓
Gallery—✓✓✓
Testimonials—✓✓✓
CMS—Optional✓✓
Blog / News—Optional✓✓
Booking systemAdd-onAdd-on✓ / Add-on✓
Payment systemAdd-onAdd-onAdd-on✓
CRM integration—Add-onAdd-on✓
API integration——Add-on✓
Custom functionality——Limited✓
MigrationAdd-onAdd-on✓✓
EXTENSIONS / 03

Add-ons

Add-onPrice (DKK)Est. Time
Contact / lead form500–1,5000.5–1.5h
Extra page500–1,0000.5–1.5h
Newsletter integration1,000–2,5001–3h
Calendar integration1,000–3,0001–3h
Booking system1,500–4,0002–5h
Website migration1,000–4,0002–6h
Payment integration2,000–5,0003–6h
CRM integration2,000–5,0003–6h
Third-party API2,500–7,500+3–10h+
Copywriting1,000–4,000+2–6h+
Custom functionality500–800/hourVariable

PROFILE / 01

PERSONAL TRANSMISSION
SIGNAL / ACTIVE
Client
TRANSMISSION / 01
CLIENT
You
TRANSMISSION / 02
DEVELOPER
CLIENT
TRANSMISSION 01 / 10
(function () { var transmissions = [ { speaker: "CLIENT", message: "I have an idea." }, { speaker: "DEVELOPER", message: "Tell me about it." }, { speaker: "CLIENT", message: "Something that feels different." }, { speaker: "DEVELOPER", message: "Different how?" }, { speaker: "CLIENT", message: "I don't want another generic website." }, { speaker: "DEVELOPER", message: "Then we start with the signal, not the template." }, { speaker: "CLIENT", message: "The signal?" }, { speaker: "DEVELOPER", message: "The thing people should feel before they understand it." }, { speaker: "CLIENT", message: "That sounds complicated." }, { speaker: "DEVELOPER", message: "It doesn't have to be." } ]; var current = 0; var speaker = document.getElementById( "transmissionSpeaker" ); var message = document.getElementById( "transmissionMessage" ); var counter = document.getElementById( "transmissionCounter" ); var next = document.getElementById( "transmissionNext" ); function typeMessage(text) { message.textContent = ""; var index = 0; function type() { if (index >= text.length) { return; } message.textContent += text.charAt(index); index++; setTimeout( type, 24 ); } type(); } function showTransmission() { var transmission = transmissions[current]; speaker.textContent = transmission.speaker; counter.textContent = "TRANSMISSION " + String(current + 1).padStart(2, "0") + " / " + String(transmissions.length).padStart(2, "0"); typeMessage( transmission.message ); } next.addEventListener( "click", function () { current++; if ( current >= transmissions.length ) { current = 0; } showTransmission(); } ); showTransmission(); })();
Secure communication channel

START A TRANSMISSION

SIGNAL / ACTIVE

Have a project, idea, question, or something you'd like to build? Send the details below. The more context you provide, the better the response can be.

PLEASE COMPLETE ALL REQUIRED FIELDS.
TRANSMISSION / ENCRYPTED
RESPONSE CHANNEL / EMAIL
TRANSMISSION / RECEIVED
MESSAGE SENT
Your transmission has been received. I'll review the details and get back to you through the contact information provided.
(function () { function initTransmission() { var customForm = document.getElementById("transmission-custom"); var nativeForm = document.getElementById("transmission-form"); if (!customForm || !nativeForm) { return; } var nameField = document.getElementById("custom-name"); var emailField = document.getElementById("custom-email"); var companyField = document.getElementById("custom-company"); var timelineField = document.getElementById("custom-timeline"); var messageField = document.getElementById("custom-message"); var consentField = document.getElementById("custom-consent"); var errorBox = document.getElementById("transmission-error"); var successBox = document.getElementById("transmission-success"); var fieldsBox = document.getElementById("transmission-fields"); var submitButton = document.getElementById("transmission-submit"); var nativeName = document.getElementById("transmission-form-name"); var nativeEmail = document.getElementById("transmission-form-email"); var nativeCompany = document.getElementById("transmission-form-company"); var nativeTimeline = document.getElementById("transmission-form-subject"); var nativeMessage = document.getElementById("transmission-form-message"); var nativeConsent = document.getElementById("transmission-form-consent"); var nativeSubmit = nativeForm.querySelector('button[type="submit"]'); if ( !nameField || !emailField || !companyField || !timelineField || !messageField || !consentField || !nativeName || !nativeEmail || !nativeCompany || !nativeTimeline || !nativeMessage || !nativeConsent || !nativeSubmit ) { console.log("TRANSMISSION: required Carrd fields not found."); return; } submitButton.addEventListener("click", function () { errorBox.style.display = "none"; var name = nameField.value.trim(); var email = emailField.value.trim(); var company = companyField.value.trim(); var timeline = timelineField.value.trim(); var message = messageField.value.trim(); if ( !name || !email || !message || !consentField.checked ) { errorBox.style.display = "block"; return; } if (!emailField.checkValidity()) { errorBox.textContent = "PLEASE ENTER A VALID EMAIL ADDRESS."; errorBox.style.display = "block"; return; } /* * Copy the custom visual fields into Carrd's * real native form fields. */ nativeName.value = name; nativeEmail.value = email; nativeCompany.value = company; nativeTimeline.value = timeline; nativeMessage.value = message; nativeConsent.checked = consentField.checked; /* * Let Carrd handle the actual submission. */ nativeSubmit.click(); }); nativeForm.addEventListener("submit", function () { /* * Give Carrd a moment to process its own * submission before showing the visual success state. */ setTimeout(function () { fieldsBox.style.display = "none"; successBox.style.display = "block"; }, 500); }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initTransmission); } else { initTransmission(); } })();