mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-14 15:16:35 +03:00
Move type scale and layout ahead of the five-card hub.
Type scale and layout return to the linear path before configure; the hub shrinks to five cards with updated navigation. Also fixes palette tooltip clipping, drops the design-context masthead and icon hub notes, and locks the mosaic shell to the viewport without overflow. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+93
-116
@@ -907,104 +907,6 @@ const questions = [
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Screen 04b: the configure hub. Every remaining question already
|
||||
holds an answer (defaults are pre-filled the moment a surface tile
|
||||
is checked), so the run can end here. The cards are skeletons;
|
||||
summaries and edited marks are written by renderHub() in
|
||||
scripts/palette-picker.js on every arrival. Placement is the
|
||||
approved masonry: tall per-surface cards anchor the outer columns. */}
|
||||
<section class="picker-screen" data-screen="04b" data-step="Configure" aria-hidden="true" aria-labelledby="picker-hub-title">
|
||||
<div class="picker-container">
|
||||
<div class="picker-hub">
|
||||
<div class="picker-question-head">
|
||||
<h2 id="picker-hub-title" class="picker-question-title">What else would you like to configure?</h2>
|
||||
<p class="picker-question-lede">
|
||||
Every choice below already holds a sensible default for your surfaces. Open any card to adjust it, or create your design context right away.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="picker-hub-grid">
|
||||
<div class="picker-hub-col">
|
||||
<button class="picker-hub-card" type="button" data-hub-target="06" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Motion
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
<button class="picker-hub-card" type="button" data-hub-target="09" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Corners
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="picker-hub-col">
|
||||
<button class="picker-hub-card" type="button" data-hub-target="05" data-hub-category="typography">
|
||||
<span class="picker-hub-eyebrow">Typography</span>
|
||||
<span class="picker-hub-title">Type scale
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
<button class="picker-hub-card" type="button" data-hub-target="11" data-hub-category="iconography">
|
||||
<span class="picker-hub-eyebrow">Iconography</span>
|
||||
<span class="picker-hub-title">Icon set
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
<button class="picker-hub-card" type="button" data-hub-target="08" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Boundaries
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="picker-hub-col">
|
||||
<button class="picker-hub-card" type="button" data-hub-target="07" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Layout
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
<button class="picker-hub-card" type="button" data-hub-target="10" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Depth
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="picker-actions-stack">
|
||||
<button class="ks-button ks-button-primary" type="button" data-hub-finish data-hub-target="12">
|
||||
Create my design context
|
||||
<span class="ks-button-arrow" aria-hidden="true">
|
||||
<svg viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square">
|
||||
<path d="M0 4h14M10 0l4 4-4 4"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<button class="picker-back" type="button" data-advance="prev">Back</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="picker-screen" data-screen="05" data-step="Type scale" aria-hidden="true" aria-labelledby="picker-scale-title">
|
||||
<div class="picker-container">
|
||||
<div class="picker-scale">
|
||||
@@ -1154,7 +1056,91 @@ const questions = [
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{questions.map((question) => <QuestionScreen {...question} />)}
|
||||
{questions.filter((question) => question.id === '07').map((question) => <QuestionScreen {...question} />)}
|
||||
|
||||
{/* Screen 04b: the configure hub. Every remaining question already
|
||||
holds an answer (defaults are pre-filled the moment a surface tile
|
||||
is checked), so the run can end here. The cards are skeletons;
|
||||
summaries and edited marks are written by renderHub() in
|
||||
scripts/palette-picker.js on every arrival. Placement is the
|
||||
approved masonry: tall per-surface cards anchor the outer columns. */}
|
||||
<section class="picker-screen" data-screen="04b" data-step="Configure" aria-hidden="true" aria-labelledby="picker-hub-title">
|
||||
<div class="picker-container">
|
||||
<div class="picker-hub">
|
||||
<div class="picker-question-head">
|
||||
<h2 id="picker-hub-title" class="picker-question-title">What else would you like to configure?</h2>
|
||||
<p class="picker-question-lede">
|
||||
Every choice below already holds a sensible default for your surfaces. Open any card to adjust it, or create your design context right away.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="picker-hub-grid">
|
||||
<div class="picker-hub-col">
|
||||
<button class="picker-hub-card" type="button" data-hub-target="06" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Motion
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
<button class="picker-hub-card" type="button" data-hub-target="08" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Boundaries
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="picker-hub-col">
|
||||
<button class="picker-hub-card" type="button" data-hub-target="11" data-hub-category="iconography">
|
||||
<span class="picker-hub-eyebrow">Iconography</span>
|
||||
<span class="picker-hub-title">Icon set
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
<button class="picker-hub-card" type="button" data-hub-target="09" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Corners
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="picker-hub-col">
|
||||
<button class="picker-hub-card" type="button" data-hub-target="10" data-hub-category="material">
|
||||
<span class="picker-hub-eyebrow">Material</span>
|
||||
<span class="picker-hub-title">Depth
|
||||
<svg class="picker-hub-arrow" viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square" aria-hidden="true"><path d="M0 4h14M10 0l4 4-4 4"></path></svg>
|
||||
<span class="picker-hub-mark" data-hub-mark hidden>Edited</span>
|
||||
</span>
|
||||
<span class="picker-hub-summary" data-hub-summary></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="picker-actions-stack">
|
||||
<button class="ks-button ks-button-primary" type="button" data-hub-finish data-hub-target="12">
|
||||
Create my design context
|
||||
<span class="ks-button-arrow" aria-hidden="true">
|
||||
<svg viewBox="0 0 16 8" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square">
|
||||
<path d="M0 4h14M10 0l4 4-4 4"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<button class="picker-back" type="button" data-advance="prev">Back</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{questions.filter((question) => question.id !== '07').map((question) => <QuestionScreen {...question} />)}
|
||||
|
||||
<section class="picker-screen" data-screen="11" data-step="Icons" aria-hidden="true" aria-labelledby="picker-icons-title">
|
||||
<div class="picker-container">
|
||||
@@ -1278,17 +1264,6 @@ const questions = [
|
||||
templates start empty and are filled from the interview by
|
||||
scripts/design-context.js. */}
|
||||
<section class="dcx-shell" data-dcx-shell hidden aria-label="Design context categories">
|
||||
<header class="dcx-masthead">
|
||||
<span class="dcx-masthead-brand">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M5 2.5 L13.5 2.5 L5.5 21.5 L5 21.5 Q2.5 21.5 2.5 19 L2.5 5 Q2.5 2.5 5 2.5 Z"></path>
|
||||
<path d="M16.5 2.5 L19 2.5 Q21.5 2.5 21.5 5 L21.5 19 Q21.5 21.5 19 21.5 L8.5 21.5 Z"></path>
|
||||
</svg>
|
||||
<span>Impeccable</span>
|
||||
</span>
|
||||
<span class="dcx-masthead-title" data-dcx-product>Design context</span>
|
||||
<span class="dcx-masthead-note">Assembled from your interview · answers saved</span>
|
||||
</header>
|
||||
<div class="dcx-grid">
|
||||
|
||||
<div class="dcx-badge" data-reveal style="--reveal-delay: 0.45s" aria-hidden="true">
|
||||
@@ -1642,13 +1617,15 @@ const questions = [
|
||||
controls()[0]?.focus();
|
||||
};
|
||||
|
||||
/* Screens 05 through 11 are reachable only from the configure hub, so
|
||||
both their CTA and their Back return there rather than to the DOM
|
||||
neighbor. The hub itself and the review screen keep the ordinary
|
||||
rule: Back on the hub is the font pair, Back on the review's error
|
||||
box is the icons screen. */
|
||||
/* Motion, boundaries, corners, depth, and icons are reachable only
|
||||
from the configure hub, so both their CTA and their Back return
|
||||
there rather than to the DOM neighbor. Type scale (05) and layout
|
||||
(07) sit on the linear path ahead of the hub and follow DOM order.
|
||||
The hub itself and the review screen keep the ordinary rule: Back
|
||||
on the hub is the layout screen (or type scale when layout is
|
||||
skipped), Back on the review's error box is the icons screen. */
|
||||
const HUB_SCREEN = '04b';
|
||||
const HUB_RETURNS = new Set(['05', '06', '07', '08', '09', '10', '11']);
|
||||
const HUB_RETURNS = new Set(['06', '08', '09', '10', '11']);
|
||||
const screenIndex = (id) => screens.findIndex((screen) => screen.dataset.screen === id);
|
||||
|
||||
form.onclick = (e) => {
|
||||
|
||||
@@ -548,8 +548,6 @@ function renderDocument() {
|
||||
const template = document.getElementById(`dcx-detail-${id}`);
|
||||
template.innerHTML = `<article class="dcx-article">${build(snapshot, name)}</article>`;
|
||||
}
|
||||
const masthead = $('[data-dcx-product]');
|
||||
if (masthead && name) masthead.textContent = `Design context — ${name}`;
|
||||
if (name) document.title = `Design context — ${name}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -2224,7 +2224,7 @@ const paintStage = () => {
|
||||
/* ============================================================
|
||||
Screen 04b: the configure hub.
|
||||
|
||||
Seven questions remain after the font pair, and every one of
|
||||
Five questions remain after the layout screen, and every one of
|
||||
them already holds an answer: sync() pre-fills each per-surface
|
||||
field with its surface's default the moment the tile is checked,
|
||||
and the flat radios ship with a default checked. The hub reads
|
||||
@@ -2237,21 +2237,19 @@ const paintStage = () => {
|
||||
const hubScreen = document.querySelector('.picker-screen[data-screen="04b"]');
|
||||
/* Card target screen mapped to the radio group that screen answers. */
|
||||
const HUB_GROUPS = {
|
||||
'05': 'type-scale',
|
||||
'06': 'motion-energy',
|
||||
'07': 'layout-structure',
|
||||
'08': 'boundary-style',
|
||||
'09': 'corner-style',
|
||||
'10': 'depth-style',
|
||||
'11': 'icon-pack',
|
||||
};
|
||||
/* Type scale and icon set render no per-surface fields, so they have
|
||||
no dataset.chosen. A change event on their group is the one signal
|
||||
/* The icon set renders no per-surface fields, so it has no
|
||||
dataset.chosen. A change event on its group is the one signal
|
||||
that a person picked rather than the markup default: programmatic
|
||||
checks never fire it. */
|
||||
const hubEdited = new Set();
|
||||
document.addEventListener('change', ({ target }) => {
|
||||
if (target?.name === 'type-scale' || target?.name === 'icon-pack') hubEdited.add(target.name);
|
||||
if (target?.name === 'icon-pack') hubEdited.add(target.name);
|
||||
});
|
||||
|
||||
const hubSurfaceLabel = (mode) => modeInputs.find((input) => input.value === mode)?.dataset.surfaceLabel ?? mode;
|
||||
@@ -2305,12 +2303,15 @@ function hubRow(surfaceLabel, valueTitle, group, value) {
|
||||
dot.setAttribute('aria-hidden', 'true');
|
||||
val.append(dot, valueTitle);
|
||||
pill.append(label, val);
|
||||
const note = document.createElement('span');
|
||||
note.className = 'picker-hub-note';
|
||||
const why = value ? hubOptionDesc(group, value) : '';
|
||||
note.textContent = why;
|
||||
note.hidden = !why;
|
||||
entry.append(pill, note);
|
||||
entry.append(pill);
|
||||
if (group !== 'icon-pack') {
|
||||
const note = document.createElement('span');
|
||||
note.className = 'picker-hub-note';
|
||||
const why = value ? hubOptionDesc(group, value) : '';
|
||||
note.textContent = why;
|
||||
note.hidden = !why;
|
||||
entry.append(note);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,65 +35,13 @@ body.is-locked { overflow: hidden; }
|
||||
but the document has its own stacked layout below 920px. */
|
||||
body.dcx-open .picker-shell { display: none; }
|
||||
body.dcx-open .picker-width-gate { display: none; }
|
||||
body.dcx-open { background: linear-gradient(180deg, var(--ks-lacquer), var(--ks-lacquer-deep)); }
|
||||
body.dcx-open { overflow: hidden; background: linear-gradient(180deg, var(--ks-lacquer), var(--ks-lacquer-deep)); }
|
||||
|
||||
.dcx-shell {
|
||||
min-height: 100svh;
|
||||
background: linear-gradient(180deg, var(--ks-lacquer), var(--ks-lacquer-deep));
|
||||
}
|
||||
|
||||
/* Masthead — the slot the prototype gave its site header, reduced to what
|
||||
the picker owes: the mark, what this page is, and that the answers are
|
||||
already on disk. */
|
||||
.dcx-masthead {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18px;
|
||||
padding: 18px clamp(14px, 2vw, 26px) 6px;
|
||||
}
|
||||
|
||||
.dcx-masthead-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--ks-kinpaku);
|
||||
}
|
||||
|
||||
.dcx-masthead-brand svg { width: 22px; height: 22px; fill: currentColor; flex-shrink: 0; }
|
||||
|
||||
.dcx-masthead-brand span {
|
||||
font-family: var(--ks-font-display);
|
||||
font-weight: 400;
|
||||
font-size: 1.02rem;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.dcx-masthead-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: 100svh;
|
||||
max-height: 100svh;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-family: var(--ks-mono);
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ks-text-muted);
|
||||
}
|
||||
|
||||
.dcx-masthead-note {
|
||||
font-family: var(--ks-mono);
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ks-text-faint);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 920px) {
|
||||
.dcx-masthead-note { display: none; }
|
||||
background: linear-gradient(180deg, var(--ks-lacquer), var(--ks-lacquer-deep));
|
||||
}
|
||||
|
||||
.dcx-expander code {
|
||||
@@ -111,15 +59,16 @@ body.dcx-open { background: linear-gradient(180deg, var(--ks-lacquer), var(--ks-
|
||||
============================================================ */
|
||||
.dcx-shell {
|
||||
--dcx-gap: clamp(10px, 0.9vw, 14px);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: var(--dcx-gap) clamp(14px, 2vw, 26px) clamp(16px, 2.2vw, 28px);
|
||||
}
|
||||
|
||||
.dcx-grid {
|
||||
position: relative;
|
||||
/* The prototype budgeted 130px for the site header; the picker's masthead
|
||||
is slimmer, so the grid keeps more of the viewport. */
|
||||
height: calc(100svh - 96px);
|
||||
min-height: 560px;
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(18, minmax(0, 1fr));
|
||||
grid-template-rows: repeat(12, minmax(0, 1fr));
|
||||
|
||||
@@ -838,6 +838,28 @@ body.picker-page {
|
||||
background: var(--ks-lacquer-raised);
|
||||
}
|
||||
|
||||
/* Tips on grips and tools sit outside their band's box. Grid paint order
|
||||
otherwise buries them under the next swatch; the deck's stacked cards
|
||||
can overlap the panel edge the same way. */
|
||||
.picker-band-item:has(.picker-band:is(:hover, :focus-within)),
|
||||
.picker-band-item:has(.picker-band[data-dragging]) {
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.picker-band-item:has(.picker-band[data-dragging]) {
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.picker-screen[data-screen="02"] .picker-palette-subgrid {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.picker-reset:is(:hover, :focus-visible) {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.picker-band {
|
||||
--band-color: var(--ks-graphite);
|
||||
--band-ink: var(--ks-champagne);
|
||||
@@ -7556,7 +7578,7 @@ body.picker-page {
|
||||
|
||||
/* ============================================================
|
||||
Screen 04b: the configure hub. Three packed columns of cards;
|
||||
the tall per-surface cards (motion, layout) anchor the outer
|
||||
the tall per-surface cards (motion, depth) anchor the outer
|
||||
tracks. Sharp corners and hairline rules, the same vocabulary
|
||||
as the option rows. Summaries are written by renderHub().
|
||||
============================================================ */
|
||||
|
||||
Reference in New Issue
Block a user