Changes to goop.scroll.pub

ScrollHub
ScrollHub
25 days ago
updated script.js
script.js
Changed around line 1
- document.addEventListener('DOMContentLoaded', () => {
- const canvas = document.getElementById('goopCanvas');
- const ctx = canvas.getContext('2d');
- const colorBtn = document.getElementById('colorBtn');
- const viscosityBtn = document.getElementById('viscosityBtn');
- const resetBtn = document.getElementById('resetBtn');
-
+ document.addEventListener("DOMContentLoaded", () => {
+ const canvasParent = document.getElementById("goopCanvas");
+ const canvas = document.createElement("canvas");
+ canvasParent.appendChild(canvas);
+ const ctx = canvas.getContext("2d");
+ const colorBtn = document.getElementById("colorBtn");
+ const viscosityBtn = document.getElementById("viscosityBtn");
+ const resetBtn = document.getElementById("resetBtn");
+
-
- window.addEventListener('resize', resizeCanvas);
+
+ window.addEventListener("resize", resizeCanvas);
-
+
- color: getComputedStyle(document.documentElement).getPropertyValue('--goop-color'),
+ color: getComputedStyle(document.documentElement).getPropertyValue(
+ "--goop-color",
+ ),
- minSize: 10
+ minSize: 10,
-
+
Changed around line 39: document.addEventListener('DOMContentLoaded', () => {
- color: goop.color
+ color: goop.color,
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- ctx.strokeStyle = `${p.color}${Math.floor((1 - distance/100) * 50 + 50).toString(16).padStart(2, '0')}`;
+ ctx.strokeStyle = `${p.color}${Math.floor(
+ (1 - distance / 100) * 50 + 50,
+ )
+ .toString(16)
+ .padStart(2, "0")}`;
-
+
-
+
- colorBtn.addEventListener('click', () => {
+ colorBtn.addEventListener("click", () => {
- goop.particles.forEach(p => {
+ goop.particles.forEach((p) => {
-
- viscosityBtn.addEventListener('click', () => {
+
+ viscosityBtn.addEventListener("click", () => {
-
- resetBtn.addEventListener('click', () => {
+
+ resetBtn.addEventListener("click", () => {
- goop.color = getComputedStyle(document.documentElement).getPropertyValue('--goop-color');
+ goop.color = getComputedStyle(document.documentElement).getPropertyValue(
+ "--goop-color",
+ );
-
+
- canvas.addEventListener('mousemove', (e) => {
+ canvas.addEventListener("mousemove", (e) => {
-
- goop.particles.forEach(p => {
+
+ goop.particles.forEach((p) => {
-
+
Changed around line 133: document.addEventListener('DOMContentLoaded', () => {
-
+
- canvas.addEventListener('touchmove', (e) => {
- e.preventDefault();
- const rect = canvas.getBoundingClientRect();
- const touch = e.touches[0];
- const touchX = touch.clientX - rect.left;
- const touchY = touch.clientY - rect.top;
-
- goop.particles.forEach(p => {
- const dx = touchX - p.x;
- const dy = touchY - p.y;
- const distance = Math.sqrt(dx * dx + dy * dy);
-
- if (distance < 150) {
- const force = 150 / distance;
- p.vx += dx * 0.0005 * force;
- p.vy += dy * 0.0005 * force;
- }
- });
- }, { passive: false });
-
+ canvas.addEventListener(
+ "touchmove",
+ (e) => {
+ e.preventDefault();
+ const rect = canvas.getBoundingClientRect();
+ const touch = e.touches[0];
+ const touchX = touch.clientX - rect.left;
+ const touchY = touch.clientY - rect.top;
+
+ goop.particles.forEach((p) => {
+ const dx = touchX - p.x;
+ const dy = touchY - p.y;
+ const distance = Math.sqrt(dx * dx + dy * dy);
+
+ if (distance < 150) {
+ const force = 150 / distance;
+ p.vx += dx * 0.0005 * force;
+ p.vy += dy * 0.0005 * force;
+ }
+ });
+ },
+ { passive: false },
+ );
+
- });
+ });
ScrollHub
ScrollHub
25 days ago
Initial commit
index.scroll
Changed around line 1
+ buildHtml
+ baseUrl https://goop.scroll.pub
+ metaTags
+ editButton /edit.html
+ title Unending Goop | Mesmerizing Interactive Experience
+ style.css
+ header
+ class hero
+ div
+ class hero-content
+ h1 Unending Goop
+ p An infinite, interactive experience of mesmerizing goop
+ main
+ section
+ class goop-container
+ div
+ id goopCanvas
+ class canvas-container
+ div
+ class controls
+ button
+ id colorBtn
+ Change Color
+ button
+ id viscosityBtn
+ Change Viscosity
+ button
+ id resetBtn
+ Reset Goop
+ footer
+ div
+ class footer-content
+ p Created with Scroll. Inspired by the infinite.
+ script.js
prompt.json
Changed around line 1
+ {
+ "id": "1b66025c-e0f2-4d49-a972-e930bbbedd8e",
+ "object": "chat.completion",
+ "created": 1749844390,
+ "model": "deepseek-chat",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "Here's my suggestion for a website showcasing \"unending amounts of goop\" with a mesmerizing, interactive experience:\n\n---domain---\ngoop.scroll.pub\n---index.scroll---\nbuildHtml\nbaseUrl https://goop.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Unending Goop | Mesmerizing Interactive Experience\nstyle.css\nheader\n class hero\n div\n class hero-content\n h1 Unending Goop\n p An infinite, interactive experience of mesmerizing goop\nmain\n section\n class goop-container\n div\n id goopCanvas\n class canvas-container\n div\n class controls\n button\n id colorBtn\n Change Color\n button\n id viscosityBtn\n Change Viscosity\n button\n id resetBtn\n Reset Goop\nfooter\n div\n class footer-content\n p Created with Scroll. Inspired by the infinite.\nscript.js\n---style.css---\n:root {\n --primary: #6c5ce7;\n --secondary: #a29bfe;\n --dark: #2d3436;\n --light: #f5f6fa;\n --goop-color: #00cec9;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Segoe UI', system-ui, sans-serif;\n line-height: 1.6;\n color: var(--dark);\n background-color: var(--light);\n overflow-x: hidden;\n}\n\n.hero {\n background: linear-gradient(135deg, var(--primary), var(--secondary));\n color: white;\n padding: 4rem 1rem;\n text-align: center;\n position: relative;\n overflow: hidden;\n}\n\n.hero-content {\n max-width: 800px;\n margin: 0 auto;\n position: relative;\n z-index: 2;\n}\n\n.hero h1 {\n font-size: 3.5rem;\n margin-bottom: 1rem;\n font-weight: 800;\n}\n\n.hero p {\n font-size: 1.25rem;\n opacity: 0.9;\n max-width: 600px;\n margin: 0 auto;\n}\n\n.goop-container {\n padding: 2rem 1rem;\n max-width: 1200px;\n margin: 0 auto;\n}\n\n.canvas-container {\n width: 100%;\n height: 70vh;\n min-height: 500px;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 10px 30px rgba(0,0,0,0.1);\n margin-bottom: 2rem;\n background: white;\n}\n\n#goopCanvas {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.controls {\n display: flex;\n gap: 1rem;\n justify-content: center;\n flex-wrap: wrap;\n}\n\nbutton {\n padding: 0.75rem 1.5rem;\n border: none;\n border-radius: 50px;\n background: var(--primary);\n color: white;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n}\n\nbutton:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 12px rgba(0,0,0,0.15);\n}\n\nbutton:active {\n transform: translateY(0);\n}\n\n.footer-content {\n text-align: center;\n padding: 2rem 1rem;\n color: var(--dark);\n opacity: 0.7;\n}\n\n@media (max-width: 768px) {\n .hero h1 {\n font-size: 2.5rem;\n }\n \n .hero p {\n font-size: 1.1rem;\n }\n \n .controls {\n flex-direction: column;\n align-items: center;\n }\n \n button {\n width: 100%;\n max-width: 300px;\n }\n}\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const canvas = document.getElementById('goopCanvas');\n const ctx = canvas.getContext('2d');\n const colorBtn = document.getElementById('colorBtn');\n const viscosityBtn = document.getElementById('viscosityBtn');\n const resetBtn = document.getElementById('resetBtn');\n \n // Set canvas size\n function resizeCanvas() {\n const container = canvas.parentElement;\n canvas.width = container.clientWidth;\n canvas.height = container.clientHeight;\n }\n \n window.addEventListener('resize', resizeCanvas);\n resizeCanvas();\n \n // Goop simulation parameters\n let goop = {\n particles: [],\n color: getComputedStyle(document.documentElement).getPropertyValue('--goop-color'),\n viscosity: 0.95,\n particleCount: 150,\n maxSize: 30,\n minSize: 10\n };\n \n // Initialize particles\n function initParticles() {\n goop.particles = [];\n for (let i = 0; i < goop.particleCount; i++) {\n goop.particles.push({\n x: Math.random() * canvas.width,\n y: Math.random() * canvas.height,\n vx: Math.random() * 4 - 2,\n vy: Math.random() * 4 - 2,\n size: Math.random() * (goop.maxSize - goop.minSize) + goop.minSize,\n color: goop.color\n });\n }\n }\n \n // Update and draw particles\n function updateParticles() {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n \n for (let i = 0; i < goop.particles.length; i++) {\n const p = goop.particles[i];\n \n // Update position with viscosity\n p.x += p.vx;\n p.y += p.vy;\n \n // Bounce off walls\n if (p.x < 0 || p.x > canvas.width) p.vx *= -1;\n if (p.y < 0 || p.y > canvas.height) p.vy *= -1;\n \n // Apply viscosity\n p.vx *= goop.viscosity;\n p.vy *= goop.viscosity;\n \n // Draw particle\n ctx.beginPath();\n ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);\n ctx.fillStyle = p.color;\n ctx.fill();\n \n // Draw connections to nearby particles\n for (let j = i + 1; j < goop.particles.length; j++) {\n const p2 = goop.particles[j];\n const dx = p.x - p2.x;\n const dy = p.y - p2.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance < 100) {\n ctx.beginPath();\n ctx.moveTo(p.x, p.y);\n ctx.lineTo(p2.x, p2.y);\n ctx.strokeStyle = `${p.color}${Math.floor((1 - distance/100) * 50 + 50).toString(16).padStart(2, '0')}`;\n ctx.lineWidth = 1;\n ctx.stroke();\n }\n }\n }\n \n requestAnimationFrame(updateParticles);\n }\n \n // Button event handlers\n colorBtn.addEventListener('click', () => {\n const hue = Math.floor(Math.random() * 360);\n goop.color = `hsl(${hue}, 70%, 60%)`;\n goop.particles.forEach(p => {\n p.color = goop.color;\n });\n });\n \n viscosityBtn.addEventListener('click', () => {\n goop.viscosity = Math.random() * 0.2 + 0.8;\n });\n \n resetBtn.addEventListener('click', () => {\n initParticles();\n goop.viscosity = 0.95;\n goop.color = getComputedStyle(document.documentElement).getPropertyValue('--goop-color');\n });\n \n // Mouse interaction\n canvas.addEventListener('mousemove', (e) => {\n const rect = canvas.getBoundingClientRect();\n const mouseX = e.clientX - rect.left;\n const mouseY = e.clientY - rect.top;\n \n goop.particles.forEach(p => {\n const dx = mouseX - p.x;\n const dy = mouseY - p.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance < 150) {\n const force = 150 / distance;\n p.vx += dx * 0.0005 * force;\n p.vy += dy * 0.0005 * force;\n }\n });\n });\n \n // Touch interaction\n canvas.addEventListener('touchmove', (e) => {\n e.preventDefault();\n const rect = canvas.getBoundingClientRect();\n const touch = e.touches[0];\n const touchX = touch.clientX - rect.left;\n const touchY = touch.clientY - rect.top;\n \n goop.particles.forEach(p => {\n const dx = touchX - p.x;\n const dy = touchY - p.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance < 150) {\n const force = 150 / distance;\n p.vx += dx * 0.0005 * force;\n p.vy += dy * 0.0005 * force;\n }\n });\n }, { passive: false });\n \n // Initialize and start animation\n initParticles();\n updateParticles();\n});\n---end---"
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 722,
+ "completion_tokens": 2139,
+ "total_tokens": 2861,
+ "prompt_tokens_details": {
+ "cached_tokens": 0
+ },
+ "prompt_cache_hit_tokens": 0,
+ "prompt_cache_miss_tokens": 722
+ },
+ "system_fingerprint": "fp_8802369eaa_prod0425fp8"
+ }
readme.scroll
Changed around line 1
+ # goop.scroll.pub
+
+ Prompt: website
+ Agent: deepseek
+ Model: deepseek-chat
+
+ ## User prompt
+ unending amounts of goop
+
+ ## System prompt
+ You are an expert web developer. Create a website based on this request: "unending amounts of goop"
+
+ Requirements:
+ - Use only Scroll, CSS, and JavaScript (NO frameworks, NO external dependencies)
+ - Create clean, semantic HTML5
+ - Make it mobile-responsive
+ - Follow modern best practices and accessibility guidelines
+ - Keep it simple but professional
+ - Use only relative links and no external resources
+ - Do not put a copyright symbol or all rights reserved in the footer.
+ - Make it beautiful. Dazzling. Advanced used of CSS.
+
+ As a refresher, for doing the html body, Scroll is a whitespace based language that uses a single indented space to mark a line (aka particle) as a subparticle of a parent line.
+
+ For example:
+
+ header
+ class hero
+ nav
+ div Scroll
+ class logo
+ div
+ class nav-links
+ a Features
+ href #features
+ a Examples
+ href #examples
+ a Edit
+ href edit.html
+ a GitHub
+ class cta-button
+ href https://github.com/breck7/scroll
+ div
+ class hero-content
+ h1 Write Better with Scroll
+ p The extendible markup language that makes source beautiful and compiles to anything
+ a Get Started
+ class primary-button
+ href https://hub.scroll.pub/
+ main
+ section
+ id features
+ class features
+ h2 Why Scroll?
+ div
+ class feature-grid
+ div
+ class feature-card
+ div ⚡
+ class feature-icon
+ h3 Simple Syntax
+ p Like Markdown, but more powerful. No parentheses needed.
+ div
+ class feature-card
+ div 🧩
+ class feature-icon
+ h3 Extendible
+ p Build your own custom parsers.
+ div
+ class feature-card
+ div 🎨
+ class feature-icon
+ h3 Beautiful Output
+ p Create stunning documents with minimal effort.
+ div
+ class feature-card
+ div 🚀
+ class feature-icon
+ h3 Fast & Light
+ p Built on the efficient PPS Stack.
+ section
+ id examples
+ class code-demo
+ h2 See It In Action
+ div
+ class code-container
+ pre
+ class code-example
+ div
+ class code-output
+ footer
+ div
+ class footer-content
+ div
+ class footer-links
+ a Documentation
+ href https://scroll.pub/tutorial.html
+ a Community
+ href https://www.reddit.com/r/WorldWideScroll/
+ a Blog
+ href https://scroll.pub/blog
+ p Started by Breck Yunits. Evolved by a community.
+ https://twitter.com/breckyunits Breck Yunits
+ https://github.com/breck7/scroll/graphs/contributors community
+
+
+ First suggest a short, memorable domain name ending in scroll.pub that represents this website. Then provide the website files. Use this exact format:
+
+ ---domain---
+ (domainscroll.pub here)
+ ---index.scroll---
+ buildHtml
+ baseUrl https://(domainscroll.pub here)
+ metaTags
+ editButton /edit.html
+ title (Title here)
+ style.css
+
+ (body content here. no blank lines please.)
+
+ script.js
+ ---style.css---
+ (CSS content here)
+ ---script.js---
+ (JavaScript content here)
+ ---end---
script.js
Changed around line 1
+ document.addEventListener('DOMContentLoaded', () => {
+ const canvas = document.getElementById('goopCanvas');
+ const ctx = canvas.getContext('2d');
+ const colorBtn = document.getElementById('colorBtn');
+ const viscosityBtn = document.getElementById('viscosityBtn');
+ const resetBtn = document.getElementById('resetBtn');
+
+ // Set canvas size
+ function resizeCanvas() {
+ const container = canvas.parentElement;
+ canvas.width = container.clientWidth;
+ canvas.height = container.clientHeight;
+ }
+
+ window.addEventListener('resize', resizeCanvas);
+ resizeCanvas();
+
+ // Goop simulation parameters
+ let goop = {
+ particles: [],
+ color: getComputedStyle(document.documentElement).getPropertyValue('--goop-color'),
+ viscosity: 0.95,
+ particleCount: 150,
+ maxSize: 30,
+ minSize: 10
+ };
+
+ // Initialize particles
+ function initParticles() {
+ goop.particles = [];
+ for (let i = 0; i < goop.particleCount; i++) {
+ goop.particles.push({
+ x: Math.random() * canvas.width,
+ y: Math.random() * canvas.height,
+ vx: Math.random() * 4 - 2,
+ vy: Math.random() * 4 - 2,
+ size: Math.random() * (goop.maxSize - goop.minSize) + goop.minSize,
+ color: goop.color
+ });
+ }
+ }
+
+ // Update and draw particles
+ function updateParticles() {
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ for (let i = 0; i < goop.particles.length; i++) {
+ const p = goop.particles[i];
+
+ // Update position with viscosity
+ p.x += p.vx;
+ p.y += p.vy;
+
+ // Bounce off walls
+ if (p.x < 0 || p.x > canvas.width) p.vx *= -1;
+ if (p.y < 0 || p.y > canvas.height) p.vy *= -1;
+
+ // Apply viscosity
+ p.vx *= goop.viscosity;
+ p.vy *= goop.viscosity;
+
+ // Draw particle
+ ctx.beginPath();
+ ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
+ ctx.fillStyle = p.color;
+ ctx.fill();
+
+ // Draw connections to nearby particles
+ for (let j = i + 1; j < goop.particles.length; j++) {
+ const p2 = goop.particles[j];
+ const dx = p.x - p2.x;
+ const dy = p.y - p2.y;
+ const distance = Math.sqrt(dx * dx + dy * dy);
+
+ if (distance < 100) {
+ ctx.beginPath();
+ ctx.moveTo(p.x, p.y);
+ ctx.lineTo(p2.x, p2.y);
+ ctx.strokeStyle = `${p.color}${Math.floor((1 - distance/100) * 50 + 50).toString(16).padStart(2, '0')}`;
+ ctx.lineWidth = 1;
+ ctx.stroke();
+ }
+ }
+ }
+
+ requestAnimationFrame(updateParticles);
+ }
+
+ // Button event handlers
+ colorBtn.addEventListener('click', () => {
+ const hue = Math.floor(Math.random() * 360);
+ goop.color = `hsl(${hue}, 70%, 60%)`;
+ goop.particles.forEach(p => {
+ p.color = goop.color;
+ });
+ });
+
+ viscosityBtn.addEventListener('click', () => {
+ goop.viscosity = Math.random() * 0.2 + 0.8;
+ });
+
+ resetBtn.addEventListener('click', () => {
+ initParticles();
+ goop.viscosity = 0.95;
+ goop.color = getComputedStyle(document.documentElement).getPropertyValue('--goop-color');
+ });
+
+ // Mouse interaction
+ canvas.addEventListener('mousemove', (e) => {
+ const rect = canvas.getBoundingClientRect();
+ const mouseX = e.clientX - rect.left;
+ const mouseY = e.clientY - rect.top;
+
+ goop.particles.forEach(p => {
+ const dx = mouseX - p.x;
+ const dy = mouseY - p.y;
+ const distance = Math.sqrt(dx * dx + dy * dy);
+
+ if (distance < 150) {
+ const force = 150 / distance;
+ p.vx += dx * 0.0005 * force;
+ p.vy += dy * 0.0005 * force;
+ }
+ });
+ });
+
+ // Touch interaction
+ canvas.addEventListener('touchmove', (e) => {
+ e.preventDefault();
+ const rect = canvas.getBoundingClientRect();
+ const touch = e.touches[0];
+ const touchX = touch.clientX - rect.left;
+ const touchY = touch.clientY - rect.top;
+
+ goop.particles.forEach(p => {
+ const dx = touchX - p.x;
+ const dy = touchY - p.y;
+ const distance = Math.sqrt(dx * dx + dy * dy);
+
+ if (distance < 150) {
+ const force = 150 / distance;
+ p.vx += dx * 0.0005 * force;
+ p.vy += dy * 0.0005 * force;
+ }
+ });
+ }, { passive: false });
+
+ // Initialize and start animation
+ initParticles();
+ updateParticles();
+ });
style.css
Changed around line 1
+ :root {
+ --primary: #6c5ce7;
+ --secondary: #a29bfe;
+ --dark: #2d3436;
+ --light: #f5f6fa;
+ --goop-color: #00cec9;
+ }
+
+ * {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ body {
+ font-family: 'Segoe UI', system-ui, sans-serif;
+ line-height: 1.6;
+ color: var(--dark);
+ background-color: var(--light);
+ overflow-x: hidden;
+ }
+
+ .hero {
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
+ color: white;
+ padding: 4rem 1rem;
+ text-align: center;
+ position: relative;
+ overflow: hidden;
+ }
+
+ .hero-content {
+ max-width: 800px;
+ margin: 0 auto;
+ position: relative;
+ z-index: 2;
+ }
+
+ .hero h1 {
+ font-size: 3.5rem;
+ margin-bottom: 1rem;
+ font-weight: 800;
+ }
+
+ .hero p {
+ font-size: 1.25rem;
+ opacity: 0.9;
+ max-width: 600px;
+ margin: 0 auto;
+ }
+
+ .goop-container {
+ padding: 2rem 1rem;
+ max-width: 1200px;
+ margin: 0 auto;
+ }
+
+ .canvas-container {
+ width: 100%;
+ height: 70vh;
+ min-height: 500px;
+ border-radius: 12px;
+ overflow: hidden;
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
+ margin-bottom: 2rem;
+ background: white;
+ }
+
+ #goopCanvas {
+ width: 100%;
+ height: 100%;
+ display: block;
+ }
+
+ .controls {
+ display: flex;
+ gap: 1rem;
+ justify-content: center;
+ flex-wrap: wrap;
+ }
+
+ button {
+ padding: 0.75rem 1.5rem;
+ border: none;
+ border-radius: 50px;
+ background: var(--primary);
+ color: white;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+ }
+
+ button:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 6px 12px rgba(0,0,0,0.15);
+ }
+
+ button:active {
+ transform: translateY(0);
+ }
+
+ .footer-content {
+ text-align: center;
+ padding: 2rem 1rem;
+ color: var(--dark);
+ opacity: 0.7;
+ }
+
+ @media (max-width: 768px) {
+ .hero h1 {
+ font-size: 2.5rem;
+ }
+
+ .hero p {
+ font-size: 1.1rem;
+ }
+
+ .controls {
+ flex-direction: column;
+ align-items: center;
+ }
+
+ button {
+ width: 100%;
+ max-width: 300px;
+ }
+ }