diff --git a/README.md b/README.md
index 826f7c2..17a651d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# The Agentic Interface Framework — website
+# The Agent Interface Framework — website
A three-page static site for the framework *Eight primitives for the
layer where humans meet agentic software*. No build step, no runtime
@@ -8,11 +8,10 @@ palette, sharp corners, inline Phosphor icons.
## Pages
- **Home** (`index.html`) — hero, "the interface is the unsolved half"
- intro with a CTA into the test, the eight primitives as exclusive
+ intro with a CTA into the test, the eight primitives as
accordions (one-liner, description, feature cards with image
- placeholders), contributors, and a contribute CTA that opens a
- mail-app form.
-- **Test** (`quicktest.html`) — The Agentic Interface Test: Quick test
+ placeholders), contributors, and a contribute-by-email line.
+- **Test** (`quicktest.html`) — The Agent Interface Test: Quick test
(16 questions) and Deep dive (48 questions) as switchable modes, all
questions on one page with a sticky "Generate score" bar; results open
in a modal with a level stepper (Chatbot → Fully Agentic), a radar
@@ -38,9 +37,8 @@ palette, sharp corners, inline Phosphor icons.
z-scale, motion) and shared components (`.btn`, `.numbox`, `.input`,
page-header band), plus all Home styles.
- `ait.css` — test-page styles, all `ait-` prefixed.
-- `script.js` — Home interactions: contribute form (opens the visitor's
- mail app addressed to parikshit@thesys.dev), animated exclusive
- accordions, scroll reveals. Home remains fully readable with
+- `script.js` — Home interactions: animated accordions (any number open
+ at once) and scroll reveals. Home remains fully readable with
JavaScript disabled.
- `ait-questions.js` — test data (`window.AIT_DATA`): 8 primitives,
16 + 48 questions with tooltips and fixes, 5 maturity levels.
diff --git a/ait-questions.js b/ait-questions.js
index f91ec4d..834fb3c 100644
--- a/ait-questions.js
+++ b/ait-questions.js
@@ -1,4 +1,4 @@
-// The Agentic Interface Test — question data.
+// The Agent Interface Test — question data.
// Every fix string is authored here at build time and never generated.
window.AIT_DATA = (function () {
'use strict';
diff --git a/ait.css b/ait.css
index beb7808..405ae14 100644
--- a/ait.css
+++ b/ait.css
@@ -128,7 +128,7 @@
.ait-row {
border-bottom: 1px solid var(--hairline);
- padding: 0.7rem 0.25rem;
+ padding: 1.15rem 0.25rem;
}
/* Deep-dive sections: the rows only carry bottom borders, so the
@@ -609,17 +609,28 @@ html[data-theme="dark"] .ait-radar-data { fill: rgba(242, 242, 242, 0.1); }
}
@media (max-width: 640px) {
- /* Two fixed 13rem tabs exceed narrow viewports — go fluid. */
+ /* Fluid tabs with a comfortable tap height on touch screens. */
.ait-mode-tabs { display: flex; }
- .ait-mode-tab { min-width: 0; flex: 1; }
+ .ait-mode-tab { min-width: 0; flex: 1; min-height: 42px; justify-content: center; }
+
+ /* Number tile on top, question below it; Yes/No sits on the text's
+ left edge with the "?" on the right at a matching size. */
.ait-row-main {
+ flex-direction: column;
+ align-items: stretch;
+ gap: 0.8rem;
+ }
+ .ait-row-textwrap {
flex-direction: column;
align-items: flex-start;
- gap: 0.6rem;
+ gap: 0.55rem;
+ max-width: none;
+ }
+ .ait-row-controls {
+ justify-content: space-between;
}
- .ait-seg-group { align-self: stretch; }
- .ait-seg { flex: 1; }
- .ait-seg-label { width: 100%; }
+ .ait-tip-btn { width: 2rem; height: 2rem; }
+ .ait-name-row .ait-name-input { width: 100%; max-width: none; }
.ait-genbar { flex-direction: column; align-items: stretch; gap: 0.5rem; }
.ait-generate { width: 100%; }
.ait-modal { padding: 1.5rem 1.1rem 1.25rem; }
diff --git a/ait.js b/ait.js
index b9f9fda..5768bba 100644
--- a/ait.js
+++ b/ait.js
@@ -1,4 +1,4 @@
-// The Agentic Interface Test — app logic. Plain script, no dependencies,
+// The Agent Interface Test — app logic. Plain script, no dependencies,
// no network. All questions render on one page; results open in a modal.
(function () {
'use strict';
@@ -68,7 +68,7 @@
// Title line shared by the modal and the canvas scorecard.
function scoreTitle(name, score) {
- return (name ? name + '\u2019s Agentic Interface Score' : 'Your Agentic Interface Score') +
+ return (name ? name + '\u2019s Agent Interface Score' : 'Your Agent Interface Score') +
' : ' + score + '/100';
}
diff --git a/components.js b/components.js
index 8575e2f..bc35be1 100644
--- a/components.js
+++ b/components.js
@@ -18,6 +18,7 @@
'arrow-up': 'M205.66 117.66a8 8 0 0 1-11.32 0L136 59.31V216a8 8 0 0 1-16 0V59.31L61.66 117.66a8 8 0 0 1-11.32-11.32l72-72a8 8 0 0 1 11.32 0l72 72a8 8 0 0 1 0 11.32Z',
check: 'M229.66 77.66l-128 128a8 8 0 0 1-11.32 0l-56-56a8 8 0 0 1 11.32-11.32L96 188.69 218.34 66.34a8 8 0 0 1 11.32 11.32Z',
x: 'M205.66 194.34a8 8 0 0 1-11.32 11.32L128 139.31l-66.34 66.35a8 8 0 0 1-11.32-11.32L116.69 128 50.34 61.66a8 8 0 0 1 11.32-11.32L128 116.69l66.34-66.35a8 8 0 0 1 11.32 11.32L139.31 128Z',
+ list: 'M224 128a8 8 0 0 1-8 8H40a8 8 0 0 1 0-16h176a8 8 0 0 1 8 8ZM40 72h176a8 8 0 0 0 0-16H40a8 8 0 0 0 0 16Zm176 112H40a8 8 0 0 0 0 16h176a8 8 0 0 0 0-16Z',
moon: 'M233.54 142.23a8 8 0 0 0-8-2 88.08 88.08 0 0 1-109.8-109.8 8 8 0 0 0-10-10 104.84 104.84 0 0 0-52.91 37A104 104 0 0 0 136 224a103.09 103.09 0 0 0 62.52-20.88 104.84 104.84 0 0 0 37-52.91 8 8 0 0 0-1.98-7.98Zm-44.64 48.11A88 88 0 0 1 65.66 67.11a89 89 0 0 1 31.4-26A106 106 0 0 0 96 56a104.11 104.11 0 0 0 104 104 106 106 0 0 0 14.92-1.06 89 89 0 0 1-26.02 31.4Z',
monitor: 'M208 40H48a24 24 0 0 0-24 24v112a24 24 0 0 0 24 24h160a24 24 0 0 0 24-24V64a24 24 0 0 0-24-24Zm8 136a8 8 0 0 1-8 8H48a8 8 0 0 1-8-8V64a8 8 0 0 1 8-8h160a8 8 0 0 1 8 8ZM168 224a8 8 0 0 1-8 8H96a8 8 0 0 1 0-16h64a8 8 0 0 1 8 8Z',
sun: 'M120 40V16a8 8 0 0 1 16 0v24a8 8 0 0 1-16 0Zm72 88a64 64 0 1 1-64-64 64.07 64.07 0 0 1 64 64Zm-16 0a48 48 0 1 0-48 48 48.05 48.05 0 0 0 48-48ZM58.34 69.66a8 8 0 0 0 11.32-11.32l-16-16a8 8 0 0 0-11.32 11.32Zm0 116.68-16 16a8 8 0 0 0 11.32 11.32l16-16a8 8 0 0 0-11.32-11.32ZM192 72a8 8 0 0 0 5.66-2.34l16-16a8 8 0 0 0-11.32-11.32l-16 16A8 8 0 0 0 192 72Zm5.66 114.34a8 8 0 0 0-11.32 11.32l16 16a8 8 0 0 0 11.32-11.32ZM48 128a8 8 0 0 0-8-8H16a8 8 0 0 0 0 16h24a8 8 0 0 0 8-8Zm80 80a8 8 0 0 0-8 8v24a8 8 0 0 0 16 0v-24a8 8 0 0 0-8-8Zm112-88h-24a8 8 0 0 0 0 16h24a8 8 0 0 0 0-16Z'
@@ -54,23 +55,46 @@
'Skip to content ' +
'';
+ '' +
+ '
';
+
+ // Mobile hamburger: collapses the nav into a panel under the bar.
+ var headerEl = this.querySelector('.site-header');
+ var navToggle = this.querySelector('.nav-toggle');
+ function setMenu(open) {
+ headerEl.classList.toggle('menu-open', open);
+ document.documentElement.classList.toggle('menu-locked', open);
+ navToggle.setAttribute('aria-expanded', String(open));
+ navToggle.innerHTML = iconSVG(open ? 'x' : 'list', 18);
+ }
+ navToggle.addEventListener('click', function () {
+ setMenu(!headerEl.classList.contains('menu-open'));
+ });
+ this.querySelector('.menu-scrim').addEventListener('click', function () { setMenu(false); });
+ document.addEventListener('keydown', function (e) {
+ if (e.key === 'Escape') setMenu(false);
+ });
+ setMenu(false);
// Star count: fetched from the GitHub API, cached for an hour.
// On any failure the count stays hidden and the button still links.
diff --git a/index.html b/index.html
index 4740182..f780b97 100644
--- a/index.html
+++ b/index.html
@@ -21,9 +21,9 @@
- The Agentic Interface Framework
+ The Agent Interface Framework
-
+
@@ -45,7 +45,7 @@
-
Agentic Interface Framework
+
Agent Interface Framework
A best-practice framework for taking your AI app from chatbot to agentic software.
@@ -70,7 +70,7 @@ The eight primitives
The eight primitives are the building blocks of an agentic interface. Each one names a category of concrete, proven patterns — from expressing intent to recovering from failure. Applied together, they produce a product where people can direct the agent, watch it work, trust its results, and keep what it makes: an interface, not just a chat box. Open a primitive to see its patterns.
-
+
1
Guide intent
@@ -150,7 +150,7 @@ Structured inputs
-
+
2
Reveal progress
@@ -262,7 +262,7 @@ Async & background work
-
+
3
Show, don’t tell
@@ -342,7 +342,7 @@ Accessible generated UI
-
+
4
Keep control
@@ -446,7 +446,7 @@ Respectful surfacing
-
+
5
Earn trust
@@ -550,7 +550,7 @@ Agent identity
-
+
6
Expect failure
@@ -635,7 +635,7 @@ Refusal surfaces
-
+
7
Make artifacts
@@ -729,7 +729,7 @@ Portability
-
+
8
Build a home
@@ -887,31 +887,15 @@ Feedback & steering
Written by practitioners
Engineers, designers, and product leaders who build agentic software and have watched the same problems recur across very different products.
+ P Parikshit
+ R Rabi
A Abhishek
A Aditya
- P Parikshit
P Prakhar
- R Rabi
Z Zahle
This is a starting point, not a finished specification. If these primitives describe what you have already learned, sign on. If they miss something, say what, and show the pattern.
-
- Contribute
-
-
+ To contribute, write to us at hello@thesys.dev .
diff --git a/quicktest.html b/quicktest.html
index 6b92efb..5db7e76 100644
--- a/quicktest.html
+++ b/quicktest.html
@@ -23,9 +23,9 @@
- The Agentic Interface Test — The Agentic Interface Framework
+ The Agent Interface Test — The Agent Interface Framework
-
+
@@ -36,7 +36,7 @@
diff --git a/resources.html b/resources.html
index b0758ab..1c21d0e 100644
--- a/resources.html
+++ b/resources.html
@@ -20,9 +20,9 @@
- Resources — The Agentic Interface Framework
+ Resources — The Agent Interface Framework
-
+
@@ -46,10 +46,9 @@ Resources
Agent Interface
By OpenUI
- The open-source, production-ready, best-practice implementation of the Agentic Interface Framework.
+ The open-source, production-ready, best-practice implementation of the Agent Interface Framework.
Explore Agent Interface
- Image
diff --git a/script.js b/script.js
index 27dcfd8..c0b217b 100644
--- a/script.js
+++ b/script.js
@@ -1,48 +1,11 @@
-// Home-page interactions: contribute form, accordions, scroll reveals.
+// Home-page interactions: accordions, scroll reveals.
// ---------------------------------------------------------------
-// Contribute CTA: reveal the form, submit via the user's mail app
-// ---------------------------------------------------------------
-const contribBtn = document.getElementById('contrib-btn');
-const contribForm = document.getElementById('contrib-form');
-
-function openContribute(focus = true) {
- if (!contribForm) return;
- contribForm.hidden = false;
- contribBtn.setAttribute('aria-expanded', 'true');
- if (focus) contribForm.querySelector('input[name="name"]').focus();
-}
-
-if (contribBtn && contribForm) {
- contribBtn.addEventListener('click', () => {
- if (contribForm.hidden) openContribute();
- else {
- contribForm.hidden = true;
- contribBtn.setAttribute('aria-expanded', 'false');
- }
- });
-
- contribForm.addEventListener('submit', (e) => {
- e.preventDefault();
- const name = contribForm.elements.name.value.trim();
- const message = contribForm.elements.message.value.trim();
- const subject = 'Contributing to the Agentic Interface Framework';
- const body = (name ? 'Name: ' + name + '\n\n' : '') + message;
- window.location.href =
- 'mailto:parikshit@thesys.dev?subject=' + encodeURIComponent(subject) +
- '&body=' + encodeURIComponent(body);
- });
-
- // Deep link: arriving at ./#contribute opens the form in place.
- if (location.hash === '#contribute') openContribute(false);
-}
-
-// ---------------------------------------------------------------
-// Accordions: exclusive open, animated as expand-then-fade.
+// Accordions: any number open at once, animated as expand-then-fade.
// The panel's height eases open first; once it has expanded, the
// content fades in. Collapse animates height and opacity together.
-// With prefers-reduced-motion (or no JS) the native details
-// behavior and its name="" exclusivity apply instead.
+// With prefers-reduced-motion (or no JS) the native details toggle
+// applies instead.
// ---------------------------------------------------------------
const accItems = Array.from(document.querySelectorAll('details.acc-item'));
const ACC_REDUCED = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
@@ -88,12 +51,6 @@ function accExpand(item) {
accSettle(body, 330, () => {
body.style.cssText = '';
delete item.dataset.animating;
- // A sibling asked this panel to close while it was mid-expand
- // (exclusivity would otherwise leave two panels open).
- if (item.dataset.closeAfter) {
- delete item.dataset.closeAfter;
- accCollapse(item);
- }
});
});
}
@@ -114,28 +71,7 @@ function accCollapse(item) {
});
}
-// Closes `item` instantly and keeps `anchorEl` (the clicked summary)
-// at the same viewport position. Used for open siblings ABOVE the
-// clicked row: an animated collapse there would drag the clicked row
-// up under the cursor, which reads as a scroll glitch. The correction
-// is the row's measured displacement, so any scroll clamping the
-// browser applies when the document shrinks is accounted for.
-function accCollapseAbove(item, anchorEl) {
- const body = item.querySelector('.acc-body');
- body.style.cssText = '';
- delete item.dataset.animating;
- delete item.dataset.closeAfter;
- const before = anchorEl.getBoundingClientRect().top;
- item.open = false;
- const shift = anchorEl.getBoundingClientRect().top - before;
- if (shift) window.scrollBy(0, shift);
-}
-
if (accItems.length && !ACC_REDUCED) {
- // JS drives exclusivity so sibling closes can animate; the native
- // exclusive-accordion attribute would snap them shut instead.
- accItems.forEach((d) => d.removeAttribute('name'));
-
accItems.forEach((item) => {
const summary = item.querySelector('summary');
const body = item.querySelector('.acc-body');
@@ -146,25 +82,51 @@ if (accItems.length && !ACC_REDUCED) {
if (item.open) {
accCollapse(item);
} else {
- accItems.forEach((other) => {
- if (other === item || !other.open) return;
- // "other precedes item": collapse instantly with scroll
- // compensation so the clicked row stays pinned; siblings
- // below can animate freely without shifting the row.
- if (other.compareDocumentPosition(item) & Node.DOCUMENT_POSITION_FOLLOWING) {
- accCollapseAbove(other, summary);
- } else if (other.dataset.animating) {
- other.dataset.closeAfter = '1';
- } else {
- accCollapse(other);
- }
- });
accExpand(item);
}
});
});
}
+// ---------------------------------------------------------------
+// Feature carousels: on mobile the card grids scroll horizontally;
+// a numbered square pager under each grid tracks and drives them.
+// (The pager is display:none on desktop, where the grid is a grid.)
+// ---------------------------------------------------------------
+document.querySelectorAll('.feature-grid').forEach((grid) => {
+ const cards = grid.querySelectorAll('.feature');
+ if (cards.length < 2) return;
+ const pager = document.createElement('div');
+ pager.className = 'feature-pager';
+ const tiles = [];
+ cards.forEach((card, i) => {
+ const b = document.createElement('button');
+ b.type = 'button';
+ b.className = 'numbox';
+ b.textContent = String(i + 1);
+ b.setAttribute('aria-label', 'Go to card ' + (i + 1) + ' of ' + cards.length);
+ b.addEventListener('click', () => {
+ grid.scrollTo({
+ left: card.offsetLeft - cards[0].offsetLeft,
+ behavior: ACC_REDUCED ? 'auto' : 'smooth'
+ });
+ });
+ pager.appendChild(b);
+ tiles.push(b);
+ });
+ const setActive = () => {
+ // Stride = real card spacing (cards are narrower than the padded grid).
+ const stride = cards.length > 1 ? cards[1].offsetLeft - cards[0].offsetLeft : grid.clientWidth;
+ const ix = Math.min(Math.round(grid.scrollLeft / stride), tiles.length - 1);
+ tiles.forEach((t, i) => t.classList.toggle('active', i === ix));
+ };
+ // Direct call, not rAF-deferred: throttled webviews freeze rAF and
+ // the active tile would never update. The work is a few class toggles.
+ grid.addEventListener('scroll', setActive, { passive: true });
+ setActive();
+ grid.after(pager);
+});
+
// ---------------------------------------------------------------
// Scroll-entry reveals, with a hard fallback: if IntersectionObserver
// is unavailable, everything is shown immediately.
diff --git a/styles.css b/styles.css
index 009671e..4f5a4cf 100644
--- a/styles.css
+++ b/styles.css
@@ -255,6 +255,20 @@ body::after { right: calc(50% - var(--container-max) / 2); }
background: var(--ink);
}
+.nav-toggle {
+ display: none;
+ align-items: center;
+ justify-content: center;
+ width: 2.2rem;
+ height: 2.2rem;
+ background: none;
+ border: none;
+ color: var(--ink);
+ cursor: pointer;
+}
+
+.nav-toggle svg { display: block; }
+
.gh-btn {
display: inline-flex;
align-items: center;
@@ -290,6 +304,17 @@ html[data-theme="dark"] .gh-btn:hover {
.gh-btn svg { display: block; }
+.gh-label { display: none; }
+
+.menu-note { display: none; }
+
+/* Page scroll is locked while the mobile menu is open. */
+html.menu-locked { overflow: hidden; }
+
+/* Scrim behind the open mobile menu: dark veil over the page with the
+ site's halftone texture fading out from top to bottom. */
+.menu-scrim { display: none; }
+
/* ---------- hero ---------- */
.hero {
@@ -549,6 +574,25 @@ html[data-theme="dark"] .gh-btn:hover {
color: var(--ink-soft);
}
+/* Mobile carousel pager: square numbered tiles under each card set. */
+.feature-pager {
+ display: none;
+ justify-content: center;
+ gap: 0.5rem;
+ margin-top: 1.1rem;
+}
+
+.feature-pager .numbox {
+ cursor: pointer;
+ transition: background 150ms, border-color 150ms, color 150ms;
+}
+
+.feature-pager .numbox.active {
+ background: var(--ink);
+ border-color: var(--ink);
+ color: var(--on-ink);
+}
+
.ph {
aspect-ratio: 16 / 10;
display: flex;
@@ -632,18 +676,6 @@ html[data-theme="dark"] .gh-btn:hover {
border-color: var(--ink);
}
-textarea.input { resize: vertical; }
-
-.field-label {
- display: block;
- font-family: var(--font);
- font-size: var(--label-sm);
- font-weight: 500;
- letter-spacing: 0.02em;
- color: var(--muted);
- margin-bottom: 0.5rem;
-}
-
/* ---------- contributors + contribute ---------- */
.contributors {
@@ -687,31 +719,15 @@ textarea.input { resize: vertical; }
margin-bottom: 1.5rem;
}
-.contrib-form {
- margin-top: 2.25rem;
- max-width: 34rem;
- display: grid;
- gap: 1.25rem;
-}
-
-/* display:grid above would otherwise defeat the hidden attribute */
-.contrib-form[hidden] { display: none; }
-
-.contrib-form label { display: block; }
-
-.form-row {
- display: flex;
- align-items: center;
- gap: 1.25rem;
- flex-wrap: wrap;
+.contrib-mail {
+ color: var(--ink);
+ font-weight: 500;
+ text-decoration: underline;
+ text-underline-offset: 3px;
+ text-decoration-thickness: 1px;
}
-.form-note {
- font-family: var(--font);
- font-size: var(--label-sm);
- letter-spacing: 0.01em;
- color: var(--muted);
-}
+.contrib-mail:hover { text-decoration-thickness: 2px; }
/* ---------- page header band (Test, Resources) ---------- */
@@ -751,6 +767,7 @@ textarea.input { resize: vertical; }
flex-direction: column;
align-items: flex-start;
gap: 0.75rem;
+ min-width: 0; /* grid items must be able to shrink below content size */
border: 1px solid var(--hairline);
background: var(--surface);
padding: 1.5rem;
@@ -792,13 +809,6 @@ html[data-theme="dark"] .res-card:not(.res-feature):focus-within {
.res-feature .btn { margin-top: 0.5rem; }
-.res-feature .ph {
- width: 22rem;
- max-width: 40%;
- flex-shrink: 0;
- margin-bottom: 0;
-}
-
.res-by {
font-family: var(--font);
font-size: var(--label-md);
@@ -997,10 +1007,87 @@ html.js .reveal.in {
:root { --container-pad: 1.5rem; }
body { font-size: 16px; }
- .header-inner { flex-direction: column; gap: 0; }
- .wordmark { padding: 0.8rem 0 0.1rem; align-self: flex-start; }
- .tabs { gap: 1.4rem; }
- .tab { padding: 0.6rem 0.1rem; }
+ /* Single-row bar; the nav collapses into a hamburger panel. */
+ .wordmark { padding: 0.8rem 0; }
+ .nav-toggle { display: inline-flex; align-self: center; }
+ .tabs {
+ display: none;
+ position: absolute;
+ top: 100%;
+ left: 0;
+ right: 0;
+ flex-direction: column;
+ align-items: stretch;
+ gap: 0;
+ background: var(--bg);
+ border-bottom: 1px solid var(--hairline);
+ padding: 4rem 1.25rem 1.25rem;
+ }
+ .menu-note {
+ display: block;
+ font-family: var(--font);
+ font-size: var(--label-md);
+ color: var(--muted);
+ text-align: center;
+ padding: 0 0.5rem;
+ margin-top: 1rem;
+ }
+ .menu-note a {
+ color: var(--ink);
+ font-weight: 500;
+ text-decoration: underline;
+ text-underline-offset: 2px;
+ }
+ /* With the menu open, the bar goes solid so it reads as one
+ surface with the panel (the frosted 60% tint would otherwise
+ blend with the dark scrim and look gray). */
+ .site-header.menu-open {
+ background: var(--bg);
+ backdrop-filter: none;
+ -webkit-backdrop-filter: none;
+ border-bottom-color: transparent;
+ }
+ .site-header.menu-open .tabs { display: flex; }
+ .tab {
+ align-self: stretch;
+ padding: 0.8rem 0.5rem;
+ font-size: 0.95rem;
+ }
+ .tab + .tab { border-top: 1px solid var(--hairline); }
+ .gh-btn {
+ margin: 4rem 0 0;
+ align-self: stretch;
+ justify-content: flex-start;
+ gap: 0.6rem;
+ padding: 0.7rem 0.9rem;
+ }
+ .gh-label { display: inline; }
+ .gh-btn .gh-stars {
+ margin-left: auto;
+ background: var(--chip-bg);
+ color: var(--ink-soft);
+ font-size: var(--label-md);
+ padding: 0.2rem 0.55rem;
+ }
+ /* Sibling of the header (a fixed child would be trapped by the
+ header's backdrop-filter containing block). Below the header's
+ z-index so the panel stays on top. */
+ .site-header.menu-open + .menu-scrim {
+ display: block;
+ position: fixed;
+ inset: 0;
+ z-index: calc(var(--z-header) - 1);
+ background: rgba(17, 17, 17, 0.78);
+ }
+ .menu-scrim::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background-image: radial-gradient(rgba(255, 255, 255, 0.55) 1px, transparent 1.5px);
+ background-size: 5px 5px;
+ -webkit-mask-image: linear-gradient(to bottom, #000, transparent 75%);
+ mask-image: linear-gradient(to bottom, #000, transparent 75%);
+ }
.hero { padding: 6.5rem 0 5.5rem; }
/* The desktop line break pins "Agentic Interface" to one line,
@@ -1011,14 +1098,34 @@ html.js .reveal.in {
.contributors { padding: 4.5rem 0 5rem; }
.page-header { padding: 4rem 0 2.75rem; }
- .feature-grid { grid-template-columns: 1fr; }
+ /* Feature cards become a swipeable carousel with a numbered pager. */
+ .feature-grid {
+ display: flex;
+ /* Full viewport width with a small gutter, escaping the accordion
+ body's indent; cards fill the padded width. */
+ margin: 0 calc(50% - 50vw);
+ padding: 0 1.1rem;
+ scroll-padding: 0 1.1rem;
+ overflow-x: auto;
+ scroll-snap-type: x mandatory;
+ scrollbar-width: none;
+ -webkit-overflow-scrolling: touch;
+ }
+ .feature-grid::-webkit-scrollbar { display: none; }
+ .feature { flex: 0 0 100%; scroll-snap-align: start; }
+ .feature-pager { display: flex; }
+
+ /* No hover on touch: resource CTAs always visible. */
+ .res-cta { opacity: 1; transform: none; }
.contrib-names { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.res-grid { grid-template-columns: 1fr; }
- .res-feature { flex-direction: column; align-items: flex-start; }
+ .res-feature { flex-direction: column; align-items: stretch; gap: 1.25rem; }
+ .res-feature .btn { align-self: flex-start; }
.acc-title { font-size: 1.15rem; }
.acc-item summary { gap: 0.9rem; padding: 1.25rem 0.1rem; }
- .acc-body { padding-left: 2.8rem; }
+ /* Body text uses the full width instead of hanging under the title. */
+ .acc-body { padding-left: 0.1rem; padding-right: 0.1rem; }
.site-footer { padding: 3rem 0 9rem; }
}