Spaces:
Running
Running
Rewrite as a model reference page; drop auto-redirect and ad copy
Browse files- README.md +14 -5
- index.html +235 -215
- style.css +424 -550
- tabs.js +15 -0
README.md
CHANGED
|
@@ -1,15 +1,24 @@
|
|
| 1 |
---
|
| 2 |
title: Qwen-Image-Edit
|
| 3 |
emoji: 🖼️
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
-
|
|
|
|
| 9 |
---
|
| 10 |
|
| 11 |
# Qwen-Image-Edit
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: Qwen-Image-Edit
|
| 3 |
emoji: 🖼️
|
| 4 |
+
colorFrom: gray
|
| 5 |
+
colorTo: blue
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
license: apache-2.0
|
| 9 |
+
short_description: Reference for Qwen-Image-Edit, instruction-based editing
|
| 10 |
---
|
| 11 |
|
| 12 |
# Qwen-Image-Edit
|
| 13 |
|
| 14 |
+
A reference page for **Qwen-Image-Edit**, the instruction-driven image editing model from
|
| 15 |
+
Alibaba Cloud's Qwen team. It applies a written instruction to an existing image while
|
| 16 |
+
preserving identity, layout and unedited regions — including editing text already present
|
| 17 |
+
in a photograph.
|
| 18 |
|
| 19 |
+
- Weights: [Qwen/Qwen-Image-Edit](https://huggingface.co/Qwen/Qwen-Image-Edit) (Apache-2.0)
|
| 20 |
+
- Code: [QwenLM/Qwen-Image](https://github.com/QwenLM/Qwen-Image)
|
| 21 |
+
- Hosted inference: [qwen-image/edit](https://wavespeed.ai/models/wavespeed-ai/qwen-image/edit)
|
| 22 |
+
|
| 23 |
+
Qwen-Image-Edit is developed and released by the Alibaba Cloud Qwen team. This Space is
|
| 24 |
+
maintained by WaveSpeed AI, which provides hosted inference for the model.
|
index.html
CHANGED
|
@@ -1,224 +1,244 @@
|
|
| 1 |
-
<!
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
<meta name="author" content="Alibaba Cloud Qwen Team" />
|
| 19 |
-
<meta name="robots" content="index, follow" />
|
| 20 |
-
<link rel="canonical" href="https://huggingface.co/Qwen/Qwen-Image-Edit" />
|
| 21 |
-
|
| 22 |
-
<link rel="stylesheet" href="style.css" />
|
| 23 |
</head>
|
| 24 |
<body>
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
from PIL import Image
|
| 90 |
-
import torch
|
| 91 |
from diffusers import QwenImageEditPipeline
|
| 92 |
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
n=1, # Number of images to generate
|
| 137 |
-
size='1024*1024', # Image size
|
| 138 |
-
steps=50, # Diffusion steps
|
| 139 |
-
image='path/to/input_image.jpg' # Input image for editing
|
| 140 |
-
)
|
| 141 |
-
|
| 142 |
-
# Save the generated image
|
| 143 |
-
if response.status_code == 200:
|
| 144 |
-
with open('qwen_vlo_result.png', 'wb') as f:
|
| 145 |
-
f.write(response.output.images[0].image)
|
| 146 |
-
print('Image saved successfully!')
|
| 147 |
-
else:
|
| 148 |
-
print(f'Failed to generate image: {response.message}')</code></pre>
|
| 149 |
-
</div>
|
| 150 |
-
</section>
|
| 151 |
-
|
| 152 |
-
<section class="showcase-section">
|
| 153 |
-
<h2>Show Cases</h2>
|
| 154 |
-
|
| 155 |
-
<div class="showcase-item-full">
|
| 156 |
-
<div class="showcase-description-full">
|
| 157 |
-
<h3>Semantic Editing</h3>
|
| 158 |
-
<p>One of the highlights of Qwen-Image Edit lies in its powerful capabilities for semantic editing. It can modify image content while perfectly preserving the original visual semantics. For example, when editing character images like Qwen's mascot Capybara, the model maintains character consistency even when most pixels in the image are changed. This enables effortless and diverse creation of original IP content, such as MBTI-themed emoji packs based on mascot characters.</p>
|
| 159 |
-
</div>
|
| 160 |
-
<div class="showcase-image-full">
|
| 161 |
-
<img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/s1.jpg" alt="Semantic Editing Example" class="showcase-img-full">
|
| 162 |
-
</div>
|
| 163 |
-
</div>
|
| 164 |
-
|
| 165 |
-
<div class="showcase-item-full">
|
| 166 |
-
<div class="showcase-description-full">
|
| 167 |
-
<h3>Novel View Synthesis</h3>
|
| 168 |
-
<p>Qwen-Image Edit excels at novel view synthesis, a key application in semantic editing. The model can rotate objects by various angles, including 90-degree and even full 180-degree rotations, allowing users to see different sides of objects. This capability is particularly valuable for product visualization, architectural rendering, and creative content production where multiple perspectives are needed.</p>
|
| 169 |
-
</div>
|
| 170 |
-
<div class="showcase-image-full">
|
| 171 |
-
<img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/s2.jpg" alt="Novel View Synthesis Example" class="showcase-img-full">
|
| 172 |
-
</div>
|
| 173 |
-
</div>
|
| 174 |
-
|
| 175 |
-
<div class="showcase-item-full">
|
| 176 |
-
<div class="showcase-description-full">
|
| 177 |
-
<h3>Appearance Editing</h3>
|
| 178 |
-
<p>Appearance editing is another powerful capability of Qwen-Image Edit. The model can keep certain regions of an image completely unchanged while adding, removing, or modifying specific elements. For example, it can insert signboards into scenes with corresponding reflections, remove fine details like hair strands, change the color of specific elements, or adjust backgrounds and clothing in portraits—all with exceptional attention to detail and realism.</p>
|
| 179 |
-
</div>
|
| 180 |
-
<div class="showcase-image-full">
|
| 181 |
-
<img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/s3.jpg" alt="Appearance Editing Example" class="showcase-img-full">
|
| 182 |
-
</div>
|
| 183 |
-
</div>
|
| 184 |
-
|
| 185 |
-
<div class="showcase-item-full">
|
| 186 |
-
<div class="showcase-description-full">
|
| 187 |
-
<h3>Text Editing Excellence</h3>
|
| 188 |
-
<p>A standout feature of Qwen-Image Edit is its accurate text editing capability, which stems from Qwen-Image's deep expertise in text rendering. The model excels at editing both English and Chinese text in images, enabling modifications to large headline text as well as precise adjustments to small and intricate text elements. This makes it particularly valuable for poster design, advertisement creation, and multilingual content production.</p>
|
| 189 |
-
</div>
|
| 190 |
-
<div class="showcase-image-full">
|
| 191 |
-
<img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/s4.jpg" alt="Text Editing Example" class="showcase-img-full">
|
| 192 |
-
</div>
|
| 193 |
-
</div>
|
| 194 |
-
|
| 195 |
-
<div class="showcase-item-full">
|
| 196 |
-
<div class="showcase-description-full">
|
| 197 |
-
<h3>Progressive Editing</h3>
|
| 198 |
-
<p>Qwen-Image Edit supports chained, step-by-step editing approaches that allow users to progressively refine and correct images. For example, when editing complex calligraphy artwork, users can draw bounding boxes to mark specific regions that need correction and instruct the model to fix these areas one by one. This iterative approach enables precise control over the editing process, ensuring the desired final result is achieved even for challenging edits.</p>
|
| 199 |
-
</div>
|
| 200 |
-
<div class="showcase-image-full">
|
| 201 |
-
<img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/bench.png" alt="Progressive Editing Example" class="showcase-img-full">
|
| 202 |
-
</div>
|
| 203 |
-
</div>
|
| 204 |
-
|
| 205 |
-
<div class="showcase-conclusion">
|
| 206 |
-
<p>Together, these features make Qwen-Image Edit not just a tool for basic image editing, but a comprehensive foundation model for intelligent visual transformation—where existing images become the canvas for sophisticated artistic and creative manipulation.</p>
|
| 207 |
-
</div>
|
| 208 |
-
</section>
|
| 209 |
-
|
| 210 |
-
<div class="resource-links-section">
|
| 211 |
-
<h2>Resources</h2>
|
| 212 |
-
<div class="resource-links">
|
| 213 |
-
<a href="https://wavespeed.ai/models/wavespeed-ai/qwen-image/edit" target="_blank" rel="noopener noreferrer" class="resource-link">Qwen-Image Edit on WaveSpeed</a>
|
| 214 |
-
<a href="https://wavespeed.ai/models/wavespeed-ai/qwen-image" target="_blank" rel="noopener noreferrer" class="resource-link">Qwen-Image on WaveSpeed</a>
|
| 215 |
-
<a href="https://wavespeed.ai/" target="_blank" rel="noopener noreferrer" class="resource-link">WaveSpeed AI</a>
|
| 216 |
-
<a href="https://huggingface.co/Qwen/Qwen-Image-Edit" target="_blank" rel="noopener noreferrer" class="resource-link">Hugging Face</a>
|
| 217 |
-
<a href="https://modelscope.cn/models/qwen/Qwen-Image-Edit" target="_blank" rel="noopener noreferrer" class="resource-link">ModelScope</a>
|
| 218 |
-
<a href="https://chat.qwen.ai/" target="_blank" rel="noopener noreferrer" class="resource-link">Qwen Chat</a>
|
| 219 |
-
</div>
|
| 220 |
-
</div>
|
| 221 |
-
</div>
|
| 222 |
-
</div>
|
| 223 |
</body>
|
| 224 |
</html>
|
|
|
|
| 1 |
+
<!doctype html>
|
| 2 |
<html lang="en">
|
| 3 |
<head>
|
| 4 |
+
<meta charset="utf-8" />
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
| 6 |
+
<title>Qwen-Image-Edit — instruction-based image editing</title>
|
| 7 |
+
<meta name="description" content="Reference for Qwen-Image-Edit, Alibaba's open instruction-driven image editing model, with hosted API usage and local diffusers setup." />
|
| 8 |
+
<link rel="canonical" href="https://wavespeed.ai/models/wavespeed-ai/qwen-image/edit" />
|
| 9 |
+
|
| 10 |
+
<meta property="og:type" content="website" />
|
| 11 |
+
<meta property="og:title" content="Qwen-Image-Edit — instruction-based image editing" />
|
| 12 |
+
<meta property="og:description" content="Reference for Qwen-Image-Edit, Alibaba's open instruction-driven image editing model, with hosted API usage and local diffusers setup." />
|
| 13 |
+
<meta property="og:url" content="https://wavespeed.ai/models/wavespeed-ai/qwen-image/edit" />
|
| 14 |
+
<meta property="og:image" content="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/merge3.jpg" />
|
| 15 |
+
<meta name="twitter:card" content="summary_large_image" />
|
| 16 |
+
|
| 17 |
+
<link rel="stylesheet" href="style.css" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
</head>
|
| 19 |
<body>
|
| 20 |
+
<header class="site-header">
|
| 21 |
+
<div class="wrap">
|
| 22 |
+
<a class="brand" href="https://wavespeed.ai" target="_blank" rel="noopener">
|
| 23 |
+
<span class="brand-mark" aria-hidden="true"></span>
|
| 24 |
+
<span>WaveSpeed AI</span>
|
| 25 |
+
</a>
|
| 26 |
+
<nav class="header-nav">
|
| 27 |
+
<a class="jump opt" href="#overview">Overview</a>
|
| 28 |
+
<a class="jump opt" href="#edits">Edit types</a>
|
| 29 |
+
<a class="jump" href="#run">Run it</a>
|
| 30 |
+
<a class="jump opt" href="#local">Local</a>
|
| 31 |
+
<a class="jump" href="#resources">Resources</a>
|
| 32 |
+
<a href="https://wavespeed.ai/models/wavespeed-ai/qwen-image/edit" target="_blank" rel="noopener">wavespeed.ai ↗</a>
|
| 33 |
+
</nav>
|
| 34 |
+
</div>
|
| 35 |
+
</header>
|
| 36 |
+
|
| 37 |
+
<main class="wrap">
|
| 38 |
+
<div class="hero">
|
| 39 |
+
<p class="eyebrow">Alibaba Cloud · Qwen Team</p>
|
| 40 |
+
<h1>Qwen-Image-Edit</h1>
|
| 41 |
+
<p class="lede">The editing counterpart to Qwen-Image. It takes an existing image plus a written instruction and applies the change while leaving the rest of the frame — including identity and layout — intact.</p>
|
| 42 |
+
<ul class="meta">
|
| 43 |
+
<li><b>Developer</b> Alibaba Cloud Qwen Team</li>
|
| 44 |
+
<li><b>Task</b> instruction-based image editing</li>
|
| 45 |
+
<li><b>License</b> Apache-2.0</li>
|
| 46 |
+
<li><b>Weights</b> open</li>
|
| 47 |
+
</ul>
|
| 48 |
+
</div>
|
| 49 |
+
|
| 50 |
+
<section id="overview">
|
| 51 |
+
<h2>Overview</h2>
|
| 52 |
+
<p class="section-note">Editing is expressed as an instruction rather than a mask. The model inherits Qwen-Image's text rendering, which is what makes editing text already present in a photograph practical.</p>
|
| 53 |
+
<div class="figure-single">
|
| 54 |
+
<figure>
|
| 55 |
+
<img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/merge3.jpg" alt="Qwen-Image sample outputs" loading="lazy" />
|
| 56 |
+
<figcaption>Sample outputs from the Qwen-Image release.</figcaption>
|
| 57 |
+
</figure>
|
| 58 |
+
</div>
|
| 59 |
+
</section>
|
| 60 |
+
<section id="edits">
|
| 61 |
+
<h2>Edit types</h2>
|
| 62 |
+
<div class="grid">
|
| 63 |
+
<div class="card">
|
| 64 |
+
<h3>Semantic edits</h3>
|
| 65 |
+
<p>Change what is in the scene — add, remove or replace an object — while lighting and perspective stay consistent with the original.</p>
|
| 66 |
+
</div>
|
| 67 |
+
<div class="card">
|
| 68 |
+
<h3>Appearance edits</h3>
|
| 69 |
+
<p>Restyle or recolour without moving anything, so composition and structure survive the edit unchanged.</p>
|
| 70 |
+
</div>
|
| 71 |
+
<div class="card">
|
| 72 |
+
<h3>Text editing</h3>
|
| 73 |
+
<p>Replace words rendered inside the image while matching the existing font, perspective and surface — the capability inherited from Qwen-Image.</p>
|
| 74 |
+
</div>
|
| 75 |
+
<div class="card">
|
| 76 |
+
<h3>Identity preservation</h3>
|
| 77 |
+
<p>Faces and distinctive objects are held stable across the edit, which is what makes chained edits usable.</p>
|
| 78 |
+
</div>
|
| 79 |
+
</div>
|
| 80 |
+
</section>
|
| 81 |
+
<section id="variants">
|
| 82 |
+
<h2>Hosted variants</h2>
|
| 83 |
+
<div class="table-scroll">
|
| 84 |
+
<table>
|
| 85 |
+
<thead><tr><th>Endpoint</th><th>Notes</th></tr></thead>
|
| 86 |
+
<tbody>
|
| 87 |
+
<tr><td><code>wavespeed-ai/qwen-image/edit</code></td><td>Base instruction-driven editing.</td></tr>
|
| 88 |
+
<tr><td><code>wavespeed-ai/qwen-image/edit-plus</code></td><td>Updated editing checkpoint.</td></tr>
|
| 89 |
+
<tr><td><code>wavespeed-ai/qwen-image/edit-plus-lora</code></td><td>Editing with LoRA adapters applied.</td></tr>
|
| 90 |
+
</tbody>
|
| 91 |
+
</table>
|
| 92 |
+
</div>
|
| 93 |
+
</section>
|
| 94 |
+
<section id="run">
|
| 95 |
+
<h2>Run it</h2>
|
| 96 |
+
<p class="section-note">Pass a publicly reachable image URL, or upload first via <code>POST /media/upload/binary</code> and use the returned URL.</p>
|
| 97 |
+
<div class="code">
|
| 98 |
+
<div class="code-tabs" role="tablist">
|
| 99 |
+
<button type="button" role="tab" aria-selected="true" data-panel="run-0">cURL</button>
|
| 100 |
+
<button type="button" role="tab" aria-selected="false" data-panel="run-1">Python</button>
|
| 101 |
+
<button type="button" role="tab" aria-selected="false" data-panel="run-2">JavaScript</button>
|
| 102 |
+
</div>
|
| 103 |
+
<pre id="run-0" role="tabpanel"><code># 1. submit the job
|
| 104 |
+
curl -X POST "https://api.wavespeed.ai/api/v3/wavespeed-ai/qwen-image/edit" \
|
| 105 |
+
-H "Authorization: Bearer $WAVESPEED_API_KEY" \
|
| 106 |
+
-H "Content-Type: application/json" \
|
| 107 |
+
-d '{
|
| 108 |
+
"image": "https://example.com/input.jpg",
|
| 109 |
+
"prompt": "Replace the text on the sign with \"Open until 9pm\", keep the original font and perspective",
|
| 110 |
+
"enable_sync_mode": false
|
| 111 |
+
}'
|
| 112 |
+
|
| 113 |
+
# -> {"code": 200, "data": {"id": "<request-id>", "status": "created", ...}}
|
| 114 |
+
|
| 115 |
+
# 2. poll until status is "completed"
|
| 116 |
+
curl "https://api.wavespeed.ai/api/v3/predictions/<request-id>/result" \
|
| 117 |
+
-H "Authorization: Bearer $WAVESPEED_API_KEY"
|
| 118 |
+
|
| 119 |
+
# -> {"code": 200, "data": {"status": "completed", "outputs": ["https://..."]}}</code></pre>
|
| 120 |
+
<pre id="run-1" role="tabpanel" hidden><code>import os, time, requests
|
| 121 |
+
|
| 122 |
+
API = "https://api.wavespeed.ai/api/v3"
|
| 123 |
+
KEY = os.environ["WAVESPEED_API_KEY"]
|
| 124 |
+
HEADERS = {"Authorization": f"Bearer {KEY}"}
|
| 125 |
+
|
| 126 |
+
# submit
|
| 127 |
+
res = requests.post(
|
| 128 |
+
f"{API}/wavespeed-ai/qwen-image/edit",
|
| 129 |
+
headers={**HEADERS, "Content-Type": "application/json"},
|
| 130 |
+
json={
|
| 131 |
+
"image": "https://example.com/input.jpg",
|
| 132 |
+
"prompt": "Replace the text on the sign with \"Open until 9pm\", keep the original font and perspective",
|
| 133 |
+
"enable_sync_mode": false
|
| 134 |
+
},
|
| 135 |
+
timeout=30,
|
| 136 |
+
)
|
| 137 |
+
res.raise_for_status()
|
| 138 |
+
request_id = res.json()["data"]["id"]
|
| 139 |
+
|
| 140 |
+
# poll
|
| 141 |
+
while True:
|
| 142 |
+
data = requests.get(
|
| 143 |
+
f"{API}/predictions/{request_id}/result",
|
| 144 |
+
headers=HEADERS,
|
| 145 |
+
timeout=30,
|
| 146 |
+
).json()["data"]
|
| 147 |
+
|
| 148 |
+
if data["status"] == "completed":
|
| 149 |
+
print(data["outputs"][0])
|
| 150 |
+
break
|
| 151 |
+
if data["status"] == "failed":
|
| 152 |
+
raise RuntimeError(data.get("error", "generation failed"))
|
| 153 |
+
time.sleep(1.5)</code></pre>
|
| 154 |
+
<pre id="run-2" role="tabpanel" hidden><code>const API = "https://api.wavespeed.ai/api/v3";
|
| 155 |
+
const KEY = process.env.WAVESPEED_API_KEY;
|
| 156 |
+
const headers = { Authorization: `Bearer ${KEY}` };
|
| 157 |
+
|
| 158 |
+
// submit
|
| 159 |
+
const submit = await fetch(`${API}/wavespeed-ai/qwen-image/edit`, {
|
| 160 |
+
method: "POST",
|
| 161 |
+
headers: { ...headers, "Content-Type": "application/json" },
|
| 162 |
+
body: JSON.stringify({
|
| 163 |
+
"image": "https://example.com/input.jpg",
|
| 164 |
+
"prompt": "Replace the text on the sign with \"Open until 9pm\", keep the original font and perspective",
|
| 165 |
+
"enable_sync_mode": false
|
| 166 |
+
}),
|
| 167 |
+
});
|
| 168 |
+
const { data: { id } } = await submit.json();
|
| 169 |
+
|
| 170 |
+
// poll
|
| 171 |
+
for (;;) {
|
| 172 |
+
const res = await fetch(`${API}/predictions/${id}/result`, { headers });
|
| 173 |
+
const { data } = await res.json();
|
| 174 |
+
|
| 175 |
+
if (data.status === "completed") {
|
| 176 |
+
console.log(data.outputs[0]);
|
| 177 |
+
break;
|
| 178 |
+
}
|
| 179 |
+
if (data.status === "failed") throw new Error(data.error ?? "generation failed");
|
| 180 |
+
await new Promise((r) => setTimeout(r, 1500));
|
| 181 |
+
}</code></pre>
|
| 182 |
+
</div>
|
| 183 |
+
<div class="callout"><p>Requests are asynchronous: <code>POST</code> returns a request id, then you poll <code>/predictions/<id>/result</code> until <code>status</code> is <code>completed</code>. Set <code>enable_sync_mode: true</code> to have the call block and return outputs directly.</p><p>API keys are created in the <a href="https://wavespeed.ai/dashboard" target="_blank" rel="noopener">WaveSpeed dashboard</a>.</p></div>
|
| 184 |
+
<div class="btn-row">
|
| 185 |
+
<a class="btn" href="https://wavespeed.ai/models/wavespeed-ai/qwen-image/edit" target="_blank" rel="noopener">Open on WaveSpeed</a>
|
| 186 |
+
<a class="btn secondary" href="https://wavespeed.ai/docs" target="_blank" rel="noopener">API reference</a>
|
| 187 |
+
</div>
|
| 188 |
+
</section>
|
| 189 |
+
<section id="local">
|
| 190 |
+
<h2>Running locally</h2>
|
| 191 |
+
<p class="section-note">Weights are Apache-2.0 and load through <code>diffusers</code>.</p>
|
| 192 |
+
<div class="code">
|
| 193 |
+
<div class="code-tabs" role="tablist">
|
| 194 |
+
<button type="button" role="tab" aria-selected="true" data-panel="local-0">Python</button>
|
| 195 |
+
</div>
|
| 196 |
+
<pre id="local-0" role="tabpanel"><code>import torch
|
| 197 |
from PIL import Image
|
|
|
|
| 198 |
from diffusers import QwenImageEditPipeline
|
| 199 |
|
| 200 |
+
pipe = QwenImageEditPipeline.from_pretrained(
|
| 201 |
+
"Qwen/Qwen-Image-Edit",
|
| 202 |
+
torch_dtype=torch.bfloat16,
|
| 203 |
+
).to("cuda")
|
| 204 |
+
|
| 205 |
+
image = Image.open("input.jpg").convert("RGB")
|
| 206 |
+
|
| 207 |
+
out = pipe(
|
| 208 |
+
image=image,
|
| 209 |
+
prompt='Replace the text on the sign with "Open until 9pm", '
|
| 210 |
+
"keep the original font and perspective",
|
| 211 |
+
negative_prompt=" ",
|
| 212 |
+
num_inference_steps=50,
|
| 213 |
+
true_cfg_scale=4.0,
|
| 214 |
+
generator=torch.Generator(device="cuda").manual_seed(42),
|
| 215 |
+
).images[0]
|
| 216 |
+
|
| 217 |
+
out.save("edited.png")</code></pre>
|
| 218 |
+
</div>
|
| 219 |
+
</section>
|
| 220 |
+
<section id="resources">
|
| 221 |
+
<h2>Resources</h2>
|
| 222 |
+
<ul class="links">
|
| 223 |
+
<li><a href="https://huggingface.co/Qwen/Qwen-Image-Edit" target="_blank" rel="noopener"><span>Qwen/Qwen-Image-Edit weights</span><span class="host">huggingface.co</span></a></li>
|
| 224 |
+
<li><a href="https://github.com/QwenLM/Qwen-Image" target="_blank" rel="noopener"><span>Qwen-Image on GitHub</span><span class="host">github.com</span></a></li>
|
| 225 |
+
<li><a href="https://wavespeed.ai/models/wavespeed-ai/qwen-image/edit" target="_blank" rel="noopener"><span>Hosted endpoint</span><span class="host">wavespeed.ai</span></a></li>
|
| 226 |
+
<li><a href="https://huggingface.co/spaces/wavespeed/qwen-image" target="_blank" rel="noopener"><span>Text-to-image variant</span><span class="host">huggingface.co</span></a></li>
|
| 227 |
+
</ul>
|
| 228 |
+
</section>
|
| 229 |
+
</main>
|
| 230 |
+
|
| 231 |
+
<footer class="site-footer">
|
| 232 |
+
<div class="wrap">
|
| 233 |
+
<p>This page is a model reference maintained by WaveSpeed AI. The model itself is developed and released by its respective authors; trademarks belong to them. WaveSpeed AI provides hosted inference for it.</p>
|
| 234 |
+
<div class="footer-links">
|
| 235 |
+
<a href="https://wavespeed.ai" target="_blank" rel="noopener">WaveSpeed AI</a>
|
| 236 |
+
<a href="https://wavespeed.ai/docs" target="_blank" rel="noopener">Docs</a>
|
| 237 |
+
<a href="https://huggingface.co/wavespeed" target="_blank" rel="noopener">Hugging Face</a>
|
| 238 |
+
</div>
|
| 239 |
+
</div>
|
| 240 |
+
</footer>
|
| 241 |
+
|
| 242 |
+
<script src="tabs.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
</body>
|
| 244 |
</html>
|
style.css
CHANGED
|
@@ -1,701 +1,575 @@
|
|
| 1 |
-
/*
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
}
|
| 13 |
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
|
|
|
| 21 |
}
|
| 22 |
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
color: white;
|
| 27 |
-
letter-spacing: 2px;
|
| 28 |
}
|
| 29 |
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
gap: 2rem;
|
| 33 |
-
align-items: center;
|
| 34 |
}
|
| 35 |
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
}
|
| 42 |
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
|
| 45 |
}
|
| 46 |
|
| 47 |
-
.
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
border-radius: 20px;
|
| 52 |
-
text-decoration: none;
|
| 53 |
-
font-size: 0.95rem;
|
| 54 |
-
font-weight: 500;
|
| 55 |
-
transition: all 0.3s ease;
|
| 56 |
}
|
| 57 |
|
| 58 |
-
|
| 59 |
-
background: #1976D2;
|
| 60 |
-
transform: translateY(-1px);
|
| 61 |
-
}
|
| 62 |
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
color: white;
|
| 70 |
-
min-height: 100vh;
|
| 71 |
-
display: flex;
|
| 72 |
-
align-items: center;
|
| 73 |
-
justify-content: center;
|
| 74 |
}
|
| 75 |
|
| 76 |
-
.
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
}
|
| 83 |
|
| 84 |
-
.
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
}
|
| 87 |
|
| 88 |
-
.
|
| 89 |
-
|
| 90 |
}
|
| 91 |
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
-webkit-text-fill-color: transparent;
|
| 100 |
-
text-shadow: 0 0 30px rgba(255,255,255,0.1);
|
| 101 |
}
|
| 102 |
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
|
|
|
| 109 |
}
|
| 110 |
|
| 111 |
-
.
|
| 112 |
-
|
|
|
|
|
|
|
|
|
|
| 113 |
}
|
| 114 |
|
| 115 |
-
.
|
| 116 |
-
|
| 117 |
-
color: #2196F3;
|
| 118 |
-
margin: 1rem 0;
|
| 119 |
-
font-weight: bold;
|
| 120 |
-
text-shadow: 0 0 10px rgba(33,150,243,0.3);
|
| 121 |
}
|
| 122 |
|
| 123 |
-
.
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
margin: 2rem auto;
|
| 127 |
-
width: 60%;
|
| 128 |
}
|
| 129 |
|
| 130 |
-
.
|
| 131 |
-
|
| 132 |
-
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| 133 |
-
gap: 2rem;
|
| 134 |
-
margin: 3rem 0;
|
| 135 |
}
|
| 136 |
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
transition: transform 0.3s ease;
|
| 142 |
}
|
| 143 |
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
| 147 |
}
|
| 148 |
|
| 149 |
-
|
| 150 |
-
font-size: 1.2rem;
|
| 151 |
-
margin: 0 0 1rem 0;
|
| 152 |
-
color: #fff;
|
| 153 |
-
}
|
| 154 |
|
| 155 |
-
.
|
| 156 |
-
|
| 157 |
-
font-size: 0.95rem;
|
| 158 |
-
line-height: 1.5;
|
| 159 |
-
margin: 0;
|
| 160 |
}
|
| 161 |
|
| 162 |
-
.
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
|
|
|
|
|
|
| 167 |
}
|
| 168 |
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
|
|
|
| 174 |
}
|
| 175 |
|
| 176 |
-
.
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
|
|
|
| 180 |
}
|
| 181 |
|
| 182 |
-
|
| 183 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
}
|
| 185 |
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
|
|
|
|
|
|
| 192 |
}
|
| 193 |
|
| 194 |
-
.
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
}
|
| 199 |
|
| 200 |
-
.
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
align-items: center;
|
| 204 |
-
padding: 1rem;
|
| 205 |
-
background: rgba(255,255,255,0.05);
|
| 206 |
-
border-radius: 8px;
|
| 207 |
-
text-decoration: none;
|
| 208 |
-
transition: all 0.3s ease;
|
| 209 |
}
|
| 210 |
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
|
|
|
| 214 |
}
|
| 215 |
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
|
|
|
|
|
|
|
|
|
| 219 |
}
|
| 220 |
|
| 221 |
-
.
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
border-radius: 12px;
|
| 227 |
-
font-weight: 500;
|
| 228 |
}
|
| 229 |
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
border: 1px solid rgba(33,150,243,0.2);
|
| 236 |
}
|
| 237 |
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
font-size: 1.2rem;
|
| 241 |
-
margin: 0 0 1rem 0;
|
| 242 |
}
|
| 243 |
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
|
|
|
|
|
|
| 249 |
}
|
| 250 |
|
| 251 |
-
.
|
| 252 |
-
|
|
|
|
|
|
|
|
|
|
| 253 |
}
|
| 254 |
|
| 255 |
-
.
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
}
|
| 261 |
|
| 262 |
-
.
|
| 263 |
-
|
| 264 |
-
height: 4px;
|
| 265 |
-
background: rgba(255,255,255,0.1);
|
| 266 |
-
border-radius: 2px;
|
| 267 |
-
margin: 1rem auto;
|
| 268 |
-
overflow: hidden;
|
| 269 |
}
|
| 270 |
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 275 |
}
|
| 276 |
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
color: white;
|
| 282 |
-
text-decoration: none;
|
| 283 |
-
border-radius: 25px;
|
| 284 |
-
font-weight: bold;
|
| 285 |
-
margin-top: 1rem;
|
| 286 |
-
transition: all 0.3s ease;
|
| 287 |
}
|
| 288 |
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
|
|
|
|
|
|
|
|
|
| 292 |
}
|
| 293 |
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
background: rgba(255,255,255,0.03);
|
| 298 |
-
border-radius: 16px;
|
| 299 |
}
|
| 300 |
|
| 301 |
-
.
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
display: flex;
|
| 306 |
-
flex-wrap: wrap;
|
| 307 |
-
justify-content: center;
|
| 308 |
-
gap: 1rem;
|
| 309 |
-
align-items: center;
|
| 310 |
}
|
| 311 |
|
| 312 |
-
.
|
| 313 |
-
|
| 314 |
-
margin-right: 0.5rem;
|
| 315 |
}
|
| 316 |
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
border-radius: 20px;
|
| 324 |
-
font-weight: 500;
|
| 325 |
}
|
| 326 |
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
|
|
|
| 331 |
}
|
| 332 |
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
}
|
| 339 |
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
}
|
| 349 |
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
line-height: 1.6;
|
| 353 |
-
font-size: 1.1rem;
|
| 354 |
}
|
| 355 |
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
margin: 30px 0;
|
| 359 |
-
border-radius: 12px;
|
| 360 |
-
overflow: hidden;
|
| 361 |
-
box-shadow: 0 10px 30px rgba(0,0,0,0.15);
|
| 362 |
}
|
| 363 |
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
|
|
|
|
|
|
| 370 |
}
|
| 371 |
|
| 372 |
-
.
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
|
|
|
|
|
|
| 376 |
}
|
| 377 |
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 385 |
}
|
| 386 |
|
| 387 |
-
.
|
| 388 |
-
|
| 389 |
-
flex-direction: column;
|
| 390 |
-
gap: 1rem;
|
| 391 |
}
|
| 392 |
|
| 393 |
-
.
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
border-bottom: 1px solid rgba(255,255,255,0.1);
|
| 399 |
}
|
| 400 |
|
| 401 |
-
.
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
}
|
| 406 |
|
| 407 |
-
.
|
| 408 |
-
|
| 409 |
}
|
| 410 |
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
transition: color 0.3s ease;
|
| 415 |
}
|
| 416 |
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
|
|
|
|
|
|
|
|
|
| 420 |
}
|
| 421 |
|
| 422 |
-
/*
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
|
|
|
|
|
|
| 429 |
}
|
| 430 |
|
| 431 |
-
.
|
| 432 |
-
|
| 433 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 434 |
}
|
| 435 |
|
| 436 |
-
.
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
border-radius: 8px;
|
| 441 |
-
overflow-x: auto;
|
| 442 |
}
|
| 443 |
|
| 444 |
-
.
|
| 445 |
-
|
|
|
|
|
|
|
|
|
|
| 446 |
}
|
| 447 |
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
}
|
| 454 |
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
margin: 3rem 0;
|
| 458 |
-
padding: 1.5rem;
|
| 459 |
-
background: rgba(255,255,255,0.03);
|
| 460 |
-
border-radius: 16px;
|
| 461 |
-
text-align: left;
|
| 462 |
}
|
| 463 |
|
| 464 |
-
.
|
| 465 |
-
|
| 466 |
-
display: grid;
|
| 467 |
}
|
| 468 |
|
| 469 |
-
.
|
| 470 |
-
|
|
|
|
|
|
|
|
|
|
| 471 |
}
|
| 472 |
|
| 473 |
-
.
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
|
|
|
| 484 |
}
|
| 485 |
|
| 486 |
-
.
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
object-fit: cover;
|
| 490 |
-
border-radius: 8px;
|
| 491 |
-
transition: transform 0.3s ease;
|
| 492 |
}
|
| 493 |
|
| 494 |
-
.
|
| 495 |
-
|
|
|
|
|
|
|
| 496 |
}
|
| 497 |
|
| 498 |
-
.
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
margin-bottom: 80px;
|
| 502 |
-
width: 100%;
|
| 503 |
}
|
| 504 |
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
margin-left: auto;
|
| 510 |
-
margin-right: auto;
|
| 511 |
-
padding: 0 20px;
|
| 512 |
}
|
| 513 |
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 518 |
}
|
| 519 |
|
| 520 |
-
.
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
}
|
| 527 |
|
| 528 |
-
.
|
| 529 |
-
|
| 530 |
-
height: auto;
|
| 531 |
-
object-fit: cover;
|
| 532 |
-
display: block;
|
| 533 |
-
transition: transform 0.5s ease;
|
| 534 |
}
|
| 535 |
|
| 536 |
-
.
|
| 537 |
-
|
|
|
|
| 538 |
}
|
| 539 |
|
| 540 |
-
.
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
border-radius: 8px;
|
| 545 |
-
border-left: 4px solid #2196F3;
|
| 546 |
-
}
|
| 547 |
-
|
| 548 |
-
.showcase-conclusion p {
|
| 549 |
-
color: #fff;
|
| 550 |
-
font-size: 1.1rem;
|
| 551 |
-
line-height: 1.6;
|
| 552 |
-
margin: 0;
|
| 553 |
-
}
|
| 554 |
-
|
| 555 |
-
.highlight-link {
|
| 556 |
-
display: inline-block;
|
| 557 |
-
padding: 0.6rem 1.2rem;
|
| 558 |
-
background: rgba(33,150,243,0.1);
|
| 559 |
-
border: 1px solid rgba(33,150,243,0.3);
|
| 560 |
-
border-radius: 8px;
|
| 561 |
-
color: #2196F3;
|
| 562 |
-
text-decoration: none;
|
| 563 |
-
font-size: 0.9rem;
|
| 564 |
-
font-weight: 500;
|
| 565 |
-
transition: all 0.3s ease;
|
| 566 |
-
}
|
| 567 |
-
|
| 568 |
-
.highlight-link:hover {
|
| 569 |
-
background: rgba(33,150,243,0.2);
|
| 570 |
-
transform: translateY(-2px);
|
| 571 |
-
}
|
| 572 |
-
|
| 573 |
-
@keyframes fadeIn {
|
| 574 |
-
from { opacity: 0; transform: translateY(-20px); }
|
| 575 |
-
to { opacity: 1; transform: translateY(0); }
|
| 576 |
-
}
|
| 577 |
-
|
| 578 |
-
@keyframes pulse {
|
| 579 |
-
0% { opacity: 0.6; }
|
| 580 |
-
50% { opacity: 1; }
|
| 581 |
-
100% { opacity: 0.6; }
|
| 582 |
-
}
|
| 583 |
-
|
| 584 |
-
@keyframes progress {
|
| 585 |
-
from { width: 0; }
|
| 586 |
-
to { width: 100%; }
|
| 587 |
-
}
|
| 588 |
-
|
| 589 |
-
@media (max-width: 768px) {
|
| 590 |
-
.nav-content {
|
| 591 |
-
padding: 0 1rem;
|
| 592 |
-
}
|
| 593 |
-
|
| 594 |
-
.nav-links {
|
| 595 |
-
gap: 1rem;
|
| 596 |
-
}
|
| 597 |
-
|
| 598 |
-
.nav-link {
|
| 599 |
-
display: none;
|
| 600 |
-
}
|
| 601 |
-
|
| 602 |
-
.nav-button {
|
| 603 |
-
display: block;
|
| 604 |
-
}
|
| 605 |
-
}
|
| 606 |
-
|
| 607 |
-
@media (max-width: 600px) {
|
| 608 |
-
h1 {
|
| 609 |
-
font-size: 2.5rem;
|
| 610 |
-
}
|
| 611 |
-
|
| 612 |
-
h2 {
|
| 613 |
-
font-size: 1.8rem;
|
| 614 |
-
}
|
| 615 |
-
|
| 616 |
-
.announcement {
|
| 617 |
-
font-size: 1.5rem;
|
| 618 |
-
}
|
| 619 |
-
|
| 620 |
-
.features-section {
|
| 621 |
-
grid-template-columns: 1fr;
|
| 622 |
-
gap: 1rem;
|
| 623 |
-
}
|
| 624 |
-
|
| 625 |
-
.container {
|
| 626 |
-
padding: 1rem;
|
| 627 |
-
}
|
| 628 |
-
|
| 629 |
-
.models-section {
|
| 630 |
-
padding: 1rem;
|
| 631 |
-
}
|
| 632 |
-
|
| 633 |
-
.models-grid {
|
| 634 |
-
grid-template-columns: 1fr;
|
| 635 |
-
gap: 1rem;
|
| 636 |
-
}
|
| 637 |
-
|
| 638 |
-
.model-link {
|
| 639 |
-
padding: 0.8rem;
|
| 640 |
-
}
|
| 641 |
-
|
| 642 |
-
.model-highlight {
|
| 643 |
-
margin-top: 1.5rem;
|
| 644 |
-
padding: 1rem;
|
| 645 |
-
}
|
| 646 |
-
|
| 647 |
-
.highlight-links {
|
| 648 |
-
flex-direction: column;
|
| 649 |
-
gap: 0.8rem;
|
| 650 |
-
}
|
| 651 |
-
|
| 652 |
-
.intro-section,
|
| 653 |
-
.news-section,
|
| 654 |
-
.quickstart-section,
|
| 655 |
-
.showcase-section,
|
| 656 |
-
.resource-links-section {
|
| 657 |
-
padding: 1rem;
|
| 658 |
-
margin: 1.5rem 0;
|
| 659 |
-
}
|
| 660 |
-
|
| 661 |
-
.code-block {
|
| 662 |
-
padding: 0.5rem;
|
| 663 |
-
}
|
| 664 |
-
|
| 665 |
-
.showcase-image {
|
| 666 |
-
height: auto;
|
| 667 |
-
max-height: 300px;
|
| 668 |
-
}
|
| 669 |
-
|
| 670 |
-
.showcase-description-full {
|
| 671 |
-
padding: 0 15px;
|
| 672 |
-
margin-bottom: 20px;
|
| 673 |
-
}
|
| 674 |
-
|
| 675 |
-
.showcase-image-full {
|
| 676 |
-
border-radius: 8px;
|
| 677 |
-
}
|
| 678 |
-
|
| 679 |
-
.showcase-item-full {
|
| 680 |
-
margin-bottom: 50px;
|
| 681 |
-
}
|
| 682 |
-
|
| 683 |
-
.hero-image img,
|
| 684 |
-
.benchmark-image img {
|
| 685 |
-
border-radius: 8px;
|
| 686 |
-
}
|
| 687 |
-
|
| 688 |
-
.news-item {
|
| 689 |
-
flex-direction: column;
|
| 690 |
-
gap: 0.3rem;
|
| 691 |
-
}
|
| 692 |
-
|
| 693 |
-
.resource-links {
|
| 694 |
-
flex-direction: column;
|
| 695 |
-
gap: 0.8rem;
|
| 696 |
-
}
|
| 697 |
-
|
| 698 |
-
.highlight-link {
|
| 699 |
-
text-align: center;
|
| 700 |
-
}
|
| 701 |
}
|
|
|
|
| 1 |
+
/* ==========================================================================
|
| 2 |
+
Shared stylesheet for wavespeed model reference pages.
|
| 3 |
+
Edit here, then run _shared/sync.sh to copy into each Space.
|
| 4 |
+
========================================================================== */
|
| 5 |
+
|
| 6 |
+
:root {
|
| 7 |
+
--bg: #ffffff;
|
| 8 |
+
--bg-soft: #f7f8fa;
|
| 9 |
+
--bg-code: #f4f5f7;
|
| 10 |
+
--fg: #14161a;
|
| 11 |
+
--fg-muted: #5b6270;
|
| 12 |
+
--fg-faint: #868d9b;
|
| 13 |
+
--line: #e4e6eb;
|
| 14 |
+
--line-strong: #d2d6de;
|
| 15 |
+
--accent: #2f5bd7;
|
| 16 |
+
--accent-soft: #eef2fd;
|
| 17 |
+
--radius: 10px;
|
| 18 |
+
--radius-sm: 6px;
|
| 19 |
+
--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
| 20 |
+
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
|
| 21 |
+
"Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
| 22 |
+
--maxw: 880px;
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
@media (prefers-color-scheme: dark) {
|
| 26 |
+
:root {
|
| 27 |
+
--bg: #0e1014;
|
| 28 |
+
--bg-soft: #161920;
|
| 29 |
+
--bg-code: #14171d;
|
| 30 |
+
--fg: #e7e9ee;
|
| 31 |
+
--fg-muted: #99a1b0;
|
| 32 |
+
--fg-faint: #6f7788;
|
| 33 |
+
--line: #252a33;
|
| 34 |
+
--line-strong: #333a46;
|
| 35 |
+
--accent: #7ba1ff;
|
| 36 |
+
--accent-soft: #172136;
|
| 37 |
+
}
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
*,
|
| 41 |
+
*::before,
|
| 42 |
+
*::after {
|
| 43 |
+
box-sizing: border-box;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
html {
|
| 47 |
+
-webkit-text-size-adjust: 100%;
|
| 48 |
+
scroll-behavior: smooth;
|
| 49 |
}
|
| 50 |
|
| 51 |
+
body {
|
| 52 |
+
margin: 0;
|
| 53 |
+
background: var(--bg);
|
| 54 |
+
color: var(--fg);
|
| 55 |
+
font-family: var(--sans);
|
| 56 |
+
font-size: 16px;
|
| 57 |
+
line-height: 1.65;
|
| 58 |
+
-webkit-font-smoothing: antialiased;
|
| 59 |
}
|
| 60 |
|
| 61 |
+
a {
|
| 62 |
+
color: var(--accent);
|
| 63 |
+
text-decoration: none;
|
|
|
|
|
|
|
| 64 |
}
|
| 65 |
|
| 66 |
+
a:hover {
|
| 67 |
+
text-decoration: underline;
|
|
|
|
|
|
|
| 68 |
}
|
| 69 |
|
| 70 |
+
img,
|
| 71 |
+
video {
|
| 72 |
+
max-width: 100%;
|
| 73 |
+
height: auto;
|
| 74 |
+
display: block;
|
| 75 |
}
|
| 76 |
|
| 77 |
+
hr {
|
| 78 |
+
border: 0;
|
| 79 |
+
border-top: 1px solid var(--line);
|
| 80 |
+
margin: 3rem 0;
|
| 81 |
}
|
| 82 |
|
| 83 |
+
.wrap {
|
| 84 |
+
max-width: var(--maxw);
|
| 85 |
+
margin: 0 auto;
|
| 86 |
+
padding: 0 20px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
}
|
| 88 |
|
| 89 |
+
/* --- header ------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
+
.site-header {
|
| 92 |
+
border-bottom: 1px solid var(--line);
|
| 93 |
+
background: var(--bg);
|
| 94 |
+
position: sticky;
|
| 95 |
+
top: 0;
|
| 96 |
+
z-index: 20;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
}
|
| 98 |
|
| 99 |
+
.site-header .wrap {
|
| 100 |
+
display: flex;
|
| 101 |
+
align-items: center;
|
| 102 |
+
justify-content: space-between;
|
| 103 |
+
gap: 16px;
|
| 104 |
+
height: 56px;
|
| 105 |
}
|
| 106 |
|
| 107 |
+
.brand {
|
| 108 |
+
display: flex;
|
| 109 |
+
align-items: center;
|
| 110 |
+
gap: 9px;
|
| 111 |
+
font-weight: 600;
|
| 112 |
+
font-size: 0.9rem;
|
| 113 |
+
color: var(--fg);
|
| 114 |
+
letter-spacing: -0.01em;
|
| 115 |
}
|
| 116 |
|
| 117 |
+
.brand:hover {
|
| 118 |
+
text-decoration: none;
|
| 119 |
}
|
| 120 |
|
| 121 |
+
.brand-mark {
|
| 122 |
+
width: 20px;
|
| 123 |
+
height: 20px;
|
| 124 |
+
border-radius: 5px;
|
| 125 |
+
background: var(--accent);
|
| 126 |
+
flex: 0 0 auto;
|
| 127 |
+
position: relative;
|
|
|
|
|
|
|
| 128 |
}
|
| 129 |
|
| 130 |
+
.brand-mark::after {
|
| 131 |
+
content: "";
|
| 132 |
+
position: absolute;
|
| 133 |
+
inset: 6px 4px;
|
| 134 |
+
border-left: 2px solid var(--bg);
|
| 135 |
+
border-right: 2px solid var(--bg);
|
| 136 |
+
opacity: 0.85;
|
| 137 |
}
|
| 138 |
|
| 139 |
+
.header-nav {
|
| 140 |
+
display: flex;
|
| 141 |
+
align-items: center;
|
| 142 |
+
gap: 20px;
|
| 143 |
+
font-size: 0.86rem;
|
| 144 |
}
|
| 145 |
|
| 146 |
+
.header-nav a {
|
| 147 |
+
color: var(--fg-muted);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
}
|
| 149 |
|
| 150 |
+
.header-nav a:hover {
|
| 151 |
+
color: var(--fg);
|
| 152 |
+
text-decoration: none;
|
|
|
|
|
|
|
| 153 |
}
|
| 154 |
|
| 155 |
+
.brand span:last-child {
|
| 156 |
+
white-space: nowrap;
|
|
|
|
|
|
|
|
|
|
| 157 |
}
|
| 158 |
|
| 159 |
+
@media (max-width: 760px) {
|
| 160 |
+
.header-nav a.opt {
|
| 161 |
+
display: none;
|
| 162 |
+
}
|
|
|
|
| 163 |
}
|
| 164 |
|
| 165 |
+
/* On phones the in-page anchors aren't worth the crowding — the page is short
|
| 166 |
+
enough to scroll, and the one outbound link needs the room. */
|
| 167 |
+
@media (max-width: 560px) {
|
| 168 |
+
.header-nav a.jump {
|
| 169 |
+
display: none;
|
| 170 |
+
}
|
| 171 |
}
|
| 172 |
|
| 173 |
+
/* --- hero --------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
|
| 175 |
+
.hero {
|
| 176 |
+
padding: 56px 0 12px;
|
|
|
|
|
|
|
|
|
|
| 177 |
}
|
| 178 |
|
| 179 |
+
.eyebrow {
|
| 180 |
+
font-size: 0.72rem;
|
| 181 |
+
font-weight: 600;
|
| 182 |
+
letter-spacing: 0.08em;
|
| 183 |
+
text-transform: uppercase;
|
| 184 |
+
color: var(--fg-faint);
|
| 185 |
+
margin: 0 0 14px;
|
| 186 |
}
|
| 187 |
|
| 188 |
+
h1 {
|
| 189 |
+
font-size: 2.6rem;
|
| 190 |
+
line-height: 1.15;
|
| 191 |
+
letter-spacing: -0.025em;
|
| 192 |
+
font-weight: 700;
|
| 193 |
+
margin: 0 0 14px;
|
| 194 |
}
|
| 195 |
|
| 196 |
+
.lede {
|
| 197 |
+
font-size: 1.12rem;
|
| 198 |
+
color: var(--fg-muted);
|
| 199 |
+
margin: 0;
|
| 200 |
+
max-width: 68ch;
|
| 201 |
}
|
| 202 |
|
| 203 |
+
@media (max-width: 620px) {
|
| 204 |
+
h1 {
|
| 205 |
+
font-size: 2rem;
|
| 206 |
+
}
|
| 207 |
+
.hero {
|
| 208 |
+
padding-top: 36px;
|
| 209 |
+
}
|
| 210 |
}
|
| 211 |
|
| 212 |
+
/* metadata strip under the title */
|
| 213 |
+
.meta {
|
| 214 |
+
display: flex;
|
| 215 |
+
flex-wrap: wrap;
|
| 216 |
+
gap: 8px 10px;
|
| 217 |
+
margin: 26px 0 0;
|
| 218 |
+
padding: 0;
|
| 219 |
+
list-style: none;
|
| 220 |
}
|
| 221 |
|
| 222 |
+
.meta li {
|
| 223 |
+
font-size: 0.78rem;
|
| 224 |
+
font-family: var(--mono);
|
| 225 |
+
color: var(--fg-muted);
|
| 226 |
+
border: 1px solid var(--line);
|
| 227 |
+
border-radius: 999px;
|
| 228 |
+
padding: 3px 11px;
|
| 229 |
+
white-space: nowrap;
|
| 230 |
}
|
| 231 |
|
| 232 |
+
.meta li b {
|
| 233 |
+
font-weight: 500;
|
| 234 |
+
color: var(--fg-faint);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
}
|
| 236 |
|
| 237 |
+
/* --- sections ----------------------------------------------------------- */
|
| 238 |
+
|
| 239 |
+
section {
|
| 240 |
+
padding: 44px 0 0;
|
| 241 |
}
|
| 242 |
|
| 243 |
+
h2 {
|
| 244 |
+
font-size: 1.35rem;
|
| 245 |
+
letter-spacing: -0.015em;
|
| 246 |
+
font-weight: 650;
|
| 247 |
+
margin: 0 0 6px;
|
| 248 |
+
scroll-margin-top: 76px;
|
| 249 |
}
|
| 250 |
|
| 251 |
+
.section-note {
|
| 252 |
+
color: var(--fg-muted);
|
| 253 |
+
margin: 0 0 22px;
|
| 254 |
+
font-size: 0.95rem;
|
| 255 |
+
max-width: 70ch;
|
|
|
|
|
|
|
| 256 |
}
|
| 257 |
|
| 258 |
+
h3 {
|
| 259 |
+
font-size: 1rem;
|
| 260 |
+
font-weight: 620;
|
| 261 |
+
margin: 0 0 6px;
|
| 262 |
+
letter-spacing: -0.005em;
|
|
|
|
| 263 |
}
|
| 264 |
|
| 265 |
+
p {
|
| 266 |
+
margin: 0 0 1rem;
|
|
|
|
|
|
|
| 267 |
}
|
| 268 |
|
| 269 |
+
/* --- cards -------------------------------------------------------------- */
|
| 270 |
+
|
| 271 |
+
.grid {
|
| 272 |
+
display: grid;
|
| 273 |
+
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
| 274 |
+
gap: 14px;
|
| 275 |
+
margin: 0;
|
| 276 |
}
|
| 277 |
|
| 278 |
+
.card {
|
| 279 |
+
border: 1px solid var(--line);
|
| 280 |
+
border-radius: var(--radius);
|
| 281 |
+
padding: 18px 18px 16px;
|
| 282 |
+
background: var(--bg);
|
| 283 |
}
|
| 284 |
|
| 285 |
+
.card p {
|
| 286 |
+
margin: 0;
|
| 287 |
+
color: var(--fg-muted);
|
| 288 |
+
font-size: 0.9rem;
|
| 289 |
+
line-height: 1.6;
|
| 290 |
}
|
| 291 |
|
| 292 |
+
.card p + p {
|
| 293 |
+
margin-top: 0.6rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
}
|
| 295 |
|
| 296 |
+
/* --- figures ------------------------------------------------------------ */
|
| 297 |
+
|
| 298 |
+
figure {
|
| 299 |
+
margin: 0 0 18px;
|
| 300 |
+
border: 1px solid var(--line);
|
| 301 |
+
border-radius: var(--radius);
|
| 302 |
+
overflow: hidden;
|
| 303 |
+
background: var(--bg-soft);
|
| 304 |
}
|
| 305 |
|
| 306 |
+
figure img,
|
| 307 |
+
figure video {
|
| 308 |
+
width: 100%;
|
| 309 |
+
display: block;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
}
|
| 311 |
|
| 312 |
+
figcaption {
|
| 313 |
+
font-size: 0.82rem;
|
| 314 |
+
color: var(--fg-muted);
|
| 315 |
+
padding: 10px 14px;
|
| 316 |
+
border-top: 1px solid var(--line);
|
| 317 |
+
background: var(--bg);
|
| 318 |
}
|
| 319 |
|
| 320 |
+
figcaption b {
|
| 321 |
+
color: var(--fg);
|
| 322 |
+
font-weight: 600;
|
|
|
|
|
|
|
| 323 |
}
|
| 324 |
|
| 325 |
+
.figure-grid {
|
| 326 |
+
display: grid;
|
| 327 |
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
| 328 |
+
gap: 14px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
}
|
| 330 |
|
| 331 |
+
.figure-grid figure {
|
| 332 |
+
margin: 0;
|
|
|
|
| 333 |
}
|
| 334 |
|
| 335 |
+
/* --- tables ------------------------------------------------------------- */
|
| 336 |
+
|
| 337 |
+
.table-scroll {
|
| 338 |
+
overflow-x: auto;
|
| 339 |
+
border: 1px solid var(--line);
|
| 340 |
+
border-radius: var(--radius);
|
|
|
|
|
|
|
| 341 |
}
|
| 342 |
|
| 343 |
+
table {
|
| 344 |
+
border-collapse: collapse;
|
| 345 |
+
width: 100%;
|
| 346 |
+
font-size: 0.88rem;
|
| 347 |
+
min-width: 480px;
|
| 348 |
}
|
| 349 |
|
| 350 |
+
th,
|
| 351 |
+
td {
|
| 352 |
+
text-align: left;
|
| 353 |
+
padding: 10px 14px;
|
| 354 |
+
border-bottom: 1px solid var(--line);
|
| 355 |
}
|
| 356 |
|
| 357 |
+
th {
|
| 358 |
+
font-weight: 600;
|
| 359 |
+
font-size: 0.76rem;
|
| 360 |
+
letter-spacing: 0.05em;
|
| 361 |
+
text-transform: uppercase;
|
| 362 |
+
color: var(--fg-faint);
|
| 363 |
+
background: var(--bg-soft);
|
| 364 |
+
white-space: nowrap;
|
| 365 |
}
|
| 366 |
|
| 367 |
+
tbody tr:last-child td {
|
| 368 |
+
border-bottom: 0;
|
|
|
|
|
|
|
| 369 |
}
|
| 370 |
|
| 371 |
+
td code {
|
| 372 |
+
font-size: 0.85em;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 373 |
}
|
| 374 |
|
| 375 |
+
/* --- code --------------------------------------------------------------- */
|
| 376 |
+
|
| 377 |
+
.code {
|
| 378 |
+
border: 1px solid var(--line);
|
| 379 |
+
border-radius: var(--radius);
|
| 380 |
+
overflow: hidden;
|
| 381 |
+
background: var(--bg-code);
|
| 382 |
+
margin: 0 0 14px;
|
| 383 |
}
|
| 384 |
|
| 385 |
+
.code-tabs {
|
| 386 |
+
display: flex;
|
| 387 |
+
gap: 2px;
|
| 388 |
+
padding: 6px 6px 0;
|
| 389 |
+
border-bottom: 1px solid var(--line);
|
| 390 |
+
background: var(--bg-soft);
|
| 391 |
}
|
| 392 |
|
| 393 |
+
.code-tabs button {
|
| 394 |
+
appearance: none;
|
| 395 |
+
border: 0;
|
| 396 |
+
background: transparent;
|
| 397 |
+
font-family: var(--mono);
|
| 398 |
+
font-size: 0.78rem;
|
| 399 |
+
color: var(--fg-muted);
|
| 400 |
+
padding: 7px 12px;
|
| 401 |
+
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
|
| 402 |
+
cursor: pointer;
|
| 403 |
+
line-height: 1;
|
| 404 |
}
|
| 405 |
|
| 406 |
+
.code-tabs button:hover {
|
| 407 |
+
color: var(--fg);
|
|
|
|
|
|
|
| 408 |
}
|
| 409 |
|
| 410 |
+
.code-tabs button[aria-selected="true"] {
|
| 411 |
+
background: var(--bg-code);
|
| 412 |
+
color: var(--fg);
|
| 413 |
+
font-weight: 600;
|
| 414 |
+
box-shadow: inset 0 -1px 0 var(--bg-code);
|
|
|
|
| 415 |
}
|
| 416 |
|
| 417 |
+
.code pre {
|
| 418 |
+
margin: 0;
|
| 419 |
+
padding: 16px 18px;
|
| 420 |
+
overflow-x: auto;
|
| 421 |
+
font-family: var(--mono);
|
| 422 |
+
font-size: 0.815rem;
|
| 423 |
+
line-height: 1.65;
|
| 424 |
+
tab-size: 2;
|
| 425 |
}
|
| 426 |
|
| 427 |
+
.code pre[hidden] {
|
| 428 |
+
display: none;
|
| 429 |
}
|
| 430 |
|
| 431 |
+
code {
|
| 432 |
+
font-family: var(--mono);
|
| 433 |
+
font-size: 0.88em;
|
|
|
|
| 434 |
}
|
| 435 |
|
| 436 |
+
p code,
|
| 437 |
+
li code {
|
| 438 |
+
background: var(--bg-code);
|
| 439 |
+
border: 1px solid var(--line);
|
| 440 |
+
border-radius: 4px;
|
| 441 |
+
padding: 1px 5px;
|
| 442 |
}
|
| 443 |
|
| 444 |
+
/* --- links list --------------------------------------------------------- */
|
| 445 |
+
|
| 446 |
+
.links {
|
| 447 |
+
display: grid;
|
| 448 |
+
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
|
| 449 |
+
gap: 10px;
|
| 450 |
+
list-style: none;
|
| 451 |
+
padding: 0;
|
| 452 |
+
margin: 0;
|
| 453 |
}
|
| 454 |
|
| 455 |
+
.links a {
|
| 456 |
+
display: flex;
|
| 457 |
+
align-items: baseline;
|
| 458 |
+
justify-content: space-between;
|
| 459 |
+
gap: 10px;
|
| 460 |
+
border: 1px solid var(--line);
|
| 461 |
+
border-radius: var(--radius-sm);
|
| 462 |
+
padding: 11px 14px;
|
| 463 |
+
color: var(--fg);
|
| 464 |
+
font-size: 0.9rem;
|
| 465 |
+
font-weight: 500;
|
| 466 |
}
|
| 467 |
|
| 468 |
+
.links a:hover {
|
| 469 |
+
border-color: var(--line-strong);
|
| 470 |
+
background: var(--bg-soft);
|
| 471 |
+
text-decoration: none;
|
|
|
|
|
|
|
| 472 |
}
|
| 473 |
|
| 474 |
+
.links .host {
|
| 475 |
+
font-family: var(--mono);
|
| 476 |
+
font-size: 0.72rem;
|
| 477 |
+
color: var(--fg-faint);
|
| 478 |
+
font-weight: 400;
|
| 479 |
}
|
| 480 |
|
| 481 |
+
/* --- run-it callout (the one place we ask for a click) ------------------- */
|
| 482 |
+
|
| 483 |
+
.callout {
|
| 484 |
+
border: 1px solid var(--line);
|
| 485 |
+
border-left: 3px solid var(--accent);
|
| 486 |
+
background: var(--bg-soft);
|
| 487 |
+
border-radius: var(--radius-sm);
|
| 488 |
+
padding: 16px 18px;
|
| 489 |
+
font-size: 0.92rem;
|
| 490 |
+
color: var(--fg-muted);
|
| 491 |
}
|
| 492 |
|
| 493 |
+
.callout p {
|
| 494 |
+
margin: 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 495 |
}
|
| 496 |
|
| 497 |
+
.callout p + p {
|
| 498 |
+
margin-top: 0.5rem;
|
|
|
|
| 499 |
}
|
| 500 |
|
| 501 |
+
.btn-row {
|
| 502 |
+
display: flex;
|
| 503 |
+
flex-wrap: wrap;
|
| 504 |
+
gap: 10px;
|
| 505 |
+
margin-top: 18px;
|
| 506 |
}
|
| 507 |
|
| 508 |
+
.btn {
|
| 509 |
+
display: inline-flex;
|
| 510 |
+
align-items: center;
|
| 511 |
+
gap: 7px;
|
| 512 |
+
border-radius: var(--radius-sm);
|
| 513 |
+
padding: 9px 16px;
|
| 514 |
+
font-size: 0.89rem;
|
| 515 |
+
font-weight: 550;
|
| 516 |
+
border: 1px solid var(--accent);
|
| 517 |
+
background: var(--accent);
|
| 518 |
+
color: #fff;
|
| 519 |
+
line-height: 1.4;
|
| 520 |
}
|
| 521 |
|
| 522 |
+
.btn:hover {
|
| 523 |
+
text-decoration: none;
|
| 524 |
+
filter: brightness(1.08);
|
|
|
|
|
|
|
|
|
|
| 525 |
}
|
| 526 |
|
| 527 |
+
.btn.secondary {
|
| 528 |
+
background: transparent;
|
| 529 |
+
color: var(--fg);
|
| 530 |
+
border-color: var(--line-strong);
|
| 531 |
}
|
| 532 |
|
| 533 |
+
.btn.secondary:hover {
|
| 534 |
+
background: var(--bg-soft);
|
| 535 |
+
filter: none;
|
|
|
|
|
|
|
| 536 |
}
|
| 537 |
|
| 538 |
+
@media (prefers-color-scheme: dark) {
|
| 539 |
+
.btn {
|
| 540 |
+
color: #0e1014;
|
| 541 |
+
}
|
|
|
|
|
|
|
|
|
|
| 542 |
}
|
| 543 |
|
| 544 |
+
/* --- footer ------------------------------------------------------------- */
|
| 545 |
+
|
| 546 |
+
.site-footer {
|
| 547 |
+
margin-top: 64px;
|
| 548 |
+
border-top: 1px solid var(--line);
|
| 549 |
+
padding: 26px 0 44px;
|
| 550 |
+
font-size: 0.83rem;
|
| 551 |
+
color: var(--fg-faint);
|
| 552 |
}
|
| 553 |
|
| 554 |
+
.site-footer .wrap {
|
| 555 |
+
display: flex;
|
| 556 |
+
flex-wrap: wrap;
|
| 557 |
+
gap: 10px 24px;
|
| 558 |
+
align-items: baseline;
|
| 559 |
+
justify-content: space-between;
|
| 560 |
}
|
| 561 |
|
| 562 |
+
.site-footer a {
|
| 563 |
+
color: var(--fg-muted);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 564 |
}
|
| 565 |
|
| 566 |
+
.site-footer p {
|
| 567 |
+
margin: 0;
|
| 568 |
+
max-width: 60ch;
|
| 569 |
}
|
| 570 |
|
| 571 |
+
.footer-links {
|
| 572 |
+
display: flex;
|
| 573 |
+
gap: 16px;
|
| 574 |
+
flex-wrap: wrap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 575 |
}
|
tabs.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Code-sample tab switcher. Progressive enhancement: with JS disabled every
|
| 2 |
+
// panel except the first stays hidden via the `hidden` attribute in the markup,
|
| 3 |
+
// so the page still shows one working example.
|
| 4 |
+
document.querySelectorAll(".code-tabs").forEach((tabs) => {
|
| 5 |
+
const buttons = [...tabs.querySelectorAll("button")];
|
| 6 |
+
const panels = buttons.map((b) => document.getElementById(b.dataset.panel));
|
| 7 |
+
|
| 8 |
+
const select = (i) => {
|
| 9 |
+
buttons.forEach((b, j) => b.setAttribute("aria-selected", String(i === j)));
|
| 10 |
+
panels.forEach((p, j) => p && (p.hidden = i !== j));
|
| 11 |
+
};
|
| 12 |
+
|
| 13 |
+
buttons.forEach((b, i) => b.addEventListener("click", () => select(i)));
|
| 14 |
+
select(0);
|
| 15 |
+
});
|