This commit is contained in:
Abdul Wahab
2026-09-01 10:02:40 +05:00
parent 60130bcea9
commit 55617ac5d8
3 changed files with 508 additions and 22 deletions
+103 -18
View File
@@ -235,7 +235,7 @@ function paintCommitted(node) {
/* Clone one questionnaire drawing into a dcx frame. Inline styles travel
with the clone; ids do not (they would collide with the originals). */
function proofHtml(source, { strategy = '', kind = 'board' } = {}) {
function proofHtml(source, { strategy = '', kind = 'board', marks = null } = {}) {
if (!source) return '';
const clone = source.cloneNode(true);
clone.hidden = false;
@@ -249,6 +249,15 @@ function proofHtml(source, { strategy = '', kind = 'board' } = {}) {
wrap.className = `dcx-proof dcx-proof--${kind}`;
wrap.setAttribute('aria-hidden', 'true');
if (strategy) wrap.dataset.dcxStrategy = strategy;
/* Committed structural answers, restated on the frame. On the screens they
reach a carried artboard through checked inputs inside #picker-form,
which a clone in the document is outside of, so design-context.css
mirrors those bodies against these attributes instead. */
if (marks) {
for (const [key, value] of Object.entries(marks)) {
if (value) wrap.setAttribute(`data-dcx-${key}`, value);
}
}
paintCommitted(wrap);
wrap.appendChild(clone);
return wrap.outerHTML;
@@ -261,6 +270,22 @@ const surfaceBoard = (mode) => $(`[data-surface-stage] [data-surface="${mode}"]`
const surfaceTilePreview = (mode) => $(`input[name="surface-modes"][value="${mode}"]`)
?.closest('.picker-mode-tile')?.querySelector('.picker-preview');
/* The boundaries screen keeps one carried ps artboard per surface, and by
that screen the drawing is the page as chosen so far. It is the clone
source for any proof that wants the whole material story on one page. */
const carriedBoard = (mode) => $(`[data-question="boundaries"] .picker-artboard[data-surface="${mode}"]`);
/* One surface's committed structural answers, as the data-dcx-* marks the
document stylesheet keys its mirrored bodies on. Layout is one answer for
the whole run, so every surface's frame carries the same value. */
const materialMarks = (s, mode) => ({
surface: mode,
boundary: s.boundaries.find((entry) => entry.mode === mode)?.value || '',
corner: s.corners.find((entry) => entry.mode === mode)?.value || '',
depth: s.depth.find((entry) => entry.mode === mode)?.value || '',
layout: s.layout.value || '',
});
/* One line per surface for the per-surface questions, marking whether the
user configured the surface or it kept the default for its kind. */
const surfaceDefs = (entries) => defs(entries.map((entry) => ({
@@ -510,15 +535,27 @@ function buildTypography(s, name) {
function buildIconography(s, name) {
const parts = [heading(6, 'Iconography', 'Icon library, license, where it lives.', name)];
if (s.icons.pack) {
const sheet = proofHtml($('[data-icon-sheet]'), { kind: 'icons' });
/* The glyphs are fetched when screen 11 first opens, so a fast run can
reach the document before any landed, and a failed fetch leaves only
an error line. A sheet with no icon cells proves nothing about the
hand, so it is dropped rather than framed. */
const sheetSource = $('[data-icon-sheet]');
const sheet = sheetSource?.querySelector('.picker-icon-cell') ? proofHtml(sheetSource, { kind: 'icons' }) : '';
if (sheet) {
parts.push(block('The hand', sheet
+ note(`${escapeHtml(s.icons.pack)}’s canonical set, as the icons screen previewed it. One pack, one hand: no mixed sets.`)));
}
/* The chosen radio's own row copy: the character note and the grid,
stroke, and license summary the screen showed beside the name. Read
off the DOM rather than kept twice, the optionCopy convention. */
const packLabel = form.querySelector('input[name="icon-pack"]:checked')?.closest('label');
const packNote = packLabel?.querySelector('.picker-strategy-desc')?.textContent.trim() || '';
const packMeta = packLabel?.querySelector('.picker-icon-meta')?.textContent.trim() || '';
parts.push(block('Library', defs([
{ dt: 'Pack', dd: `<strong>${escapeHtml(s.icons.pack)}</strong>` },
s.icons.license && { dt: 'License', dd: escapeHtml(s.icons.license) },
s.icons.url && { dt: 'Home', dd: `<a href="${escapeHtml(s.icons.url)}" target="_blank" rel="noopener">${escapeHtml(s.icons.url)}</a>` },
{ dt: 'Pack', dd: `<strong>${escapeHtml(s.icons.pack)}</strong>${packMeta ? ` &middot; ${escapeHtml(packMeta)}` : ''}` },
packNote ? { dt: 'Why this hand', dd: escapeHtml(packNote) } : null,
s.icons.license ? { dt: 'License', dd: escapeHtml(s.icons.license) } : null,
s.icons.url ? { dt: 'Home', dd: `<a href="${escapeHtml(s.icons.url)}" target="_blank" rel="noopener">${escapeHtml(s.icons.url)}</a>` } : null,
].filter(Boolean)) + note('Chosen on the icons screen. The pack names the hand; stroke weight and metaphor rules resolve during implementation.')));
} else {
parts.push(block('Library', empty('No pack selected', 'The icons screen was not completed on this run.')));
@@ -538,12 +575,35 @@ const pickGrid = (entries) => `<div class="dcx-picks" data-count="${entries.leng
function buildMaterial(s, name) {
const interview = s.context?.interview || {};
const parts = [heading(7, 'Material', 'Motion, layout structure, boundaries, corners, depth.', name)];
/* Every structural answer on one drawing per surface: the boundaries
screen's carried artboard, cloned with the surface's committed strategy
and material answers restated on its frame. A surface with no board in
the DOM drops its card rather than framing nothing. */
const proofCards = s.surfaces.map((surface) => {
const board = carriedBoard(surface.mode);
if (!board) return '';
return `
<article class="dcx-surface-card">
${proofHtml(board, {
strategy: s.strategy.find((entry) => entry.mode === surface.mode)?.value || '',
kind: 'board',
marks: materialMarks(s, surface.mode),
})}
<div class="dcx-surface-copy">
<h3 class="dcx-surface-name">${escapeHtml(surface.label)}</h3>
</div>
</article>`;
}).filter(Boolean);
if (proofCards.length) {
parts.push(block('The page, as chosen', `<div class="dcx-surfaces" data-count="${proofCards.length}">${proofCards.join('')}</div>`
+ note('Each surface&rsquo;s page anatomy carrying every structural answer below at once, the way the question screens accumulated them: color strategy, layout, boundaries, corners, depth.')));
}
/* Movement is only asked of the two surfaces that make a claim on attention,
so this list is one or two entries long and empty on a run of neither. An
empty one says the question was never put, which is a different thing from
a quiet answer and is worth saying out loud. */
if (s.motion.length) {
parts.push(block('Motion per surface', surfaceDefs(s.motion)
parts.push(block('Motion per surface', pickGrid(s.motion)
+ note(interview.motionEnergy
? `The seed interview asked for <strong>${escapeHtml(interview.motionEnergy)}</strong>; the motion screen answered it per surface above.`
: 'Asked of the landing page and the portfolio only. A tool and a document are moved through rather than watched, so their movement follows the interface rather than a house style.')));
@@ -571,22 +631,47 @@ function buildMaterial(s, name) {
function buildInterface(s, name) {
const parts = [heading(8, 'Interface', 'Per-surface decisions at a glance, component status.', name)];
const ASPECTS = [['Color strategy', 'strategy'], ['Boundaries', 'boundaries'], ['Corners', 'corners'], ['Depth', 'depth']];
parts.push(block('Decisions per surface', `<div class="dcx-surfaces" data-count="${s.surfaces.length}">${s.surfaces.map((surface) => `
parts.push(block('Decisions per surface', `<div class="dcx-surfaces" data-count="${s.surfaces.length}">${s.surfaces.map((surface) => {
const strategyValue = s.strategy.find((entry) => entry.mode === surface.mode)?.value || '';
const board = carriedBoard(surface.mode);
/* The matrix quotes every per-surface answer. A question this surface
was never asked reads Not asked rather than borrowing another
surface's answer; layout is one answer for the run and is quoted on
every card, the rule the Material page states. */
const rows = [
['Color strategy', s.strategy.find((entry) => entry.mode === surface.mode)],
['Boundaries', s.boundaries.find((entry) => entry.mode === surface.mode)],
['Corners', s.corners.find((entry) => entry.mode === surface.mode)],
['Depth', s.depth.find((entry) => entry.mode === surface.mode)],
['Motion', s.motion.find((entry) => entry.mode === surface.mode)],
['Layout', s.layout.value ? s.layout : undefined],
];
return `
<article class="dcx-surface-card">
${proofHtml(surfaceBoard(surface.mode) || surfaceTilePreview(surface.mode), {
strategy: s.strategy.find((entry) => entry.mode === surface.mode)?.value || '',
kind: 'board',
})}
${board
? proofHtml(board, { strategy: strategyValue, kind: 'board', marks: materialMarks(s, surface.mode) })
: proofHtml(surfaceBoard(surface.mode) || surfaceTilePreview(surface.mode), { strategy: strategyValue, kind: 'board' })}
<div class="dcx-surface-copy">
<h3 class="dcx-surface-name">${escapeHtml(surface.label)}</h3>
<dl class="dcx-matrix">${ASPECTS.map(([label, key]) => {
const entry = s[key].find((item) => item.mode === surface.mode);
return `<div class="dcx-matrix-row"><dt>${escapeHtml(label)}</dt><dd>${escapeHtml(entry?.title || '—')}${entry && !entry.chosen ? ' <span class="dcx-default-mark">default</span>' : ''}</dd></div>`;
}).join('')}</dl>
<dl class="dcx-matrix">${rows.map(([label, entry]) => `
<div class="dcx-matrix-row"><dt>${escapeHtml(label)}</dt><dd>${entry ? escapeHtml(entry.title) : 'Not asked'}${entry && !entry.chosen ? ' <span class="dcx-default-mark">default</span>' : ''}</dd></div>`).join('')}</dl>
</div>
</article>`).join('')}</div>`
+ note('Each surface&rsquo;s artboard in its own color strategy, with the four per-surface answers beneath it.')));
</article>`;
}).join('')}</div>`
+ note('Each surface&rsquo;s anatomy carrying its committed answers, with every per-surface decision beneath it.')));
/* The run's own tokens in one place: what the seed DESIGN.md frontmatter
will carry. Every row omits when its screen was not completed. */
const kit = [
s.fonts.heading ? { dt: 'Faces', dd: `<strong>${escapeHtml(s.fonts.heading)}</strong> for headings, <strong>${escapeHtml(s.fonts.body)}</strong> for body` } : null,
s.scale.ratio ? { dt: 'Type scale', dd: `<strong>${escapeHtml(s.scale.name)}</strong> &middot; ratio <code>${s.scale.ratio.toFixed(3)}</code> on a 16px base` } : null,
s.icons.pack ? { dt: 'Icons', dd: `<strong>${escapeHtml(s.icons.pack)}</strong>${s.icons.license ? ` &middot; ${escapeHtml(s.icons.license)}` : ''}` } : null,
s.palette.length ? { dt: 'Palette', dd: s.palette.map((entry) => `<code>${entry.hex}</code>`).join(' &middot; ') } : null,
s.layout.value ? { dt: 'Layout', dd: `<strong>${escapeHtml(s.layout.title)}</strong>, one answer for the run` } : null,
].filter(Boolean);
if (kit.length) {
parts.push(block('The kit', defs(kit)
+ note('The tokens the seed DESIGN.md will carry in its frontmatter, gathered from their own pages in this document.')));
}
parts.push(block('Components', empty(
'No component library seeded yet',
'Components are documented on the first scan pass, once there is code to capture actual tokens and states from. Re-run <code>/impeccable document</code> then.',
+389
View File
@@ -1189,6 +1189,395 @@ body.dcx-open { overflow: hidden; background: linear-gradient(180deg, var(--ks-l
--pv-tertiary: var(--pkc-tertiary);
--pv-t-on-n: var(--pkc-t-on-p);
}
/* ============================================================
Material proofs: the structural screens' own artboards, cloned.
A .dcx-proof--board can also frame a ps artboard clone (the anatomy
screens 07 to 10 draw on), not just a tile drawing. On screen those
boards take every committed answer through checked inputs inside
#picker-form, which a clone in the document is outside of, so the frame
restates each answer as a data-dcx-* attribute and the bodies below are
verbatim copies of the committed bodies the screens set. Change a body
here and in its named source together. The palette rides two ways: the
screens paint all thirteen --pv-* slots inline on every artboard they
showed (inline styles travel with a clone), and for a board whose screen
the run never opened, the frame's --pkc-* paint reaches the clone
through the same six-slot map the tile clones above use, with the
artboard's own class defaults covering the contrast slots. */
.dcx-proof--board > .picker-artboard {
--pv-primary: var(--pkc-primary, var(--ks-champagne));
--pv-secondary: var(--pkc-secondary, var(--ks-patina));
--pv-tertiary: var(--pkc-tertiary, var(--ks-kinpaku));
--pv-neutral: var(--pkc-neutral, var(--ks-lacquer-raised));
--pv-n-ink: var(--pkc-n-ink, var(--ks-champagne));
--pv-p-ink: var(--pkc-p-ink, var(--ks-champagne));
}
/* Two rules the clone loses with its data-surface attribute (proofHtml
strips it): the landing board's right-gutter chrome, and the handset
print's freeform cut, which rides --pvs-drift and stays a rectangle
under the other layout answers. The frame's data-dcx-surface carries
the surface instead. Sources: picker/styles/screens/layout.css, the
[data-carry][data-surface="persuade"] rules. */
.dcx-proof--board[data-dcx-surface="persuade"] > .picker-artboard :is(.ps-nav, .ps-editorial, .ps-footer) {
padding-right: var(--pvs-gutter-end);
}
.dcx-proof--board[data-dcx-surface="persuade"] > .picker-artboard .ps-phone-body > .ps-image {
clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--pvs-drift, 0) * 16%), 0 100%);
}
/* The strategy, restated for artboard clones: the [data-artboard] bodies
from picker.css. Restrained is the artboard's own defaults there and
stays bodiless here, exactly as the tile remaps above leave full
palette alone. */
.dcx-proof--board[data-dcx-strategy="committed"] > .picker-artboard {
--pvs-headline: color-mix(in oklab, var(--pv-primary) 80%, var(--pv-strong));
--pvs-headline-text: var(--pv-p-on-n);
--pvs-eyebrow: var(--pv-primary);
--pvs-ghost: color-mix(in oklab, var(--pv-primary) 14%, var(--pv-neutral));
--pvs-ghost-edge: var(--pv-primary);
--pvs-image: var(--pv-primary);
--pvs-image-a: var(--pv-primary);
--pvs-image-b: color-mix(in oklab, var(--pv-primary) 72%, var(--pv-neutral));
--pvs-image-edge: var(--pv-primary);
--pvs-accent-a: var(--pv-primary);
--pvs-accent-b: color-mix(in oklab, var(--pv-primary) 70%, var(--pv-neutral));
--pvs-accent-c: var(--pv-primary);
--pvs-accent-d: color-mix(in oklab, var(--pv-primary) 18%, var(--pv-neutral));
}
.dcx-proof--board[data-dcx-strategy="full-palette"] > .picker-artboard {
--pvs-headline: color-mix(in oklab, var(--pv-primary) 80%, var(--pv-strong));
--pvs-headline-text: var(--pv-p-on-n);
--pvs-accent-text: var(--pv-t-on-n);
--pvs-eyebrow: var(--pv-tertiary);
--pvs-ghost: color-mix(in oklab, var(--pv-secondary) 18%, var(--pv-neutral));
--pvs-ghost-edge: var(--pv-secondary);
--pvs-image: var(--pv-primary);
--pvs-image-a: var(--pv-primary);
--pvs-image-b: color-mix(in oklab, var(--pv-secondary) 32%, var(--pv-primary));
--pvs-image-edge: var(--pv-primary);
--pvs-signal: var(--pv-tertiary);
--pvs-signal-ink: var(--pv-t-ink);
--pvs-signal-text: var(--pv-t-on-t);
--pvs-accent-a: var(--pv-secondary);
--pvs-accent-b: color-mix(in oklab, var(--pv-secondary) 42%, var(--pv-neutral));
--pvs-accent-c: var(--pv-primary);
--pvs-accent-d: var(--pv-tertiary);
}
.dcx-proof--board[data-dcx-strategy="drenched"] > .picker-artboard {
--pvs-ground: var(--pv-primary);
--pvs-ink: var(--pv-p-ink);
--pvs-surface: color-mix(in oklab, var(--pv-p-ink) 10%, var(--pv-primary));
--pvs-headline: var(--pv-p-ink);
--pvs-eyebrow: color-mix(in oklab, var(--pv-p-ink) 70%, var(--pv-primary));
--pvs-copy: color-mix(in oklab, var(--pv-p-ink) 55%, var(--pv-primary));
--pvs-title: var(--pv-p-ink);
--pvs-cta: var(--pv-p-ink);
--pvs-cta-ink: var(--pv-primary);
--pvs-cta-text: var(--pv-p-on-i);
--pvs-mark-text: var(--pv-p-ink);
--pvs-accent-text: var(--pv-t-on-p);
--pvs-copy-mix: 14%;
--pvs-bars-mix: 16%;
--pvs-ghost: color-mix(in oklab, var(--pv-p-ink) 22%, var(--pv-primary));
--pvs-ghost-edge: color-mix(in oklab, var(--pv-p-ink) 45%, var(--pv-primary));
--pvs-image: color-mix(in oklab, var(--pv-p-ink) 20%, var(--pv-primary));
--pvs-image-a: color-mix(in oklab, var(--pv-p-ink) 16%, var(--pv-primary));
--pvs-image-b: color-mix(in oklab, var(--pv-p-ink) 28%, var(--pv-primary));
--pvs-image-edge: color-mix(in oklab, var(--pv-p-ink) 40%, var(--pv-primary));
--pvs-signal: var(--pv-tertiary);
--pvs-signal-ink: var(--pv-t-ink);
--pvs-signal-text: var(--pv-t-on-t);
--pvs-bars: color-mix(in oklab, var(--pv-p-ink) 45%, var(--pv-primary));
--pvs-rule: color-mix(in oklab, var(--pv-p-ink) 28%, var(--pv-primary));
--pvs-accent-a: var(--pv-secondary);
--pvs-accent-b: var(--pv-tertiary);
--pvs-accent-c: color-mix(in oklab, var(--pv-p-ink) 30%, var(--pv-primary));
--pvs-accent-d: color-mix(in oklab, var(--pv-p-ink) 14%, var(--pv-primary));
}
/* Boundaries: the four committed bodies from styles/screens/boundaries.css. */
.dcx-proof--board[data-dcx-boundary="open-space"] > .picker-artboard {
--pvs-divider-w: 0px;
--pvs-band: transparent;
--pvs-band-alt: transparent;
--pvs-band-top: transparent;
--pvs-panel: transparent;
--pvs-panel-edge-w: 0px;
--pvs-panel-pad: 0px;
--pvs-proof-inset: 0px;
}
.dcx-proof--board[data-dcx-boundary="thin-dividers"] > .picker-artboard {
--pvs-divider-w: 1px;
--pvs-divider-c: color-mix(in oklab, var(--pvs-ink) 24%, var(--pvs-ground));
--pvs-band: transparent;
--pvs-band-alt: transparent;
--pvs-band-top: transparent;
--pvs-panel: transparent;
--pvs-panel-edge-w: 0px;
--pvs-panel-pad: 0px;
--pvs-proof-inset: 0px;
}
.dcx-proof--board[data-dcx-boundary="surface-changes"] > .picker-artboard {
--pvs-divider-w: 0px;
--pvs-band: color-mix(in oklab, var(--pvs-ink) 7%, var(--pvs-ground));
--pvs-band-alt: color-mix(in oklab, var(--pvs-ink) 13%, var(--pvs-ground));
--pvs-band-top: color-mix(in oklab, var(--pvs-ink) 7%, var(--pvs-ground));
--pvs-panel: transparent;
--pvs-panel-edge-w: 0px;
--pvs-panel-pad: 0px;
--pvs-proof-inset: 0px;
}
.dcx-proof--board[data-dcx-boundary="cards-and-panels"] > .picker-artboard {
--pvs-divider-w: 0px;
--pvs-band: transparent;
--pvs-band-alt: color-mix(in oklab, var(--pvs-ink) 5%, var(--pvs-ground));
--pvs-band-top: transparent;
--pvs-panel: color-mix(in oklab, var(--pvs-ink) 5%, var(--pvs-ground));
--pvs-panel-edge: color-mix(in oklab, var(--pvs-ink) 20%, var(--pvs-ground));
--pvs-panel-edge-w: 1px;
--pvs-panel-pad: 5%;
--pvs-proof-inset: var(--pvs-gutter);
}
/* The open rail plate joins the card answer, as on the screen. */
.dcx-proof--board[data-dcx-boundary="cards-and-panels"] > .picker-artboard .ps-ops-item {
background-color: var(--pvs-panel);
}
/* Corners: the four committed bodies from styles/screens/corners.css. */
.dcx-proof--board[data-dcx-corner="sharp"] > .picker-artboard {
--pvs-radius-frame: 0px;
--pvs-radius-frame-phone: 0px;
--pvs-radius-surface: 0px;
--pvs-radius-control: 0px;
--pvs-radius-bar: 0px;
}
.dcx-proof--board[data-dcx-corner="slightly-soft"] > .picker-artboard {
--pvs-radius-frame: 4px;
--pvs-radius-frame-phone: 5px;
--pvs-radius-surface: 3px;
--pvs-radius-control: 3px;
--pvs-radius-bar: 2px;
}
.dcx-proof--board[data-dcx-corner="friendly"] > .picker-artboard {
--pvs-radius-frame: 7px;
--pvs-radius-frame-phone: 11px;
--pvs-radius-surface: 8px;
--pvs-radius-control: 8px;
--pvs-radius-bar: 3px;
}
.dcx-proof--board[data-dcx-corner="pill"] > .picker-artboard {
--pvs-radius-frame: 9px;
--pvs-radius-frame-phone: 15px;
--pvs-radius-surface: 12px;
--pvs-radius-control: 999px;
--pvs-radius-bar: 3px;
}
/* Depth: the three committed bodies from styles/screens/depth.css. */
.dcx-proof--board[data-dcx-depth="flat"] > .picker-artboard {
--pvs-shadow-chrome: none;
--pvs-shadow-card: none;
--pvs-shadow-control: none;
--pvs-shadow-surface: none;
}
.dcx-proof--board[data-dcx-depth="soft-lift"] > .picker-artboard {
--pvs-shadow-chrome: 0 1px 2px rgb(0 0 0 / 0.1);
--pvs-shadow-card:
0 1px 1px rgb(0 0 0 / 0.15),
0 3px 7px rgb(0 0 0 / 0.14);
--pvs-shadow-control: 0 1px 2px rgb(0 0 0 / 0.24);
--pvs-shadow-surface: 0 2px 5px rgb(0 0 0 / 0.14);
}
.dcx-proof--board[data-dcx-depth="floating"] > .picker-artboard {
--pvs-shadow-chrome: 0 2px 6px rgb(0 0 0 / 0.16);
--pvs-shadow-card:
0 2px 3px rgb(0 0 0 / 0.2),
0 9px 18px rgb(0 0 0 / 0.24);
--pvs-shadow-control: 0 3px 6px rgb(0 0 0 / 0.32);
--pvs-shadow-surface: 0 6px 14px rgb(0 0 0 / 0.22);
}
/* Where a cast shadow is allowed to land, keyed to the boundary answer
exactly as depth.css keys it to the checked boundary input. */
.dcx-proof--board[data-dcx-boundary="cards-and-panels"] > .picker-artboard :is(.ps-gallery-item, .ps-desktop > .ps-proof),
.dcx-proof--board[data-dcx-boundary="surface-changes"] > .picker-artboard .ps-desktop > .ps-proof {
box-shadow: var(--pvs-shadow-card);
}
.dcx-proof--board:not([data-dcx-boundary="cards-and-panels"]) > .picker-artboard .ps-gallery-item {
box-shadow: none;
}
.dcx-proof--board:not([data-dcx-boundary="cards-and-panels"]) > .picker-artboard .ps-gallery-item > i {
box-shadow: var(--pvs-shadow-card);
}
.dcx-proof--board:not([data-dcx-boundary="surface-changes"]) > .picker-artboard :is(.ps-nav, .ps-phone-top) {
box-shadow: none;
}
.dcx-proof--board:not([data-dcx-boundary="surface-changes"]) > .picker-artboard :is(.ps-ops-rail, .ps-docs-rail) {
box-shadow: none;
}
.dcx-proof--board:not([data-dcx-boundary="surface-changes"]):not([data-dcx-boundary="cards-and-panels"]) > .picker-artboard .ps-ops-panel {
box-shadow: none;
}
.dcx-proof--board:not([data-dcx-boundary="cards-and-panels"]) > .picker-artboard :is(.ps-ops-chart, .ps-ops-table) {
box-shadow: none;
}
.dcx-proof--board:not([data-dcx-boundary="cards-and-panels"]) > .picker-artboard .ps-ops-plot > i {
box-shadow: var(--pvs-shadow-card);
}
.dcx-proof--board:not([data-dcx-boundary="surface-changes"]) > .picker-artboard .ps-docs-note {
box-shadow: none;
}
.dcx-proof--board[data-dcx-boundary="surface-changes"] > .picker-artboard .ps-index-row--flip {
box-shadow: var(--pvs-shadow-card);
}
/* Layout: the committed bodies from styles/screens/layout.css, the landing
measure and the region tracks folded into one body per answer (their
sources are two rules on the same committed selector). */
.dcx-proof--board[data-dcx-layout="simple-grid"] > .picker-artboard {
--pvs-gutter: 6%;
--pvs-gutter-end: 6%;
--pvs-hero-cols: var(--pvs-w6) minmax(0, 1fr);
--pvs-hero-gap: var(--pvs-gut);
--pvs-editorial-cols: var(--pvs-w4) minmax(0, 1fr);
--pvs-editorial-gap: var(--pvs-gut);
--pvs-gallery-cols: repeat(4, minmax(0, 1fr));
--pvs-gallery-gap: calc(var(--pvs-gut) * 100 / 66.1333);
--pvs-section-align: start;
--pvs-rows: 9.4% 45.5% 9% 27.8% 8.3%;
--pvs-phone-gutter: 7%;
--pvs-phone-gallery-cols: 1fr 1fr;
--pvs-shell-cols:
calc(var(--pvs-w2) + var(--pvs-gut) / 2)
calc(var(--pvs-w7) + var(--pvs-gut))
minmax(0, 1fr);
--pvs-measure-cols:
calc(var(--pvs-w3) + var(--pvs-gut) / 2)
minmax(0, 1fr);
--pvs-metric-cols: repeat(3, minmax(0, 1fr));
--pvs-entry-cols: var(--pvs-w6) minmax(0, 1fr);
--pvs-entry-flip-cols: var(--pvs-w6) minmax(0, 1fr);
}
.dcx-proof--board[data-dcx-layout="simple-grid"] > .picker-artboard .ps-index-row--flip > .ps-image {
grid-area: 1 / 1;
}
.dcx-proof--board[data-dcx-layout="simple-grid"] > .picker-artboard .ps-index-row--flip > .ps-index-cap {
grid-area: 1 / 2;
}
.dcx-proof--board[data-dcx-layout="balanced"] > .picker-artboard {
--pvs-gutter: 6%;
--pvs-gutter-end: 6%;
--pvs-hero-cols: var(--pvs-w5) minmax(0, 1fr);
--pvs-hero-gap: var(--pvs-gut);
--pvs-editorial-cols: var(--pvs-w3) minmax(0, 1fr);
--pvs-editorial-gap: var(--pvs-gut);
--pvs-gallery-cols: 23.8fr 15.3333fr 15.3333fr 15.3333fr;
--pvs-gallery-gap: calc(var(--pvs-gut) * 100 / 74.6);
--pvs-section-align: center;
--pvs-rows: 9.4% 50.6% 9% 22.7% 8.3%;
--pvs-phone-gutter: 6%;
--pvs-phone-gallery-cols: 1.35fr 0.85fr;
--pvs-shell-cols:
calc(var(--pvs-w2) + var(--pvs-gut) / 2)
calc(var(--pvs-w8) + var(--pvs-gut))
minmax(0, 1fr);
--pvs-measure-cols:
calc(var(--pvs-w3) + var(--pvs-gut) / 2)
calc(var(--pvs-w6) + var(--pvs-gut))
minmax(0, 1fr);
--pvs-metric-cols: 1.45fr 1fr 1fr;
--pvs-entry-cols: var(--pvs-w7) minmax(0, 1fr);
--pvs-entry-flip-cols: minmax(0, 1fr) var(--pvs-w7);
}
.dcx-proof--board[data-dcx-layout="freeform"] > .picker-artboard {
--pvs-gutter: 6%;
--pvs-gutter-end: 6%;
--pvs-hero-cols: var(--pvs-w5) minmax(0, 1fr);
--pvs-hero-gap: var(--pvs-gut);
--pvs-editorial-cols: var(--pvs-w3) minmax(0, 1fr);
--pvs-editorial-gap: var(--pvs-gut);
--pvs-gallery-cols: repeat(4, minmax(0, 1fr));
--pvs-gallery-gap: calc(var(--pvs-gut) * 100 / 74.6);
--pvs-section-align: start;
--pvs-rows: 9.4% 48% 8.4% 26.2% 8%;
--pvs-phone-gutter: 6%;
--pvs-phone-gallery-cols: 1.5fr 0.9fr;
--pvs-drift: 1;
--pvs-entry-cols: var(--pvs-w7) minmax(0, 1fr);
--pvs-entry-flip-cols: minmax(0, 1fr) var(--pvs-w7);
}
/* Freeform's one move on the landing hero: the print cut loose of the
grid, with the copy holding the page's left measure. */
.dcx-proof--board[data-dcx-layout="freeform"] > .picker-artboard .ps-desktop .ps-hero {
position: relative;
display: block;
padding: 0;
}
.dcx-proof--board[data-dcx-layout="freeform"] > .picker-artboard .ps-desktop .ps-hero > .ps-image {
position: absolute;
inset: 0;
height: 100%;
clip-path: polygon(40% 0, 100% 0, 100% 78%, 66% 84%);
}
.dcx-proof--board[data-dcx-layout="freeform"] > .picker-artboard .ps-desktop .ps-hero > .ps-hero-copy {
position: relative;
z-index: 1;
box-sizing: border-box;
width: 44%;
height: 100%;
align-content: center;
padding-left: var(--pvs-gutter, 6%);
}
/* Freeform on the index: the prints laid down askew with the caption
stepping onto the corner, the committed rules that are surface-scoped
on screen and read the frame's surface mark here. */
.dcx-proof--board[data-dcx-layout="freeform"][data-dcx-surface="experience"] > .picker-artboard .ps-index-row > .ps-image {
rotate: -1.7deg;
}
.dcx-proof--board[data-dcx-layout="freeform"][data-dcx-surface="experience"] > .picker-artboard .ps-index-row--flip > .ps-image {
rotate: 1.4deg;
}
.dcx-proof--board[data-dcx-layout="freeform"][data-dcx-surface="experience"] > .picker-artboard .ps-index-cap {
position: relative;
z-index: 1;
translate: -9% 0;
}
.dcx-proof--board[data-dcx-layout="freeform"][data-dcx-surface="experience"] > .picker-artboard .ps-index-row--flip > .ps-index-cap {
translate: 9% 0;
}
/* The scale sheet and specimen size themselves against their rail on screen
05; in the document they stand at natural height and full width. */
+16 -4
View File
@@ -1429,6 +1429,17 @@ body.picker-page {
height: calc(5.58708 * var(--pv-x));
background: var(--pv-primary);
border-radius: 2px;
display: grid;
place-items: center;
color: var(--pv-neutral);
}
.pv-pill::after {
content: "";
width: calc(8.5 * var(--pv-x));
height: calc(1.3 * var(--pv-x));
background: currentColor;
border-radius: 2px;
}
/* The hero is a size container so the page it draws scales with the card rather
@@ -1951,7 +1962,7 @@ body.picker-page {
flex: none;
width: calc(6.92 * var(--pv-x));
height: var(--h);
background: var(--po-wash);
background: var(--po-ink-soft);
}
.po-chart .po-peak {
@@ -2051,10 +2062,10 @@ body.picker-page {
/* A square stood on its corner, two borders lit. Half of it falls outside the
drawn chevron, so the margins are placing the tip rather than the box. */
.po-chev {
align-self: start;
align-self: center;
width: calc(2 * var(--pv-x));
aspect-ratio: 1;
margin: calc(1.86 * var(--pv-x)) calc(3.14 * var(--pv-x)) 0 auto;
margin: 0 calc(3.14 * var(--pv-x)) 0 auto;
border-right: 1px solid var(--po-ink);
border-bottom: 1px solid var(--po-ink);
transform: rotate(45deg);
@@ -2154,8 +2165,9 @@ body.picker-page {
}
.po-phone-body .po-chev {
align-self: center;
width: calc(2.77 * var(--pv-x));
margin: calc(2.65 * var(--pv-x)) calc(5.03 * var(--pv-x)) 0 auto;
margin: 0 calc(5.03 * var(--pv-x)) 0 auto;
}
.po-prow {