diff --git a/docs/gallery/armature-bend/index.html b/docs/gallery/armature-bend/index.html index dc0a16c..7a1031d 100644 --- a/docs/gallery/armature-bend/index.html +++ b/docs/gallery/armature-bend/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/attribute-domain-shear/index.html b/docs/gallery/attribute-domain-shear/index.html index c8e5813..ac3e0c0 100644 --- a/docs/gallery/attribute-domain-shear/index.html +++ b/docs/gallery/attribute-domain-shear/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/bmesh-gear/index.html b/docs/gallery/bmesh-gear/index.html index 25983f7..bf181c7 100644 --- a/docs/gallery/bmesh-gear/index.html +++ b/docs/gallery/bmesh-gear/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/car-mirror-symmetry/index.html b/docs/gallery/car-mirror-symmetry/index.html index d41ceea..97cac45 100644 --- a/docs/gallery/car-mirror-symmetry/index.html +++ b/docs/gallery/car-mirror-symmetry/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/collision-hull-proxy/index.html b/docs/gallery/collision-hull-proxy/index.html index 5c84f2d..ed49a3c 100644 --- a/docs/gallery/collision-hull-proxy/index.html +++ b/docs/gallery/collision-hull-proxy/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/color-attribute-wheel/index.html b/docs/gallery/color-attribute-wheel/index.html index 2e13a3a..492d2f5 100644 --- a/docs/gallery/color-attribute-wheel/index.html +++ b/docs/gallery/color-attribute-wheel/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/compositor-glare/index.html b/docs/gallery/compositor-glare/index.html index 9277d8a..db5456d 100644 --- a/docs/gallery/compositor-glare/index.html +++ b/docs/gallery/compositor-glare/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/curve-bevel-arc/index.html b/docs/gallery/curve-bevel-arc/index.html index 4f9641c..3bc0b25 100644 --- a/docs/gallery/curve-bevel-arc/index.html +++ b/docs/gallery/curve-bevel-arc/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/custom-normals-shade/index.html b/docs/gallery/custom-normals-shade/index.html index f9193f1..edca46c 100644 --- a/docs/gallery/custom-normals-shade/index.html +++ b/docs/gallery/custom-normals-shade/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/damped-track-aim/index.html b/docs/gallery/damped-track-aim/index.html index aa8e1e5..6f5ec41 100644 --- a/docs/gallery/damped-track-aim/index.html +++ b/docs/gallery/damped-track-aim/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/degenerate-bevel-weld/index.html b/docs/gallery/degenerate-bevel-weld/index.html index 14d45c6..a6dbacf 100644 --- a/docs/gallery/degenerate-bevel-weld/index.html +++ b/docs/gallery/degenerate-bevel-weld/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/depsgraph-export/index.html b/docs/gallery/depsgraph-export/index.html index 58b1bf8..52830ad 100644 --- a/docs/gallery/depsgraph-export/index.html +++ b/docs/gallery/depsgraph-export/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/driver-wave/index.html b/docs/gallery/driver-wave/index.html index 666fd38..12465f4 100644 --- a/docs/gallery/driver-wave/index.html +++ b/docs/gallery/driver-wave/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/gltf-export-roundtrip/index.html b/docs/gallery/gltf-export-roundtrip/index.html index 409e3ed..0c1b860 100644 --- a/docs/gallery/gltf-export-roundtrip/index.html +++ b/docs/gallery/gltf-export-roundtrip/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/gltf-skin-roundtrip/index.html b/docs/gallery/gltf-skin-roundtrip/index.html index 51296e0..26dd9f0 100644 --- a/docs/gallery/gltf-skin-roundtrip/index.html +++ b/docs/gallery/gltf-skin-roundtrip/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/gn-instance-grid/index.html b/docs/gallery/gn-instance-grid/index.html index a60b19e..4f69e10 100644 --- a/docs/gallery/gn-instance-grid/index.html +++ b/docs/gallery/gn-instance-grid/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/gn-sdf-remesh/index.html b/docs/gallery/gn-sdf-remesh/index.html index 7f853ec..18bad45 100644 --- a/docs/gallery/gn-sdf-remesh/index.html +++ b/docs/gallery/gn-sdf-remesh/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/gp-lineart-contour/index.html b/docs/gallery/gp-lineart-contour/index.html index cb1f03e..3f351d1 100644 --- a/docs/gallery/gp-lineart-contour/index.html +++ b/docs/gallery/gp-lineart-contour/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/grease-pencil-rosette/index.html b/docs/gallery/grease-pencil-rosette/index.html index ef5eba9..9450d65 100644 --- a/docs/gallery/grease-pencil-rosette/index.html +++ b/docs/gallery/grease-pencil-rosette/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/image-pixels-testcard/index.html b/docs/gallery/image-pixels-testcard/index.html index 05c1f80..c220454 100644 --- a/docs/gallery/image-pixels-testcard/index.html +++ b/docs/gallery/image-pixels-testcard/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,10 +221,18 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } diff --git a/docs/gallery/index.html b/docs/gallery/index.html index 81e72e3..c2d7d6a 100644 --- a/docs/gallery/index.html +++ b/docs/gallery/index.html @@ -68,14 +68,82 @@ font-size: clamp(2.2rem, 5vw, 3.4rem); letter-spacing: 0.005em; line-height: 0.98; } header.hero p { color: var(--text-dim); max-width: 62ch; margin-top: 0.7rem; font-size: 1rem; } - /* ---- index: filter chips ---- */ - .chips { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 0.25rem; - display: flex; flex-wrap: wrap; gap: 0.5rem; } + /* ---- index: sticky controls (search, density toggle, tag chips) ---- */ + .controls { position: sticky; top: 46px; z-index: 4; + background: color-mix(in srgb, var(--bg) 94%, transparent); + backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); } + .controls-inner { max-width: var(--maxw); margin: 0 auto; padding: 0.55rem 1.25rem 0.6rem; + display: flex; flex-direction: column; gap: 0.5rem; } + .controls-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } + .searchwrap { position: relative; flex: 1 1 240px; min-width: 150px; } + .searchwrap input { width: 100%; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text); border-radius: var(--radius); padding: 0.34rem 1.9rem 0.34rem 0.7rem; + font-family: var(--font-sans); font-size: 0.85rem; line-height: 1.4; } + .searchwrap input:focus { border-color: var(--select); outline: none; } + .searchwrap input::placeholder { color: var(--text-dim); } + .searchwrap input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; } + .q-clear { position: absolute; right: 0.2rem; top: 50%; transform: translateY(-50%); + background: none; border: none; color: var(--text-dim); font-size: 1.05rem; line-height: 1; + cursor: pointer; padding: 0.25rem 0.45rem; border-radius: 3px; } + .q-clear:hover { color: var(--select); } + .count { font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; color: var(--text-dim); white-space: nowrap; } + .density { display: flex; border: 1px solid var(--border); border-radius: var(--radius); + overflow: hidden; } + .density-btn { background: var(--surface-2); border: none; color: var(--text-dim); cursor: pointer; + font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em; + text-transform: uppercase; padding: 0.36rem 0.7rem; transition: color 0.15s, background 0.15s; } + .density-btn + .density-btn { border-left: 1px solid var(--border); } + .density-btn:hover { color: var(--select); } + .density-btn.active { background: var(--select); color: #1a1b1e; } + .tags-toggle { display: none; background: var(--surface-2); border: 1px solid var(--border); + color: var(--text-dim); border-radius: 3px; padding: 0.3rem 0.7rem; cursor: pointer; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; text-transform: uppercase; } + .tags-toggle:hover, .tags-toggle.has-active { color: var(--select); border-color: var(--select); } + + /* Tag chips wrap by default (no-JS safe). With JS the row becomes a scroll + strip on wide viewports and collapses behind the Tags toggle on narrow + ones, so the sticky bar never eats the mobile viewport. */ + .chips { display: flex; flex-wrap: wrap; gap: 0.4rem; } + html.js .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 0.25rem; + scrollbar-width: thin; scrollbar-color: var(--border) transparent; } + html.js .chips::-webkit-scrollbar { height: 5px; } + html.js .chips::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } .chip { background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); border-radius: 3px; padding: 0.22rem 0.7rem; font-size: 0.72rem; font-weight: 400; - font-family: var(--font-mono); cursor: pointer; transition: color 0.15s, border-color 0.15s; } + font-family: var(--font-mono); cursor: pointer; white-space: nowrap; flex: 0 0 auto; + transition: color 0.15s, border-color 0.15s; } .chip:hover { color: var(--select); border-color: var(--select); } .chip.active { color: #1a1b1e; background: var(--select); border-color: var(--select); } + @media (max-width: 719px) { + html.js .tags-toggle { display: inline-block; } + html.js .chips { display: none; } + html.js .chips.open { display: flex; flex-wrap: wrap; overflow-y: auto; max-height: 40vh; } + } + + /* Compact density: hero + name + one-line teaser. The description and + WITNESSES text stay in the DOM (searchable, screen-reader reachable, + present with JS disabled when the class is never applied) but are + visually collapsed. Applied only by JS via the density-compact class. */ + html.density-compact .grid { gap: 1rem; } + html.density-compact .card-body { padding: 0.65rem 0.9rem 0.7rem; } + html.density-compact .card-body h2 { font-size: 0.88rem; margin-bottom: 0.15rem; } + html.density-compact .teaches { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 0; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } + html.density-compact .witnesses { position: absolute; width: 1px; height: 1px; margin: -1px; + padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; } + html.density-compact .card-link { display: none; } + .noresults { color: var(--text-dim); text-align: center; padding: 3rem 1rem; font-size: 0.95rem; } + .noresults .chip { margin-left: 0.6rem; } + .to-top { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 6; cursor: pointer; + background: var(--surface-2); border: 1px solid var(--border); color: var(--text-dim); + border-radius: var(--radius); padding: 0.45rem 0.75rem; + font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.04em; + text-transform: uppercase; opacity: 0; visibility: hidden; + transition: opacity 0.2s, visibility 0.2s, color 0.15s, border-color 0.15s; } + .to-top.show { opacity: 1; visibility: visible; } + .to-top:hover { color: var(--select); border-color: var(--select); } main { max-width: var(--maxw); margin: 0 auto; padding: 1rem 1.25rem 2rem; } .grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: stretch; } @@ -153,12 +221,36 @@ footer .statusbar code { font-family: inherit; text-transform: none; } @media (min-width: 720px) { .grid { grid-template-columns: 1fr 1fr; gap: 1.75rem; } } + @media (min-width: 560px) { html.density-compact .grid { grid-template-columns: 1fr 1fr; gap: 1rem; } } + @media (min-width: 900px) { html.density-compact .grid { grid-template-columns: repeat(3, 1fr); } } + @media (min-width: 1560px) { + html.density-compact .controls-inner, + html.density-compact main { max-width: 1400px; } + html.density-compact .grid { grid-template-columns: repeat(4, 1fr); } + } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .card { transition: none; } .card:hover { transform: none; } + .to-top { transition: none; } } + @@ -172,47 +264,64 @@

Examples Gallery

Runnable, smoke-gated Blender Python examples — each executed headless on Blender 4.5 LTS and 5.1, so every render reflects code that actually runs.

-