mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-20 01:56:37 +03:00
Build out the layout screen's three compositions
Each option now draws its own page rather than a shared field with a different column count. Simple grid holds strict paired rows at equal image measures, balanced alternates wide images against captions, and freeform crops a lead, adds an upper portrait, and spills the card row into a set of prints with their own captions and marks. All three carry handset sequences at the reference measures. Behind them: one shared alignment-grid component mounted on every body that asks for it, code-native nav primitives placed at the reference measures rather than left to their grids, a project image-tone contract the boards key their fills on, and footer link groups. Prepared with AI assistance (Cursor). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -40,12 +40,15 @@ interface Props {
|
||||
*/
|
||||
carry?: boolean;
|
||||
/*
|
||||
The layout screen's index board carries parts no other board draws: a
|
||||
pagination rail on the handset, and the project rail and support row that
|
||||
only the freeform answer places (layout-portfolio.css parks them until it
|
||||
does). Mounted only where asked, because the motion screen reads the same
|
||||
index body through :nth-of-type and an extra sibling would shift its
|
||||
scenes.
|
||||
The layout screen's boards carry parts no other board draws: the shared
|
||||
alignment-grid component on every desktop and handset body, and on the
|
||||
index a pagination rail for the handset plus the project rail and support
|
||||
row that only the freeform answer places (layout-portfolio.css parks them
|
||||
until it does). The index projects also take the data-project-index and
|
||||
data-project-tone hooks that screen's sheet keys plate placement and
|
||||
image treatment on. Mounted only where asked, because the motion screen
|
||||
reads the same index body through :nth-of-type and an extra sibling would
|
||||
shift its scenes.
|
||||
*/
|
||||
portfolioExtras?: boolean;
|
||||
}
|
||||
@@ -81,6 +84,7 @@ const hook = type ? '' : undefined;
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="ps-desktop">
|
||||
{portfolioExtras && <div class="ps-layout-grid" aria-hidden="true"></div>}
|
||||
<div class="ps-nav">
|
||||
<div class="ps-nav-lede">
|
||||
{!type && <i class="ps-menu"></i>}
|
||||
@@ -212,7 +216,11 @@ const hook = type ? '' : undefined;
|
||||
<i class="ps-index-head"></i>
|
||||
{[0, 1].map((n) => (
|
||||
<div class:list={['ps-index-row', n === 1 && 'ps-index-row--flip']}>
|
||||
<div class="ps-image"></div>
|
||||
<div
|
||||
class="ps-image"
|
||||
data-project-index={portfolioExtras ? String(n + 1) : undefined}
|
||||
data-project-tone={portfolioExtras ? (n === 0 ? 'green' : 'light') : undefined}
|
||||
></div>
|
||||
<div class="ps-index-cap">
|
||||
<i class="ps-index-name"></i>
|
||||
<i class="ps-index-tag"></i>
|
||||
@@ -222,7 +230,7 @@ const hook = type ? '' : undefined;
|
||||
))}
|
||||
{portfolioExtras && (
|
||||
<div class="ps-support" aria-hidden="true">
|
||||
<div class="ps-image ps-support-image"></div>
|
||||
<div class="ps-image ps-support-image" data-project-tone="light"></div>
|
||||
<span class="ps-support-meta"><i></i><i></i><i></i></span>
|
||||
</div>
|
||||
)}
|
||||
@@ -433,10 +441,18 @@ const hook = type ? '' : undefined;
|
||||
{portfolioExtras && (
|
||||
<div class="ps-phone-project-rail" aria-hidden="true"><i></i><i></i><i></i></div>
|
||||
)}
|
||||
{[0, 1].map(() => (
|
||||
{portfolioExtras && <div class="ps-layout-grid" aria-hidden="true"></div>}
|
||||
{[0, 1].map((n) => (
|
||||
<Fragment>
|
||||
<div class="ps-image"></div>
|
||||
<div class="ps-index-cap">
|
||||
<div
|
||||
class="ps-image"
|
||||
data-project-index={portfolioExtras ? String(n + 1) : undefined}
|
||||
data-project-tone={portfolioExtras ? (n === 0 ? 'green' : 'light') : undefined}
|
||||
></div>
|
||||
<div
|
||||
class="ps-index-cap"
|
||||
data-project-index={portfolioExtras ? String(n + 1) : undefined}
|
||||
>
|
||||
{type ? (
|
||||
<Fragment>
|
||||
<strong class="ps-index-title" data-type-gallery-title></strong>
|
||||
@@ -456,7 +472,7 @@ const hook = type ? '' : undefined;
|
||||
{portfolioExtras && (
|
||||
<Fragment>
|
||||
<div class="ps-support ps-phone-support" aria-hidden="true">
|
||||
<div class="ps-image ps-support-image"></div>
|
||||
<div class="ps-image ps-support-image" data-project-tone="light"></div>
|
||||
<span class="ps-support-meta"><i></i><i></i><i></i></span>
|
||||
</div>
|
||||
{/* The desktop pagination rail restated at the foot of the stack. */}
|
||||
@@ -474,6 +490,7 @@ const hook = type ? '' : undefined;
|
||||
</div>
|
||||
) : (
|
||||
<div class="ps-phone-body">
|
||||
{portfolioExtras && <div class="ps-layout-grid" aria-hidden="true"></div>}
|
||||
<div class="ps-image"></div>
|
||||
{type ? (
|
||||
<Fragment>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -147,14 +147,23 @@
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.picker-preview-layout .ps-desktop::before {
|
||||
/* The field is one shared component, .ps-layout-grid, mounted by the
|
||||
artboard as the first drawn part of every desktop and handset body on
|
||||
this screen. An element rather than a pseudo so both bodies carry the
|
||||
same instrument by construction, and so the marks sit over the section
|
||||
bands rather than under the page: a line a band can bury is a ruler
|
||||
that only measures the empty rows. */
|
||||
.picker-preview-layout .ps-layout-grid {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.picker-preview-layout .ps-desktop > .ps-layout-grid {
|
||||
--pvs-field-col: 6.8667%;
|
||||
--pvs-field-gut: 1.6%;
|
||||
--pvs-mark: calc(var(--pvs-field-col) + var(--pvs-field-gut) / 2);
|
||||
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
inset: 0 6%;
|
||||
background-image: repeating-linear-gradient(
|
||||
to right,
|
||||
@@ -164,7 +173,6 @@
|
||||
transparent calc(var(--pvs-mark) + 0.5px)
|
||||
calc(var(--pvs-field-col) + var(--pvs-field-gut))
|
||||
);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* The handset has one column, so twelve bands would say nothing there. What
|
||||
@@ -175,16 +183,16 @@
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.picker-preview-layout .ps-phone-body::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: var(--pvs-phone-gutter, 6%);
|
||||
right: var(--pvs-phone-gutter, 6%);
|
||||
.picker-preview-layout .ps-phone-body > .ps-layout-grid {
|
||||
inset: 0 var(--pvs-phone-gutter, 6%);
|
||||
border-inline: 1px solid color-mix(in oklab, var(--pvs-ink) 5%, transparent);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* The magnifier is decoration on a board judging proportion, and it is the
|
||||
one nav part that reads as an icon rather than a mass, so these abstract
|
||||
studies leave it out. */
|
||||
.picker-preview-layout .ps-search {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* ── Simple grid ─────────────────────────────────────────────
|
||||
@@ -365,6 +373,377 @@
|
||||
grid-template-columns: 1.5fr 0.9fr;
|
||||
}
|
||||
|
||||
/* ── Freeform's card row: the gallery spill ──────────────────
|
||||
On the landing page the drift is granted a second block: the card row
|
||||
stops being four equal cells and becomes an index spill. One work leads
|
||||
at double width and double height, two more answer it at their own sizes,
|
||||
and each carries the hero's own image treatment, so the row reads as
|
||||
three prints set down on the table rather than a product grid. The proof
|
||||
band above gives up its four claims for the two entry marks that caption
|
||||
the spill, and the section copy leaves the way it does on Simple grid:
|
||||
the works are the section. This screen's persuade preview only; the
|
||||
committed page keeps the disciplined row, because the spill is this
|
||||
drawing's way of showing the permission, not a structure that travels. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"],
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] {
|
||||
/* The proof band thins to a caption row and the freed height goes to the
|
||||
spill, so the two bands trade rather than the page growing. */
|
||||
--pvs-rows: 9.4% 48% 2.8% 31.8% 8%;
|
||||
}
|
||||
|
||||
/* Two entry marks where the four claims were: one at the page's left
|
||||
measure, one on the line the middle print hangs from. Both dots take the
|
||||
page's own primary, the color the prints are drawn in. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-proof,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-proof {
|
||||
grid-template-columns: 51.2% minmax(0, 1fr);
|
||||
column-gap: 0;
|
||||
padding-block: 0;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-proof-divider, .ps-proof-item:nth-of-type(3), .ps-proof-item:nth-of-type(4)),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-proof-divider, .ps-proof-item:nth-of-type(3), .ps-proof-item:nth-of-type(4)) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-proof-item,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-proof-item {
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-proof-item i,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-proof-item i {
|
||||
background-color: var(--pvs-cta);
|
||||
}
|
||||
|
||||
/* A mark's label is a phrase, not a fill: it stops well short of its
|
||||
column instead of running to the next print's edge. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-proof-item span,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-proof-item span {
|
||||
flex: none;
|
||||
width: 27.6%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-proof-item:nth-of-type(2) span,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-proof-item:nth-of-type(2) span {
|
||||
width: 29%;
|
||||
}
|
||||
|
||||
/* The section copy leaves and the spill takes the whole band, hung from
|
||||
its top so the lead print's extra height reads downward. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-editorial,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-editorial {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 0;
|
||||
padding-block: 1.5% 0;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-editorial-copy,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-editorial-copy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Five columns of the field for the lead, three for each of the others,
|
||||
read off the drawn lines the way the hero's spans are. The fourth card
|
||||
leaves: a spill is an uneven count or it is a grid again. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery {
|
||||
grid-template-columns: 47.2% 24% minmax(0, 1fr);
|
||||
gap: 4%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(4),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(4) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The plates take the hero's own image treatment, corner mark included:
|
||||
the spill is made of the same prints the hero laid down, not the flat
|
||||
category tiles of the disciplined answers. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-gallery-item > i,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-gallery-item > i {
|
||||
position: relative;
|
||||
background-color: var(--pvs-image);
|
||||
background-image: linear-gradient(135deg, var(--pvs-image-a), var(--pvs-image-b));
|
||||
border: 1px solid var(--pvs-image-edge);
|
||||
box-shadow: var(--pvs-shadow-surface);
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-gallery-item > i::after,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-gallery-item > i::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
right: 5%;
|
||||
width: clamp(6px, 1.1vw, 10px);
|
||||
aspect-ratio: 1;
|
||||
background-color: var(--pvs-accent-d);
|
||||
border-radius: var(--pvs-radius-dot);
|
||||
}
|
||||
|
||||
/* The two supporting prints stop at half the band and hold their captions
|
||||
directly under themselves; the lead keeps the flexible row and so takes
|
||||
the height the captions leave. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-gallery-item:nth-child(2), .ps-gallery-item:nth-child(3)),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-gallery-item:nth-child(2), .ps-gallery-item:nth-child(3)) {
|
||||
grid-template-rows: 46% auto;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
/* The third print is the quiet one, a wash of the ghost tint rather than
|
||||
another full print, so the spill has a near-far rhythm. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) > i,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) > i {
|
||||
background-color: var(--pvs-ghost);
|
||||
background-image: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/* Every caption closes on a short link dash in the page's primary, the
|
||||
same mark the section copy's own link would have carried. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-gallery-item span::after,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-gallery-item span::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 33%;
|
||||
height: 5px;
|
||||
margin-top: 3px;
|
||||
background-color: var(--pvs-cta);
|
||||
border-radius: var(--pvs-radius-bar);
|
||||
}
|
||||
|
||||
/* The lead print stops a step short of the band's foot, where the mock's
|
||||
caption block ends. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
/* The lead's caption runs in two columns under its width, the way a wide
|
||||
print takes a two-column note; the dash returns to the first column. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child span,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child span {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
column-gap: 9.4%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child span::before,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child span::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 94%;
|
||||
height: 6px;
|
||||
background-color: var(--pvs-bars);
|
||||
border-radius: var(--pvs-radius-bar);
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child b,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child b {
|
||||
width: 93%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child b:nth-of-type(2),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child b:nth-of-type(2) {
|
||||
width: 77%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child b:nth-of-type(3),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child b:nth-of-type(3) {
|
||||
width: 57%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child span::after,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:first-child span::after {
|
||||
grid-column: 1;
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
/* The supporting notes run at a tighter pitch than the lead's two-column
|
||||
note, which is how the mock sets them. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-gallery-item:nth-child(2), .ps-gallery-item:nth-child(3)) span,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-gallery-item:nth-child(2), .ps-gallery-item:nth-child(3)) span {
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-gallery-item:nth-child(2), .ps-gallery-item:nth-child(3)) span::after,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop :is(.ps-gallery-item:nth-child(2), .ps-gallery-item:nth-child(3)) span::after {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
/* The middle print's own line lengths. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(2) b,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(2) b {
|
||||
width: 68%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(2) b:nth-of-type(2),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(2) b:nth-of-type(2) {
|
||||
width: 89%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(2) b:nth-of-type(3),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(2) b:nth-of-type(3) {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
/* The quiet print keeps a two-line note. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) b,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) b {
|
||||
width: 83%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) b:nth-of-type(2),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) b:nth-of-type(2) {
|
||||
width: 72%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) b:nth-of-type(3),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) b:nth-of-type(3) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) span::after,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-desktop .ps-gallery-item:nth-child(3) span::after {
|
||||
width: 34%;
|
||||
}
|
||||
|
||||
/* ── The spill on the handset ────────────────────────────────
|
||||
One column, so the spill becomes a run of two entries down the page:
|
||||
mark, print, note, dash, then the second entry at its own smaller size.
|
||||
The second entry carries its own mark, drawn by the item because the
|
||||
proof band above can only caption the first. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-proof,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-proof {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* The mark row gives back the height the two-item band needed, and the
|
||||
run of two entries below takes it. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body {
|
||||
/* The hero keeps its capped share, so the top half of the page is the
|
||||
one every other answer draws. The rows below tighten instead: the mark
|
||||
row thins to the single dot it holds, and the stack's gap comes in a
|
||||
point, which is the room the two-entry run needs at this frame. */
|
||||
grid-template-rows: minmax(0, 31%) auto auto auto 14px auto minmax(min-content, 1fr);
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body :is(.ps-proof-divider, .ps-proof-item:nth-of-type(2)),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body :is(.ps-proof-divider, .ps-proof-item:nth-of-type(2)) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-proof-item span,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-proof-item span {
|
||||
flex: none;
|
||||
width: 29%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-editorial-copy,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-editorial-copy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* The lead print at full measure. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:first-child,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:first-child {
|
||||
grid-template-rows: 46px auto;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:first-child b,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:first-child b {
|
||||
width: 72%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:first-child b:nth-of-type(2),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:first-child b:nth-of-type(2) {
|
||||
width: 51%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item b:nth-of-type(3),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item b:nth-of-type(3) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item span,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item span {
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item span::after,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item span::after {
|
||||
width: 24%;
|
||||
height: 5px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* The second entry: its own mark in the first row, then the quiet print
|
||||
at a smaller measure, then the note. */
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) {
|
||||
margin-top: 8px;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
grid-template-rows: auto 25px auto;
|
||||
gap: 4px 9px;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2)::before,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2)::before {
|
||||
content: "";
|
||||
grid-area: 1 / 1;
|
||||
align-self: center;
|
||||
width: 10px;
|
||||
aspect-ratio: 1;
|
||||
background-color: var(--pvs-cta);
|
||||
border-radius: var(--pvs-radius-dot);
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2)::after,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2)::after {
|
||||
content: "";
|
||||
grid-area: 1 / 2;
|
||||
align-self: center;
|
||||
width: 23%;
|
||||
height: 6px;
|
||||
background-color: var(--pvs-bars);
|
||||
border-radius: var(--pvs-radius-bar);
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) > i,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) > i {
|
||||
grid-area: 2 / 1 / 3 / 3;
|
||||
width: 69%;
|
||||
background-color: var(--pvs-ghost);
|
||||
background-image: none;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) span,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) span {
|
||||
grid-area: 3 / 1 / 4 / 3;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) b,
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) b {
|
||||
width: 54%;
|
||||
}
|
||||
|
||||
#picker-form:has(.picker-strategy-option:hover input[name="layout-structure"][value="freeform"]) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) b:nth-of-type(2),
|
||||
:where(#picker-form:not(:has(.picker-strategy-option:hover input[name="layout-structure"]))):has(input[name="layout-structure"][value="freeform"]:checked) .picker-preview-layout[data-surface="persuade"] .ps-phone-body .ps-gallery-item:nth-child(2) b:nth-of-type(2) {
|
||||
width: 41%;
|
||||
}
|
||||
|
||||
/* ── Freeform ────────────────────────────────────────────────
|
||||
The committed page, carried to boundaries, corners, and depth. Same terms
|
||||
as the preview above: the measure every other answer uses, with the drift
|
||||
|
||||
Reference in New Issue
Block a user