mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-17 08:36:25 +03:00
Refine homepage layout: install, Stay updated, Changelog/FAQ, Visual Mode
- Restructure install section into a split primary card with the recommended path on the left and other install methods on the right - Drop the prefix toggle UI; bundle name is now baked into data-bundle - Balance the Stay updated step as paired Substack iframe + X follow card with matching height, border, and treatment - Pair Changelog and FAQ side-by-side on desktop with a centered divider and shared border-top; section nav highlights both when in view - Tone down the Visual Mode demo by removing side-tab borders, stacked card icons, and tiny body text so the overlay reads cleanly - Refine the Chrome extension callout: drop the pill badge, use an editorial eyebrow above the title, enlarge the thumbnail - Exclude private evals/ directory from version control
This commit is contained in:
@@ -29,3 +29,6 @@ extension/detector/
|
||||
|
||||
# User design context
|
||||
.impeccable.md
|
||||
|
||||
# Evals (private, commercial)
|
||||
evals/
|
||||
|
||||
@@ -118,39 +118,32 @@
|
||||
background: rgba(255,255,255,0.06);
|
||||
border-radius: 12px;
|
||||
padding: 20px 16px;
|
||||
border-left: 4px solid #8b5cf6;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(135deg, #8b5cf6, #a855f7);
|
||||
margin-bottom: 12px;
|
||||
.card-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.card p {
|
||||
font-size: 11px;
|
||||
color: rgba(255,255,255,0.5);
|
||||
font-size: 13px;
|
||||
color: rgba(255,255,255,0.55);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.card:nth-child(2) { border-left-color: #ec4899; }
|
||||
.card:nth-child(2) .card-icon { background: linear-gradient(135deg, #ec4899, #f472b6); }
|
||||
.card:nth-child(3) { border-left-color: #06b6d4; }
|
||||
.card:nth-child(3) .card-icon { background: linear-gradient(135deg, #06b6d4, #22d3ee); }
|
||||
|
||||
/* Stats */
|
||||
.stats {
|
||||
display: flex;
|
||||
@@ -195,18 +188,24 @@
|
||||
|
||||
<div class="cards">
|
||||
<div class="card">
|
||||
<div class="card-icon">⚡</div>
|
||||
<h3>Fast Performance</h3>
|
||||
<div class="card-heading">
|
||||
<span class="card-icon">⚡</span>
|
||||
<h3>Fast Performance</h3>
|
||||
</div>
|
||||
<p>Blazing fast inference with our optimized pipeline.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon">🔒</div>
|
||||
<h3>Secure & Safe</h3>
|
||||
<div class="card-heading">
|
||||
<span class="card-icon">🔒</span>
|
||||
<h3>Secure & Safe</h3>
|
||||
</div>
|
||||
<p>Enterprise-grade security with encrypted data.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-icon">📈</div>
|
||||
<h3>Analytics</h3>
|
||||
<div class="card-heading">
|
||||
<span class="card-icon">📈</span>
|
||||
<h3>Analytics</h3>
|
||||
</div>
|
||||
<p>Powerful insights to help you make better decisions.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+4
-19
@@ -169,28 +169,13 @@ function renderPatternsWithTabs(patterns, antipatterns) {
|
||||
// EVENT HANDLERS
|
||||
// ============================================
|
||||
|
||||
// Sync prefix radio buttons to hidden checkbox + update download button label
|
||||
document.querySelectorAll('input[name="prefix-choice"]').forEach((radio) => {
|
||||
radio.addEventListener('change', () => {
|
||||
const prefixToggle = document.getElementById('prefix-toggle');
|
||||
if (prefixToggle) prefixToggle.checked = radio.value === 'prefixed';
|
||||
const btnLabel = document.querySelector('#download-zip-btn span');
|
||||
if (btnLabel) {
|
||||
btnLabel.textContent = radio.value === 'prefixed'
|
||||
? 'Download prefixed zip'
|
||||
: 'Download universal zip';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Handle bundle download clicks via event delegation
|
||||
// Handle bundle download clicks via event delegation.
|
||||
// Each download button carries the full bundle name in data-bundle (e.g.
|
||||
// "universal" or "universal-prefixed") so the handler is just a redirect.
|
||||
document.addEventListener("click", (e) => {
|
||||
const bundleBtn = e.target.closest("[data-bundle]");
|
||||
if (bundleBtn) {
|
||||
const provider = bundleBtn.dataset.bundle;
|
||||
const prefixToggle = document.getElementById('prefix-toggle');
|
||||
const usePrefixed = prefixToggle && prefixToggle.checked;
|
||||
const bundleName = usePrefixed ? `${provider}-prefixed` : provider;
|
||||
const bundleName = bundleBtn.dataset.bundle;
|
||||
window.location.href = `/api/download/bundle/${bundleName}`;
|
||||
}
|
||||
|
||||
|
||||
+342
-187
@@ -2633,12 +2633,14 @@ code {
|
||||
gap: var(--spacing-md);
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
padding: var(--spacing-sm) 0;
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
|
||||
.detection-callout-image {
|
||||
display: block;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
width: 132px;
|
||||
height: 112px;
|
||||
flex-shrink: 0;
|
||||
object-fit: cover;
|
||||
object-position: top left;
|
||||
@@ -2657,20 +2659,29 @@ code {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.detection-badge {
|
||||
.detection-eyebrow {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.detection-callout-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
letter-spacing: -0.01em;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.detection-callout:hover .detection-callout-title {
|
||||
color: var(--color-accent);
|
||||
border: 1px solid var(--color-accent);
|
||||
padding: 3px 10px;
|
||||
border-radius: 99px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.detection-desc {
|
||||
@@ -2820,12 +2831,118 @@ code {
|
||||
}
|
||||
|
||||
/* Two-path install layout */
|
||||
.install-paths {
|
||||
/* Row 1: full-width primary install card with internal 2-column split */
|
||||
.install-row-primary {
|
||||
display: grid;
|
||||
grid-template-columns: 5fr 3fr 3fr;
|
||||
gap: 0 var(--spacing-xl);
|
||||
grid-template-columns: 1.1fr 0.9fr;
|
||||
gap: var(--spacing-xl);
|
||||
align-items: start;
|
||||
margin: 0 0 var(--spacing-xl);
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: var(--spacing-lg);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.install-primary-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.install-primary-alts {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-lg);
|
||||
min-width: 0;
|
||||
padding-left: var(--spacing-xl);
|
||||
border-left: 1px solid var(--color-mist);
|
||||
}
|
||||
|
||||
.install-alts-label {
|
||||
display: block;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.14em;
|
||||
color: var(--color-ash);
|
||||
}
|
||||
|
||||
.install-alt-sublabel {
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 400;
|
||||
color: var(--color-ash);
|
||||
text-transform: none;
|
||||
letter-spacing: 0;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
/* Compact zip download links — replaces the old big black download button.
|
||||
Two equal-weight options stacked vertically, each is its own affordance. */
|
||||
.install-zip-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.install-zip-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
padding: 8px 12px;
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-charcoal);
|
||||
background: transparent;
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
transition: border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.install-zip-link:hover {
|
||||
border-color: var(--color-accent);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.install-zip-link svg {
|
||||
flex-shrink: 0;
|
||||
color: var(--color-ash);
|
||||
}
|
||||
|
||||
.install-zip-link:hover svg {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.install-zip-link-name {
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.install-zip-link:hover .install-zip-link-name {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.install-zip-link-examples {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 4px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.install-alt-method .install-zip-link-examples code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-accent-dim);
|
||||
color: var(--color-accent);
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.install-path {
|
||||
@@ -2840,28 +2957,82 @@ code {
|
||||
padding: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.install-path-label {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.14em;
|
||||
color: var(--color-accent);
|
||||
/* Steps 2-4: vertical accordion. Native <details name="install-steps">
|
||||
gives mutual exclusion (opening one closes the others). Items are
|
||||
separated by hairlines, not card chrome. */
|
||||
.install-accordion {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 0 var(--spacing-xl);
|
||||
}
|
||||
|
||||
.install-path:not(.install-path-primary) {
|
||||
padding-top: var(--spacing-lg);
|
||||
.install-step {
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
|
||||
.install-path-secondary .install-path-label {
|
||||
.install-step:last-child {
|
||||
border-bottom: 1px solid var(--color-mist);
|
||||
}
|
||||
|
||||
.install-step-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-md);
|
||||
padding: var(--spacing-md) var(--spacing-xs);
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
transition: background var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.install-step-summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.install-step-summary:hover {
|
||||
background: var(--color-cream);
|
||||
}
|
||||
|
||||
.install-step-summary h3 {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.install-step-arrow {
|
||||
flex-shrink: 0;
|
||||
color: var(--color-ash);
|
||||
transition: transform var(--duration-base) var(--ease-out);
|
||||
}
|
||||
|
||||
.install-step[open] .install-step-arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.install-step-body {
|
||||
padding: 0 var(--spacing-xs) var(--spacing-md);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.install-step-body .install-path-desc {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.install-step-status {
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-ash);
|
||||
margin: 0 0 var(--spacing-sm);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.install-path-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin: var(--spacing-xs) 0 var(--spacing-sm);
|
||||
margin: 0 0 var(--spacing-sm);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
@@ -2985,6 +3156,66 @@ code {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Lightweight terminal block — used in row 2 (CLI) where the heavy
|
||||
skeuomorphic glass-terminal would be visually too much. Just a thin
|
||||
bordered code line with a copy button and an optional note below. */
|
||||
.install-cmd-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-xs);
|
||||
margin-bottom: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.install-cmd-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
padding: 10px 14px;
|
||||
background: var(--color-cream);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.install-cmd-line .terminal-prompt {
|
||||
flex-shrink: 0;
|
||||
color: var(--color-accent);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.install-cmd-line code {
|
||||
flex: 1;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-ink);
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.install-cmd-line .copy-btn {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.install-cmd-note {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-ash);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.install-cmd-note code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-mist);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
|
||||
/* Better together callout */
|
||||
.install-together {
|
||||
max-width: 960px;
|
||||
@@ -3021,47 +3252,90 @@ code {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Inline step numbers in path labels */
|
||||
/* Inline step numbers — sit to the left of the title text inside each h3.
|
||||
The h3 uses flex with align-items: center so the step is centered with
|
||||
the text without needing vertical-align fiddling. Margin/gap is handled
|
||||
by the parent flex's gap. */
|
||||
.install-path-step {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
border: 1.5px solid currentColor;
|
||||
font-size: 0.5rem;
|
||||
border: 1.5px solid var(--color-accent);
|
||||
color: var(--color-accent);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
margin-right: 4px;
|
||||
vertical-align: 1px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Stay updated (third column) */
|
||||
.install-updated-subscribe {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
|
||||
gap: var(--spacing-sm);
|
||||
margin-bottom: var(--spacing-md);
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.install-updated-subscribe iframe {
|
||||
.install-updated-substack {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: 130px;
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
background: var(--color-paper);
|
||||
}
|
||||
|
||||
.install-updated-x {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--spacing-xs);
|
||||
height: 130px;
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
background: var(--color-paper);
|
||||
color: var(--color-ink);
|
||||
text-decoration: none;
|
||||
transition: color var(--duration-fast) var(--ease-out);
|
||||
transition: border-color var(--duration-fast) var(--ease-out),
|
||||
background var(--duration-fast) var(--ease-out),
|
||||
transform var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.install-updated-x:hover {
|
||||
border-color: var(--color-ink);
|
||||
background: var(--color-cream);
|
||||
}
|
||||
|
||||
.install-updated-x-icon {
|
||||
color: var(--color-ink);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.install-updated-x-label {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--color-ash);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.install-updated-x-handle {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.install-updated-x:hover .install-updated-x-handle {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
@@ -3123,12 +3397,19 @@ a.install-updated-ref:hover {
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.install-paths {
|
||||
.install-row-primary {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-xl);
|
||||
gap: var(--spacing-lg);
|
||||
max-width: calc(100vw - var(--spacing-md) * 2);
|
||||
}
|
||||
|
||||
.install-primary-alts {
|
||||
padding-left: 0;
|
||||
padding-top: var(--spacing-lg);
|
||||
border-left: none;
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
|
||||
.install-path-primary {
|
||||
margin-bottom: var(--spacing-sm);
|
||||
padding: var(--spacing-md);
|
||||
@@ -3149,10 +3430,27 @@ a.install-updated-ref:hover {
|
||||
gap: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.install-updated-subscribe iframe {
|
||||
.install-updated-subscribe {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.install-updated-substack {
|
||||
height: 130px;
|
||||
}
|
||||
|
||||
.install-updated-x {
|
||||
height: auto;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: var(--spacing-sm);
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
}
|
||||
|
||||
.install-updated-x-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.install-terminal-cmd code {
|
||||
font-size: 0.75rem;
|
||||
white-space: normal;
|
||||
@@ -3420,142 +3718,7 @@ a.install-updated-ref:hover {
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.install-alt-download {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.install-alt-divider {
|
||||
height: 1px;
|
||||
background: var(--color-mist);
|
||||
}
|
||||
|
||||
.install-prefix-options {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--spacing-sm);
|
||||
margin-top: var(--spacing-md);
|
||||
}
|
||||
|
||||
.install-prefix-option {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
border: 1.5px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all var(--duration-fast) var(--ease-out);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.install-prefix-option:hover {
|
||||
border-color: var(--color-charcoal);
|
||||
}
|
||||
|
||||
.install-prefix-option:has(input:checked) {
|
||||
border-color: var(--color-accent);
|
||||
}
|
||||
|
||||
.install-prefix-option input {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1.5px solid var(--color-mist);
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
transition: all var(--duration-fast) var(--ease-out);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.install-prefix-option input:checked {
|
||||
border-color: var(--color-accent);
|
||||
background: var(--color-accent);
|
||||
}
|
||||
|
||||
.install-prefix-option input:checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: var(--color-paper);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.install-prefix-option input:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.install-prefix-option-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.install-prefix-option-label {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.install-prefix-option-examples {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.install-prefix-option-examples code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-accent-dim);
|
||||
color: var(--color-accent);
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.install-prefix-option-wrap {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.install-prefix-reason {
|
||||
font-size: 0.6875rem;
|
||||
color: var(--color-ash);
|
||||
line-height: 1.4;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.install-prefix-option-label code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-accent-dim);
|
||||
color: var(--color-accent);
|
||||
padding: 1px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.install-alt-method .install-prefix-options {
|
||||
margin-top: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.install-alt-method .install-alt-download {
|
||||
margin-top: var(--spacing-sm);
|
||||
}
|
||||
|
||||
/* Hidden prefix checkbox for download logic */
|
||||
/* Visually hidden helper (kept for accessibility patterns elsewhere) */
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
@@ -3569,14 +3732,6 @@ a.install-updated-ref:hover {
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.install-prefix-options {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.install-alt-method {
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
}
|
||||
|
||||
.install-alt-method code {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
+305
-164
@@ -1005,6 +1005,25 @@
|
||||
color: var(--color-accent);
|
||||
border-bottom-color: var(--color-accent);
|
||||
}
|
||||
.changelog-faq-row {
|
||||
position: relative;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.changelog-faq-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||
column-gap: calc(var(--spacing-xl) * 1.5);
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
.changelog-faq-row > .changelog-section, .changelog-faq-row > .faq-section {
|
||||
border-top: none;
|
||||
}
|
||||
.changelog-faq-row > .faq-section {
|
||||
border-left: 1px solid var(--color-mist);
|
||||
padding-left: calc(var(--spacing-xl) * 0.75);
|
||||
margin-left: calc(var(--spacing-xl) * -0.75);
|
||||
}
|
||||
}
|
||||
.changelog-section {
|
||||
position: relative;
|
||||
padding: var(--spacing-xl) 0;
|
||||
@@ -4715,11 +4734,13 @@ code {
|
||||
gap: var(--spacing-md);
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
padding: var(--spacing-sm) 0;
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
.detection-callout-image {
|
||||
display: block;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
width: 132px;
|
||||
height: 112px;
|
||||
flex-shrink: 0;
|
||||
object-fit: cover;
|
||||
object-position: top left;
|
||||
@@ -4736,19 +4757,26 @@ code {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
}
|
||||
.detection-badge {
|
||||
.detection-eyebrow {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--color-accent);
|
||||
}
|
||||
.detection-callout-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
letter-spacing: -0.01em;
|
||||
line-height: 1.15;
|
||||
}
|
||||
.detection-callout:hover .detection-callout-title {
|
||||
color: var(--color-accent);
|
||||
border: 1px solid var(--color-accent);
|
||||
padding: 3px 10px;
|
||||
border-radius: 99px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.detection-desc {
|
||||
flex: 1;
|
||||
@@ -4864,12 +4892,102 @@ code {
|
||||
.platforms-section .section-subtitle {
|
||||
max-width: 60ch;
|
||||
}
|
||||
.install-paths {
|
||||
.install-row-primary {
|
||||
display: grid;
|
||||
grid-template-columns: 5fr 3fr 3fr;
|
||||
gap: 0 var(--spacing-xl);
|
||||
grid-template-columns: 1.1fr 0.9fr;
|
||||
gap: var(--spacing-xl);
|
||||
align-items: start;
|
||||
margin: 0 0 var(--spacing-xl);
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
padding: var(--spacing-lg);
|
||||
min-width: 0;
|
||||
}
|
||||
.install-primary-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
.install-primary-alts {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-lg);
|
||||
min-width: 0;
|
||||
padding-left: var(--spacing-xl);
|
||||
border-left: 1px solid var(--color-mist);
|
||||
}
|
||||
.install-alts-label {
|
||||
display: block;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.14em;
|
||||
color: var(--color-ash);
|
||||
}
|
||||
.install-alt-sublabel {
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 400;
|
||||
color: var(--color-ash);
|
||||
text-transform: none;
|
||||
letter-spacing: 0;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.install-zip-links {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-top: var(--spacing-xs);
|
||||
}
|
||||
.install-zip-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
padding: 8px 12px;
|
||||
font-family: var(--font-body);
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-charcoal);
|
||||
background: transparent;
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
transition: border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
.install-zip-link:hover {
|
||||
border-color: var(--color-accent);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
.install-zip-link svg {
|
||||
flex-shrink: 0;
|
||||
color: var(--color-ash);
|
||||
}
|
||||
.install-zip-link:hover svg {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
.install-zip-link-name {
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.install-zip-link:hover .install-zip-link-name {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
.install-zip-link-examples {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 4px;
|
||||
margin-left: auto;
|
||||
}
|
||||
.install-alt-method .install-zip-link-examples code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-accent-dim);
|
||||
color: var(--color-accent);
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.install-path {
|
||||
display: flex;
|
||||
@@ -4881,25 +4999,67 @@ code {
|
||||
border-radius: 16px;
|
||||
padding: var(--spacing-lg);
|
||||
}
|
||||
.install-path-label {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.14em;
|
||||
color: var(--color-accent);
|
||||
.install-accordion {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 0 var(--spacing-xl);
|
||||
}
|
||||
.install-path:not(.install-path-primary) {
|
||||
padding-top: var(--spacing-lg);
|
||||
.install-step {
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
.install-path-secondary .install-path-label {
|
||||
.install-step:last-child {
|
||||
border-bottom: 1px solid var(--color-mist);
|
||||
}
|
||||
.install-step-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-md);
|
||||
padding: var(--spacing-md) var(--spacing-xs);
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
transition: background var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
.install-step-summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
.install-step-summary:hover {
|
||||
background: var(--color-cream);
|
||||
}
|
||||
.install-step-summary h3 {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
}
|
||||
.install-step-arrow {
|
||||
flex-shrink: 0;
|
||||
color: var(--color-ash);
|
||||
transition: transform var(--duration-base) var(--ease-out);
|
||||
}
|
||||
.install-step[open] .install-step-arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.install-step-body {
|
||||
padding: 0 var(--spacing-xs) var(--spacing-md);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.install-step-body .install-path-desc {
|
||||
margin-top: 0;
|
||||
}
|
||||
.install-step-status {
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-ash);
|
||||
margin: 0 0 var(--spacing-sm);
|
||||
font-style: italic;
|
||||
}
|
||||
.install-path-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin: var(--spacing-xs) 0 var(--spacing-sm);
|
||||
margin: 0 0 var(--spacing-sm);
|
||||
line-height: 1.2;
|
||||
}
|
||||
.install-path-badge {
|
||||
@@ -5000,6 +5160,55 @@ code {
|
||||
.install-path-link a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.install-cmd-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-xs);
|
||||
margin-bottom: var(--spacing-sm);
|
||||
}
|
||||
.install-cmd-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
padding: 10px 14px;
|
||||
background: var(--color-cream);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
.install-cmd-line .terminal-prompt {
|
||||
flex-shrink: 0;
|
||||
color: var(--color-accent);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
.install-cmd-line code {
|
||||
flex: 1;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-ink);
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.install-cmd-line .copy-btn {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.install-cmd-note {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-ash);
|
||||
line-height: 1.5;
|
||||
}
|
||||
.install-cmd-note code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-mist);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
.install-together {
|
||||
max-width: 960px;
|
||||
margin: 0 0 var(--spacing-xl);
|
||||
@@ -5035,37 +5244,71 @@ code {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
border: 1.5px solid currentColor;
|
||||
font-size: 0.5rem;
|
||||
border: 1.5px solid var(--color-accent);
|
||||
color: var(--color-accent);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.625rem;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
margin-right: 4px;
|
||||
vertical-align: 1px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.install-updated-subscribe {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
|
||||
gap: var(--spacing-sm);
|
||||
margin-bottom: var(--spacing-md);
|
||||
align-items: stretch;
|
||||
}
|
||||
.install-updated-subscribe iframe {
|
||||
.install-updated-substack {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
height: 130px;
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
background: var(--color-paper);
|
||||
}
|
||||
.install-updated-x {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--spacing-xs);
|
||||
height: 130px;
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
border: 1px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
background: var(--color-paper);
|
||||
color: var(--color-ink);
|
||||
text-decoration: none;
|
||||
transition: color var(--duration-fast) var(--ease-out);
|
||||
transition: border-color var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
.install-updated-x:hover {
|
||||
border-color: var(--color-ink);
|
||||
background: var(--color-cream);
|
||||
}
|
||||
.install-updated-x-icon {
|
||||
color: var(--color-ink);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.install-updated-x-label {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--color-ash);
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
.install-updated-x-handle {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
.install-updated-x:hover .install-updated-x-handle {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
.install-updated-refs {
|
||||
@@ -5119,11 +5362,17 @@ a.install-updated-ref:hover {
|
||||
color: var(--color-ink);
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.install-paths {
|
||||
.install-row-primary {
|
||||
grid-template-columns: 1fr;
|
||||
gap: var(--spacing-xl);
|
||||
gap: var(--spacing-lg);
|
||||
max-width: calc(100vw - var(--spacing-md) * 2);
|
||||
}
|
||||
.install-primary-alts {
|
||||
padding-left: 0;
|
||||
padding-top: var(--spacing-lg);
|
||||
border-left: none;
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
.install-path-primary {
|
||||
margin-bottom: var(--spacing-sm);
|
||||
padding: var(--spacing-md);
|
||||
@@ -5140,9 +5389,23 @@ a.install-updated-ref:hover {
|
||||
align-items: flex-start;
|
||||
gap: var(--spacing-xs);
|
||||
}
|
||||
.install-updated-subscribe iframe {
|
||||
.install-updated-subscribe {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.install-updated-substack {
|
||||
height: 130px;
|
||||
}
|
||||
.install-updated-x {
|
||||
height: auto;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: var(--spacing-sm);
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
}
|
||||
.install-updated-x-label {
|
||||
display: none;
|
||||
}
|
||||
.install-terminal-cmd code {
|
||||
font-size: 0.75rem;
|
||||
white-space: normal;
|
||||
@@ -5371,122 +5634,6 @@ a.install-updated-ref:hover {
|
||||
border-radius: 3px;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
.install-alt-download {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
.install-alt-divider {
|
||||
height: 1px;
|
||||
background: var(--color-mist);
|
||||
}
|
||||
.install-prefix-options {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--spacing-sm);
|
||||
margin-top: var(--spacing-md);
|
||||
}
|
||||
.install-prefix-option {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
padding: 10px 12px;
|
||||
border: 1.5px solid var(--color-mist);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all var(--duration-fast) var(--ease-out);
|
||||
line-height: 1;
|
||||
}
|
||||
.install-prefix-option:hover {
|
||||
border-color: var(--color-charcoal);
|
||||
}
|
||||
.install-prefix-option:has(input:checked) {
|
||||
border-color: var(--color-accent);
|
||||
}
|
||||
.install-prefix-option input {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1.5px solid var(--color-mist);
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
transition: all var(--duration-fast) var(--ease-out);
|
||||
position: relative;
|
||||
}
|
||||
.install-prefix-option input:checked {
|
||||
border-color: var(--color-accent);
|
||||
background: var(--color-accent);
|
||||
}
|
||||
.install-prefix-option input:checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: var(--color-paper);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.install-prefix-option input:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.install-prefix-option-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
padding-top: 1px;
|
||||
}
|
||||
.install-prefix-option-label {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-ink);
|
||||
line-height: 1;
|
||||
}
|
||||
.install-prefix-option-examples {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
.install-prefix-option-examples code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-accent-dim);
|
||||
color: var(--color-accent);
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.install-prefix-option-wrap {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
align-self: flex-start;
|
||||
}
|
||||
.install-prefix-reason {
|
||||
font-size: 0.6875rem;
|
||||
color: var(--color-ash);
|
||||
line-height: 1.4;
|
||||
padding-left: 2px;
|
||||
}
|
||||
.install-prefix-option-label code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.6875rem;
|
||||
background: var(--color-accent-dim);
|
||||
color: var(--color-accent);
|
||||
padding: 1px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.install-alt-method .install-prefix-options {
|
||||
margin-top: var(--spacing-sm);
|
||||
}
|
||||
.install-alt-method .install-alt-download {
|
||||
margin-top: var(--spacing-sm);
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
@@ -5499,12 +5646,6 @@ a.install-updated-ref:hover {
|
||||
border: 0;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.install-prefix-options {
|
||||
flex-direction: column;
|
||||
}
|
||||
.install-alt-method {
|
||||
padding: var(--spacing-sm) var(--spacing-md);
|
||||
}
|
||||
.install-alt-method code {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
@@ -1068,6 +1068,34 @@
|
||||
border-bottom-color: var(--color-accent);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
CHANGELOG + FAQ ROW (side-by-side on desktop)
|
||||
============================================ */
|
||||
|
||||
.changelog-faq-row {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.changelog-faq-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||
column-gap: calc(var(--spacing-xl) * 1.5);
|
||||
border-top: 1px solid var(--color-mist);
|
||||
}
|
||||
|
||||
.changelog-faq-row > .changelog-section,
|
||||
.changelog-faq-row > .faq-section {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.changelog-faq-row > .faq-section {
|
||||
border-left: 1px solid var(--color-mist);
|
||||
padding-left: calc(var(--spacing-xl) * 0.75);
|
||||
margin-left: calc(var(--spacing-xl) * -0.75);
|
||||
}
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
CHANGELOG SECTION
|
||||
============================================ */
|
||||
|
||||
+105
-125
@@ -289,11 +289,12 @@
|
||||
<span class="visual-mode-feature-label">Three ways to use it</span>
|
||||
<p>The <strong>Chrome extension</strong> on any site, embedded in <code>/critique</code> during an AI design review, or standalone via <code>npx impeccable live</code>.</p>
|
||||
</div>
|
||||
<a href="https://chromewebstore.google.com/" class="detection-callout" target="_blank" rel="noopener">
|
||||
<a href="https://impeccablestyle.substack.com" class="detection-callout" target="_blank" rel="noopener">
|
||||
<img src="assets/extension-detection.png" alt="Impeccable Chrome extension panel listing detected anti-patterns" class="detection-callout-image" loading="lazy" width="600" height="508">
|
||||
<div class="detection-callout-inner">
|
||||
<span class="detection-badge">New!</span>
|
||||
<span class="detection-cmd">Get the Chrome extension →</span>
|
||||
<span class="detection-eyebrow">Coming soon</span>
|
||||
<span class="detection-callout-title">Chrome extension</span>
|
||||
<span class="detection-cmd">Get notified →</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@@ -308,11 +309,10 @@
|
||||
<h2 class="section-title">Get Started</h2>
|
||||
</div>
|
||||
|
||||
<div class="install-paths" data-reveal>
|
||||
<!-- Skills path (primary) -->
|
||||
<div class="install-path install-path-primary">
|
||||
<span class="install-path-label"><span class="install-path-step">1</span></span>
|
||||
<h3 class="install-path-title">Install the skills <span class="install-path-badge">Recommended</span></h3>
|
||||
<!-- Row 1: Primary install (full width, white card with internal 2-col split) -->
|
||||
<div class="install-row-primary" data-reveal>
|
||||
<div class="install-primary-main">
|
||||
<h3 class="install-path-title"><span class="install-path-step">1</span>Install the skills <span class="install-path-badge">Recommended</span></h3>
|
||||
<p class="install-path-desc">21 commands that steer your AI toward better design, in real time. The full Impeccable experience.</p>
|
||||
|
||||
<div class="install-path-terminal">
|
||||
@@ -343,135 +343,114 @@
|
||||
<div class="install-path-next">
|
||||
Then run <code><span class="install-path-slash">/</span>impeccable teach</code> to set up your project's design context.
|
||||
</div>
|
||||
|
||||
<!-- Alternatives (collapsible) -->
|
||||
<details class="install-alternatives">
|
||||
<summary class="install-alternatives-toggle">Other install methods</summary>
|
||||
<div class="install-alternatives-content">
|
||||
<div class="install-alt-method">
|
||||
<span class="install-alt-label">Claude Code plugin</span>
|
||||
<div class="install-terminal-cmd">
|
||||
<span class="terminal-prompt">$</span>
|
||||
<code>/plugin marketplace add pbakaus/impeccable</code>
|
||||
<button class="copy-btn" aria-label="Copy command" data-copy="/plugin marketplace add pbakaus/impeccable">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="install-alt-note">Then open <code>/plugin</code> to install from Discover tab</span>
|
||||
</div>
|
||||
<div class="install-alt-divider"></div>
|
||||
<div class="install-alt-method">
|
||||
<span class="install-alt-label">Manual download</span>
|
||||
<span class="install-alt-note">Contains all provider directories. Extract to your project root.</span>
|
||||
<div class="install-prefix-options">
|
||||
<label class="install-prefix-option" data-prefix="default">
|
||||
<input type="radio" name="prefix-choice" value="default" checked />
|
||||
<div class="install-prefix-option-content">
|
||||
<span class="install-prefix-option-label">Default names</span>
|
||||
<span class="install-prefix-option-examples"><code>/polish</code> <code>/audit</code> <code>/typeset</code></span>
|
||||
</div>
|
||||
</label>
|
||||
<div class="install-prefix-option-wrap">
|
||||
<label class="install-prefix-option" data-prefix="prefixed">
|
||||
<input type="radio" name="prefix-choice" value="prefixed" />
|
||||
<div class="install-prefix-option-content">
|
||||
<span class="install-prefix-option-label">Prefixed with <code>/i-</code></span>
|
||||
<span class="install-prefix-option-examples"><code>/i-polish</code> <code>/i-audit</code> <code>/i-typeset</code></span>
|
||||
</div>
|
||||
</label>
|
||||
<span class="install-prefix-reason">Avoids conflicts with built-in commands or other skill packs</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="install-alt-download">
|
||||
<button class="btn btn-primary" data-bundle="universal" aria-label="Download universal zip" id="download-zip-btn">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/>
|
||||
</svg>
|
||||
<span>Download universal zip</span>
|
||||
</button>
|
||||
</div>
|
||||
<input type="checkbox" id="prefix-toggle" class="sr-only" />
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<!-- CLI path (secondary) -->
|
||||
<div class="install-path install-path-secondary">
|
||||
<span class="install-path-label"><span class="install-path-step">2</span></span>
|
||||
<h3 class="install-path-title">Add the CLI <span class="install-path-badge install-path-badge-muted">Beta</span></h3>
|
||||
<p class="install-path-desc">Deterministic anti-pattern detection, cheatsheet and more. Use in CI and beyond.</p>
|
||||
<!-- Other install methods -->
|
||||
<div class="install-primary-alts">
|
||||
<span class="install-alts-label">Other install methods</span>
|
||||
|
||||
<div class="install-path-terminal">
|
||||
<div class="glass-terminal">
|
||||
<div class="terminal-header">
|
||||
<span class="terminal-dot red"></span>
|
||||
<span class="terminal-dot yellow"></span>
|
||||
<span class="terminal-dot green"></span>
|
||||
</div>
|
||||
<div class="terminal-body">
|
||||
<div class="install-terminal-row">
|
||||
<div class="install-terminal-cmd">
|
||||
<span class="terminal-prompt">$</span>
|
||||
<code>npm i -g impeccable</code>
|
||||
<button class="copy-btn" aria-label="Copy command" data-copy="npm i -g impeccable">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="install-terminal-note">Or run directly: <code>npx impeccable ...</code></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="install-path-subcommands">
|
||||
<span class="install-path-subcommand"><code>detect</code> Scan files, dirs, or URLs</span>
|
||||
<span class="install-path-subcommand"><code>skills install</code> Install skills into your project</span>
|
||||
<span class="install-path-subcommand"><code>skills update</code> Update to latest version</span>
|
||||
</div>
|
||||
|
||||
<p class="install-path-link"><a href="https://www.npmjs.com/package/impeccable">View on npm</a></p>
|
||||
</div>
|
||||
|
||||
<!-- Stay sharp (third column) -->
|
||||
<div class="install-path install-updated">
|
||||
<span class="install-path-label"><span class="install-path-step">3</span></span>
|
||||
<h3 class="install-path-title">Stay updated</h3>
|
||||
|
||||
<div class="install-updated-subscribe">
|
||||
<iframe src="https://impeccablestyle.substack.com/embed" width="100%" height="150" style="border: 1px solid #e8e4df; border-radius: 8px; background: white;" frameborder="0" scrolling="no"></iframe>
|
||||
<a href="https://x.com/impeccable_ai" class="install-updated-x" target="_blank" rel="noopener">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
||||
<span>Follow @impeccable_ai</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="install-updated-refs">
|
||||
<span class="install-updated-refs-label">Quick reference</span>
|
||||
<a href="/cheatsheet" class="install-updated-ref">Command cheatsheet →</a>
|
||||
<div class="install-updated-ref install-updated-ref-terminal">
|
||||
<div class="install-alt-method">
|
||||
<span class="install-alt-label">Claude Code plugin</span>
|
||||
<div class="install-terminal-cmd">
|
||||
<span class="terminal-prompt">$</span>
|
||||
<code>impeccable skills help</code>
|
||||
<code>/plugin marketplace add pbakaus/impeccable</code>
|
||||
<button class="copy-btn" aria-label="Copy command" data-copy="/plugin marketplace add pbakaus/impeccable">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="install-alt-note">Then open <code>/plugin</code> in Claude Code</span>
|
||||
</div>
|
||||
|
||||
<div class="install-alt-method">
|
||||
<span class="install-alt-label">Manual download <span class="install-alt-sublabel">all 11 providers</span></span>
|
||||
<div class="install-zip-links">
|
||||
<button class="install-zip-link" data-bundle="universal" aria-label="Download universal zip with default command names">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/>
|
||||
</svg>
|
||||
<span class="install-zip-link-name">Default zip</span>
|
||||
<span class="install-zip-link-examples"><code>/polish</code> <code>/audit</code></span>
|
||||
</button>
|
||||
<button class="install-zip-link" data-bundle="universal-prefixed" aria-label="Download universal zip with prefixed command names">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/>
|
||||
</svg>
|
||||
<span class="install-zip-link-name">Prefixed zip</span>
|
||||
<span class="install-zip-link-examples"><code>/i-polish</code> <code>/i-audit</code></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Better together callout -->
|
||||
<div class="install-together" data-reveal>
|
||||
<div class="install-together-inner">
|
||||
<span class="install-together-badge">Best together</span>
|
||||
<p class="install-together-text">Skills give your AI the full design toolkit. The CLI adds automated quality gates for reviews and CI.</p>
|
||||
</div>
|
||||
<!-- Steps 2-4: vertical accordion, mutually exclusive (only one open at a time) -->
|
||||
<div class="install-accordion" data-reveal>
|
||||
<!-- Step 2: CLI -->
|
||||
<details name="install-steps" class="install-step">
|
||||
<summary class="install-step-summary">
|
||||
<h3 class="install-path-title"><span class="install-path-step">2</span>Add the CLI <span class="install-path-badge install-path-badge-muted">Beta</span></h3>
|
||||
<svg class="install-step-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg>
|
||||
</summary>
|
||||
<div class="install-step-body">
|
||||
<p class="install-path-desc">Anti-pattern detection from the terminal. Scans HTML, CSS, JSX/TSX, Vue, and Svelte — perfect for CI, pre-commit hooks, and one-off audits.</p>
|
||||
|
||||
<div class="install-cmd-block">
|
||||
<div class="install-cmd-line">
|
||||
<span class="terminal-prompt">$</span>
|
||||
<code>npm i -g impeccable</code>
|
||||
<button class="copy-btn" aria-label="Copy command" data-copy="npm i -g impeccable">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="install-cmd-note">Or use <code>npx impeccable</code> directly without installing.</span>
|
||||
</div>
|
||||
|
||||
<p class="install-path-link"><a href="https://www.npmjs.com/package/impeccable" target="_blank" rel="noopener">Full command reference on npm →</a></p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- Step 3: Browser extension -->
|
||||
<details name="install-steps" class="install-step">
|
||||
<summary class="install-step-summary">
|
||||
<h3 class="install-path-title"><span class="install-path-step">3</span>Browser extension <span class="install-path-badge install-path-badge-muted">Coming soon</span></h3>
|
||||
<svg class="install-step-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg>
|
||||
</summary>
|
||||
<div class="install-step-body">
|
||||
<p class="install-path-desc">One-click anti-pattern detection on any live page — yours, staging, production, or anyone else's. Same detection engine as <code>/critique</code>, in your browser.</p>
|
||||
<p class="install-step-status">Currently in Chrome Web Store review.</p>
|
||||
<p class="install-path-link"><a href="https://impeccablestyle.substack.com" target="_blank" rel="noopener">Get notified when it lands →</a></p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<!-- Step 4: Stay updated -->
|
||||
<details name="install-steps" class="install-step">
|
||||
<summary class="install-step-summary">
|
||||
<h3 class="install-path-title"><span class="install-path-step">4</span>Stay updated</h3>
|
||||
<svg class="install-step-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg>
|
||||
</summary>
|
||||
<div class="install-step-body">
|
||||
<p class="install-path-desc">Roughly monthly notes on new commands, anti-patterns, and the design thinking behind Impeccable.</p>
|
||||
<div class="install-updated-subscribe">
|
||||
<iframe class="install-updated-substack" src="https://impeccablestyle.substack.com/embed" width="100%" height="130" frameborder="0" scrolling="no"></iframe>
|
||||
<a href="https://x.com/impeccable_ai" class="install-updated-x" target="_blank" rel="noopener">
|
||||
<svg class="install-updated-x-icon" width="22" height="22" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
||||
<span class="install-updated-x-label">Follow on X</span>
|
||||
<span class="install-updated-x-handle">@impeccable_ai</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 5+6. CHANGELOG + FAQ (side-by-side on desktop) -->
|
||||
<div class="changelog-faq-row">
|
||||
<!-- 5. CHANGELOG -->
|
||||
<section class="changelog-section" id="changelog">
|
||||
<div class="section-header" data-reveal>
|
||||
@@ -654,6 +633,7 @@
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
</div><!-- /.changelog-faq-row -->
|
||||
|
||||
<!-- PARTNERSHIPS -->
|
||||
<section class="consulting-section" id="consulting">
|
||||
|
||||
@@ -42,9 +42,23 @@ export function initSectionNav() {
|
||||
}
|
||||
}
|
||||
|
||||
// If the current section shares its top row with siblings (e.g. side-by-side
|
||||
// changelog + FAQ on desktop), treat all of them as active.
|
||||
const activeSections = new Set();
|
||||
if (currentSection) {
|
||||
const currentEl = document.getElementById(currentSection);
|
||||
const currentTop = currentEl?.offsetTop ?? 0;
|
||||
sectionIds.forEach(id => {
|
||||
const el = document.getElementById(id);
|
||||
if (el && Math.abs(el.offsetTop - currentTop) < 4) {
|
||||
activeSections.add(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update active state
|
||||
items.forEach(item => {
|
||||
if (item.dataset.section === currentSection) {
|
||||
if (activeSections.has(item.dataset.section)) {
|
||||
item.classList.add('is-active');
|
||||
} else {
|
||||
item.classList.remove('is-active');
|
||||
|
||||
Reference in New Issue
Block a user