From 07158a2b612758512b1f86a03e1e3283dc6c8f0e Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Tue, 6 Oct 2026 02:14:16 +1100 Subject: [PATCH 1/2] feat(home): apply the dot brand to the home page The home page still carried the noise field, the taste-tested hero and a featured collections band the new copy deck retires. It now uses the approved copy and the motifs that real data supports. - Hero: braille names texture fed this week's trending Skill names, the rose dot as the H1 full stop, the claims line and the skilld install promo. The rail stops auto scrolling so the texture is the band's one moving region. - Four tiles replace the three doors. - Trending cards link their source post. A card gets a run chip only when its repository holds exactly one Skill. - Converge is the trending loader and the divider into publishing. - The collections band, its fetch and its CSS are gone. NoiseField and its WebGL guard go with it, since nothing else used them. - Band edges and heading underlines turn stone, so rose stays the one picked dot. Page title and meta description are unchanged for the SEO experiment. --- app/assets/css/main.css | 517 +++++---------------------- app/components/NoiseField.client.vue | 405 --------------------- app/pages/index.vue | 515 ++++++-------------------- app/utils/webgl-context.ts | 50 --- scripts/lib/production-smoke.ts | 2 +- test/a11y.spec.ts | 1 - test/unit/production-smoke.test.ts | 2 +- test/unit/webgl-context.test.ts | 61 +--- 8 files changed, 203 insertions(+), 1350 deletions(-) delete mode 100644 app/components/NoiseField.client.vue diff --git a/app/assets/css/main.css b/app/assets/css/main.css index 4191323e..a0590501 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -545,12 +545,6 @@ } } -.home-featured-heading { - display: grid; - gap: 1.5rem; - align-items: end; -} - .home-community-band { background: color-mix(in oklab, var(--ui-bg) 94%, var(--ui-bg-muted)); } @@ -599,294 +593,6 @@ } } -.home-featured-title { - font-size: clamp(2.5rem, 2.1rem + 1.8vw, 3.5rem); - font-weight: 600; - letter-spacing: -0.04em; - line-height: 1.02; -} - -.home-featured-layout { - display: grid; - min-width: 0; - gap: 0.75rem; -} - -.home-featured-lead, -.home-featured-support-card { - min-width: 0; - border: 1px solid var(--ui-border); - border-radius: var(--ui-radius); - background: var(--ui-bg); -} - -.home-featured-lead { - padding: 1.25rem; -} - -.home-featured-lead__intro { - display: flex; - min-width: 0; - flex-direction: column; - gap: 1rem; -} - -.home-featured-lead__title { - font-size: clamp(1.75rem, 1.55rem + 0.8vw, 2.25rem); - font-weight: 600; - letter-spacing: -0.035em; - line-height: 1.08; -} - -.home-featured-curator { - display: flex; - min-width: 0; - flex: none; - align-items: center; - gap: 0.75rem; -} - -.home-featured-avatar, -.home-featured-skill-avatar, -.home-featured-support-avatar { - flex: none; - border: 2px solid var(--ui-bg); - border-radius: 9999px; - outline: 1px solid var(--ui-border); - background: var(--ui-bg-muted); - object-fit: cover; -} - -.home-featured-avatar { - width: 3.5rem; - height: 3.5rem; -} - -.home-featured-rationale { - margin-top: 1.25rem; - padding-block: 1.25rem; - border-block: 1px solid var(--ui-border); -} - -.home-featured-skill-heading { - display: flex; - align-items: baseline; - justify-content: space-between; - gap: 1rem; - margin-top: 1.25rem; -} - -.home-featured-skills { - display: grid; - min-width: 0; - grid-template-columns: minmax(0, 1fr); - margin-top: 0.75rem; - padding: 0; - border-block: 1px solid var(--ui-border); - list-style: none; -} - -.home-featured-skills > li { - min-width: 0; -} - -.home-featured-skills > li:not(:last-child) { - border-bottom: 1px solid var(--ui-border); -} - -.home-featured-skill { - display: flex; - min-width: 0; - min-height: 4.75rem; - height: 100%; - align-items: center; - gap: 0.75rem; - padding: 0.75rem; - overflow-wrap: anywhere; - transition: background-color 200ms ease-out; -} - -.home-featured-skill-avatar { - width: 2rem; - height: 2rem; -} - -.home-featured-skill:focus-visible, -.home-featured-support-card:focus-visible { - outline: 2px solid var(--ui-color-primary-500) !important; - outline-offset: -3px !important; -} - -.home-featured-install { - min-width: 0; - margin-top: 1.5rem; -} - -.home-featured-install__heading { - display: flex; - min-width: 0; - flex-direction: column; - gap: 0.75rem; -} - -.home-featured-command { - display: grid; - min-width: 0; - gap: 0.5rem; - margin-top: 1rem; -} - -/* The command wraps rather than scrolls: a horizontal scrollbar inside the - lead card is chrome the reader has to operate to finish reading one line. */ -.home-featured-command code { - display: block; - min-width: 0; - max-width: 100%; - padding: 0.75rem 1rem; - border: 1px solid var(--ui-border); - border-radius: var(--ui-radius); - background: var(--ui-bg-muted); - font-size: 0.875rem; - line-height: 1.5rem; - user-select: text; -} - -.home-featured-command code:focus-visible { - outline: 2px solid var(--ui-color-primary-500); - outline-offset: 2px; -} - -.home-featured-copy { - width: 100%; -} - -.home-featured-feedback { - min-height: 1.5rem; - margin: 0; - padding-top: 0.5rem; -} - -.home-featured-support { - display: grid; - min-width: 0; - gap: 0.75rem; -} - -.home-featured-support article { - min-width: 0; - height: 100%; -} - -.home-featured-support-card { - display: flex; - min-height: 11rem; - height: 100%; - flex-direction: column; - background: color-mix(in oklab, var(--ui-bg-muted) 32%, var(--ui-bg)); - padding: 1.25rem; - transition: background-color 200ms ease-out, border-color 200ms ease-out; -} - -.home-featured-support-avatar { - width: 2rem; - height: 2rem; -} - -.home-featured-owner-stack { - display: flex; - flex: none; - align-items: center; -} - -.home-featured-owner-stack > * + * { - margin-left: -0.5rem; -} - -.home-featured-support-arrow { - color: var(--ui-text-muted); - transition: color 200ms ease-out, translate 200ms ease-out; -} - -.home-featured-support-meta { - margin-top: auto; - padding-top: 1rem; -} - -@media (min-width: 40rem) { - .home-featured-heading { - grid-template-columns: minmax(0, 1fr) auto; - } - - .home-featured-lead { - padding: 1.5rem; - } - - .home-featured-lead__intro { - flex-direction: row; - align-items: flex-start; - justify-content: space-between; - } - - .home-featured-install__heading { - flex-direction: row; - align-items: flex-start; - justify-content: space-between; - } - - .home-featured-command { - grid-template-columns: minmax(0, 1fr) auto; - } - - .home-featured-copy { - width: auto; - } - - .home-featured-support { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .home-featured-skills { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .home-featured-skills > li:not(:last-child) { - border-bottom: 0; - } - - .home-featured-skills > li:nth-child(odd) { - border-right: 1px solid var(--ui-border); - } - - .home-featured-skills > li:nth-child(n+3) { - border-top: 1px solid var(--ui-border); - } -} - -@media (min-width: 64rem) { - .home-featured-layout { - grid-template-columns: minmax(0, 1.55fr) minmax(0, 0.85fr); - } - - .home-featured-support { - align-self: start; - grid-template-columns: minmax(0, 1fr); - grid-template-rows: repeat(2, auto); - } - -} - -@media (hover: hover) { - .home-featured-skill:hover, - .home-featured-support-card:hover { - background: var(--ui-bg-muted); - } - - .home-featured-support-card:hover .home-featured-support-arrow { - color: var(--ui-text); - translate: 0.125rem -0.125rem; - } -} - .home-freshness-title { font-size: clamp(2.25rem, 1.9rem + 1.7vw, 3.5rem); letter-spacing: -0.04em; @@ -1536,6 +1242,95 @@ } } +/* The braille names texture: behind the hero, masked clear of the headline. + Phones stack the copy above the rail, so the names sit below the copy. */ +.home-hero-texture { + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + mask-image: linear-gradient(to bottom, transparent 45%, #000 85%); + -webkit-mask-image: linear-gradient(to bottom, transparent 45%, #000 85%); +} + +@media (min-width: 64rem) { + .home-hero-texture { + mask-image: linear-gradient(to right, transparent 38%, #000 80%); + -webkit-mask-image: linear-gradient(to right, transparent 38%, #000 80%); + } +} + +/* The H1 full stop is the brand dot, the hero's rose element. */ +.home-hero-dot { + display: inline-block; + width: 0.16em; + height: 0.16em; + margin-inline-start: 0.05em; + border-radius: 999px; + background: var(--brand-dot); +} + +.home-hero-claims a { + color: var(--ui-text); + text-decoration-line: underline; + text-decoration-color: var(--ui-border-accented); + text-underline-offset: 0.2em; + transition: text-decoration-color 200ms ease-out; +} + +.home-hero-claims a:hover { + text-decoration-color: currentColor; +} + +.home-hero-promo { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem 0.75rem; + max-width: 36rem; +} + +/* Trending cards: the repository link covers the card, and the run chip and + the source link sit above it. */ +.home-trending-card { + position: relative; + display: flex; + height: 100%; + min-width: 0; + flex-direction: column; + border: 1px solid var(--ui-border); + border-radius: var(--ui-radius); + padding: 1rem; + transition: border-color 200ms ease-out; +} + +.home-trending-card__link::after { + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; +} + +.home-trending-card__action { + position: relative; + z-index: 1; +} + +@media (hover: hover) { + .home-trending-card:has(.home-trending-card__link:hover) { + border-color: var(--ui-text-muted); + } +} + +.home-trending-card:has(.home-trending-card__link:focus-visible) { + outline: 2px solid var(--ui-primary); + outline-offset: 2px; +} + +.home-trending-card__link:focus-visible { + outline: none; +} + /* the homepage hero: named agent row under the search. Proof of "every agent". */ .home-hero-agents { display: flex; @@ -1573,62 +1368,6 @@ column-gap: 0.5rem; } -/* "ecosystem" carries the brand: rose ink and the chevron mark in place of a full stop. */ -.home-hero-eco { - position: relative; - display: inline-block; - color: var(--ui-primary); - opacity: 0.92; -} - -/* Dot-grid underline: the noise field's grid, frozen, in rose. */ -.home-hero-eco::after { - content: ''; - position: absolute; - inset-inline: 0.04em 0.3em; - bottom: -0.01em; - height: 0.13em; - background-image: radial-gradient(circle, var(--ui-primary) 1px, transparent 1.25px); - background-size: 0.115em 0.115em; - opacity: 0.6; - pointer-events: none; -} - - -.home-hero-taste { - position: relative; - display: inline-block; -} - -/* Emoji wink on the first line: sits on the cap line, clear of the last letter. */ -.home-hero-emoji { - position: absolute; - top: 0.04em; - right: -1.55em; - font-size: 0.4em; - line-height: 1; - transform: rotate(10deg); - transform-origin: 50% 80%; -} - -/* A quick wiggle when the headline is hovered: 360ms, inside the motion budget. */ -.home-hero-title:hover .home-hero-emoji { - animation: home-emoji-wiggle 360ms ease-in-out; -} - -@keyframes home-emoji-wiggle { - 0% { transform: rotate(10deg); } - 30% { transform: rotate(-6deg) scale(1.08); } - 60% { transform: rotate(16deg) scale(1.04); } - 100% { transform: rotate(10deg); } -} - -@media (prefers-reduced-motion: reduce) { - .home-hero-title:hover .home-hero-emoji { - animation: none; - } -} - /* The homepage authoring link opens the setup wizard. */ .home-make-strip { display: grid; @@ -1650,38 +1389,6 @@ } } -/* the homepage rail: fade both ends so a half row reads as depth, not a bug. */ -/* The packet: a rose dot that rides the rail's spine, the CLI ripple as a signal. */ -.home-hero-rail .skill-source-stream__list::after { - content: ''; - position: absolute; - inset-inline-start: calc(1.125rem - 2.5px); - top: 1.75rem; - width: 6px; - height: 6px; - border-radius: 999px; - background: var(--ui-primary); - box-shadow: 0 0 6px 1px var(--ui-primary); - opacity: 0; - animation: home-packet 2.4s ease-in infinite; - animation-delay: 1s; - pointer-events: none; -} - -@keyframes home-packet { - 0% { transform: translateY(0); opacity: 0; } - 8% { opacity: 1; } - 70% { opacity: 1; } - 78% { transform: translateY(calc(100% * 1)); opacity: 0; } - 100% { transform: translateY(0); opacity: 0; } -} - -@media (prefers-reduced-motion: reduce) { - .home-hero-rail .skill-source-stream__list::after { - animation: none; - } -} - .home-hero-rail [class*="stream"] { scrollbar-width: none; } @@ -1742,7 +1449,8 @@ band, so the page reads as one made thing instead of a decorated hero. ========================================================================== */ -/* Band edges are printed in the dot grid, not drawn as a flat rule. */ +/* Band edges are printed in the dot grid, not drawn as a flat rule. Stone + dots: rose is for the one dot a motif picks. */ .home-page > section, .home-page > nav { position: relative; @@ -1756,16 +1464,16 @@ bottom: 0; z-index: 2; height: 5px; - background-image: radial-gradient(circle, var(--ui-primary) 1.1px, transparent 1.4px); + background-image: radial-gradient(circle, var(--ui-text-dimmed) 1.1px, transparent 1.4px); background-size: 7px 5px; - opacity: 0.28; + opacity: 0.5; pointer-events: none; } -/* One word per heading carries the hero's dot underline. */ +/* One word per heading carries a stone underline. */ .home-ink { text-decoration-line: underline; - text-decoration-color: color-mix(in oklab, var(--ui-primary) 65%, transparent); + text-decoration-color: var(--ui-border-accented); text-decoration-thickness: max(2px, 0.045em); text-underline-offset: 0.16em; text-decoration-skip-ink: none; @@ -1799,23 +1507,6 @@ z-index: 1; } -/* The tasted chip: the hero's emoji, reused wherever a person said yes. */ -.home-tasted { - display: inline-flex; - align-items: center; - gap: 0.35rem; - padding: 0.2rem 0.5rem 0.2rem 0.4rem; - border: 1px solid color-mix(in oklab, var(--ui-primary) 32%, transparent); - border-radius: 999px; - background: color-mix(in oklab, var(--ui-primary) 10%, transparent); - color: var(--ui-primary); - font-family: var(--font-mono); - font-size: 0.6875rem; - letter-spacing: 0.04em; - text-transform: uppercase; - white-space: nowrap; -} - /* Ecosystem tiles under the authoring strip. Same chip as the agent row. */ .home-eco-logos { display: flex; @@ -1850,13 +1541,6 @@ color: var(--ui-text-highlighted); } -/* The rail spine carries a rose wash under the packet. */ -.home-hero-rail .skill-source-stream__list::after { - width: 7px; - height: 7px; - box-shadow: 0 0 10px 2px color-mix(in oklab, var(--ui-primary) 70%, transparent); -} - /* One heading scale for every band on /alt. The page had four before. */ .home-page .home-h2 { font-size: clamp(1.875rem, 1.5rem + 1.5vw, 2.625rem); @@ -1900,10 +1584,6 @@ } /* Two h3 steps under the heading scale, not four. */ -.home-page .home-featured-lead__title { - font-size: 1.75rem; -} - .home-page .home-freshness-primary-title, .home-page .home-freshness-secondary-title { font-size: 1.5rem; @@ -1977,13 +1657,6 @@ } } -/* "+N more" closes the lead collection's skill list when it is truncated. */ -.home-featured-skill-more { - display: flex; - align-items: center; - padding: 0.75rem 1rem; -} - /* An in-page jump landed the heading flush against the sticky header, with no space above it. The header is 4rem; this adds a breath on top of that. */ .home-page > section[id] { diff --git a/app/components/NoiseField.client.vue b/app/components/NoiseField.client.vue deleted file mode 100644 index 6ff531ea..00000000 --- a/app/components/NoiseField.client.vue +++ /dev/null @@ -1,405 +0,0 @@ - - - diff --git a/app/pages/index.vue b/app/pages/index.vue index bcb3a7e9..79adb9f3 100644 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -1,9 +1,7 @@