chore(repo): initialize team collaboration repository
This commit is contained in:
@@ -0,0 +1,597 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<!-- @template name="Deck" description="A twenty-one-slide presentation starter: cover, contents, dividers, columns, quadrants, a data table, SVG charts and timeline, bleed imagery, a quote and a close, on the theme's tokens" -->
|
||||
<helmet>
|
||||
<link rel="stylesheet" href="_ds/industry-22c874fd-9888-4e99-8234-d60d39b3d719/styles.css" />
|
||||
<title>Industry — deck</title>
|
||||
<script src="./ds-base.js"></script>
|
||||
<script src="./image-slot.js"></script>
|
||||
<style>
|
||||
/* Template scaffolding — slide layout and projection-scale sizing only; every
|
||||
color, font, radius and shadow comes from ../../styles.css. Change one
|
||||
number here to re-size the whole deck.
|
||||
THE WHOLE-GRID DECK (review rounds 4-5, replacing the containers-only
|
||||
reading at Barron's pick): the modular grid the blueprint grammar
|
||||
implies is drawn in full on every slide — the Grid Systems cover reading
|
||||
of the same direction. Type registers baseline-ON-rule, display sizes
|
||||
step up hard (Müller-Brockmann size contrast), photographs become grid
|
||||
objects, and the system's "+" registration marks keep marking what is
|
||||
measured. The field is EQUAL-MARGINED — 120px from all four stage
|
||||
edges — and nearly every element seats on a DRAWN rule (each seat's
|
||||
comment carries its derivation). */
|
||||
deck-stage {
|
||||
--type-display: 288px; /* 140 → 288: the grid variant's size contrast */
|
||||
--type-title: 96px; /* 76 → 96 */
|
||||
--type-subtitle: 40px;
|
||||
--type-body: 34px;
|
||||
--type-small: 28px;
|
||||
--type-kicker: 24px;
|
||||
--pad-x: 120px; /* round 2 (Barron): equal field margins — 120 on all four sides */
|
||||
--page-foot-note: "Confidential — July 2026"; /* the deck-wide imprint text (page furniture; see the PAGE FURNITURE note below) */
|
||||
--pad-top: 96px;
|
||||
--pad-bottom: 120px;
|
||||
--baseline: 48px; /* grid unit — one default-text line: the 34px Barlow body at its ~1.41
|
||||
deck leading (a compact sans). The field's bottom rule is the 20th gridline (960); in
|
||||
this variant the cover/close meta seats a half-step ABOVE it, on the 936 cell-bottom
|
||||
rule (see .pin-bottom), and 960 itself stays the hard vertical budget: the bleed's
|
||||
note ends exactly ON it, the reviewed deck's own footer convention. */
|
||||
}
|
||||
|
||||
.slide {
|
||||
display: flex; flex-direction: column;
|
||||
isolation: isolate; /* the slide is its own stacking context, so the board's
|
||||
negative z-index (below) floors it above the slide's OWN background but
|
||||
beneath every in-flow and positioned child — without isolation a negative
|
||||
z-index would drop the board behind the slide background entirely, and
|
||||
with z-index:auto a positioned board paints ABOVE in-flow ink (CSS paint
|
||||
order), the opposite of the drawn-grid intent */
|
||||
background: var(--color-bg); color: var(--color-text);
|
||||
font-family: var(--font-body);
|
||||
text-wrap: pretty; /* inherited: better breaks, no orphans on wrapped blocks */
|
||||
padding: var(--pad-top) var(--pad-x) var(--pad-bottom);
|
||||
print-color-adjust: exact; -webkit-print-color-adjust: exact;
|
||||
}
|
||||
|
||||
/* — the board: the whole modular grid, drawn — */
|
||||
/* The variant's one big move. The field is equal-margined: 120px from every
|
||||
stage edge (x 120..1800, y 120..960), so the frame reads symmetric and the
|
||||
bottom rule IS the deck's established 960 footer/budget line. Columns:
|
||||
four 384px modules with 48px gutters (pitch 432) — one baseline unit of
|
||||
gutter, the Grid Systems cover's wider vertical doubling. Rows: seven
|
||||
groups at pitch 120 (2.5 baseline units), each a 96px cell plus a 24px
|
||||
caption row — the cover's doubled-line rhythm, every rule top on the
|
||||
deck's 48/24px baseline lattice. Drawn as
|
||||
border + four repeating gradients (origin border-box, so offsets count
|
||||
from the field edge); zero-flow overlay like the reviewed deck's cells —
|
||||
delete it and no baseline moves. Ink rules on paper; the dividers and
|
||||
bleeds re-derive the rule color per ground (see below). Four "+" marks
|
||||
register the field corners; content-anchored crosses stay on the
|
||||
containers that keep them. */
|
||||
.board {
|
||||
--board-rule: color-mix(in srgb, var(--color-divider) 50%, transparent); /* review
|
||||
round 10 (Barron, pre-ship): the grid fades by half — scoped here so the
|
||||
chart grids and timeline line (data furniture on the same divider token)
|
||||
keep their full ink. The table has no rules of its own — the board rules
|
||||
it — so its ruling fades with the board, a deliberate part of the fade. */
|
||||
position: absolute; z-index: -1; /* beneath all content — see .slide's isolation
|
||||
note. The bleed slide overrides this: there the board deliberately lies ON
|
||||
the photograph, beneath the scrim (see .bleed .board) */
|
||||
left: var(--pad-x); top: calc(2.5 * var(--baseline));
|
||||
width: calc(1680px + 1px); height: calc(17.5 * var(--baseline) + 1px);
|
||||
border: 1px solid var(--board-rule, var(--color-divider));
|
||||
background-origin: border-box; background-clip: border-box;
|
||||
pointer-events: none;
|
||||
background:
|
||||
repeating-linear-gradient(to bottom, var(--board-rule, var(--color-divider)) 0 1px, transparent 1px 120px),
|
||||
repeating-linear-gradient(to bottom, transparent 0 96px, var(--board-rule, var(--color-divider)) 96px 97px, transparent 97px 120px),
|
||||
repeating-linear-gradient(to right, var(--board-rule, var(--color-divider)) 0 1px, transparent 1px 432px),
|
||||
repeating-linear-gradient(to right, transparent 0 384px, var(--board-rule, var(--color-divider)) 384px 385px, transparent 385px 432px);
|
||||
}
|
||||
|
||||
/* — shared pieces — */
|
||||
/* Baseline grid: text sits on a 48px rhythm (--baseline) measured from the
|
||||
slide's top edge. Snapped text blocks are trimmed to their cap and baseline
|
||||
edges (text-box), so a block's bottom edge IS its last baseline and the next
|
||||
block's first baseline lands N gridlines down with
|
||||
margin-top: calc(N * var(--baseline) - 1cap). Compact rhythms (chart axes
|
||||
and ticks) sit on the 24px half-step. Review the rhythm with ?baselines in
|
||||
the URL, or press B (script in the helmet) — half-step lines draw
|
||||
fainter than full ones. In this variant the board's rules are a subset of
|
||||
the same lattice: row-group tops are full gridlines, cell bottoms are
|
||||
half-steps, so "baseline on the rule" and "baseline on the grid" are one
|
||||
statement. */
|
||||
.kicker {
|
||||
position: absolute; top: calc(2 * var(--baseline) - 1cap); /* baseline on the reviewed
|
||||
deck's own kicker line (96) — now half a unit ABOVE the field's 120 top rule,
|
||||
so the rule and its corner crosses stay clean */
|
||||
left: var(--pad-x); text-box: trim-both cap alphabetic;
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: var(--type-kicker); letter-spacing: 0.08em; text-transform: uppercase;
|
||||
color: var(--color-accent);
|
||||
font-feature-settings: "tnum" 1;
|
||||
}
|
||||
.k-right { left: auto; right: var(--pad-x); } /* the cover/close kicker rides the
|
||||
top rule flush right — the Grid Systems cover's author line */
|
||||
.slide-title {
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: var(--type-title); line-height: calc(2 * var(--baseline)); letter-spacing: 0; margin: 0;
|
||||
margin-left: -0.052em; /* optical left alignment — measured for Barlow
|
||||
Condensed SemiBold in the reviewed deck; em-scaled, so it holds at 96px */
|
||||
text-box: trim-both cap alphabetic;
|
||||
}
|
||||
.pin-bottom { position: absolute; left: var(--pad-x); right: var(--pad-x); bottom: calc(var(--pad-bottom) + var(--baseline) / 2); } /* baseline
|
||||
on the 936 caption rule — inside the field, clear of the 960 corner crosses;
|
||||
the last caption row [936,960] is the imprint's band */
|
||||
.meta { display: flex; align-items: baseline; gap: 18px; font-size: var(--type-kicker); color: color-mix(in srgb, var(--color-text) 55%, transparent); }
|
||||
.meta span { text-box: trim-both cap alphabetic; } /* baseline on the 936 caption rule — see .pin-bottom */
|
||||
|
||||
/* PAGE FURNITURE — on by default. To remove the page numbers and footer
|
||||
text deck-wide, add data-no-page-furniture to the deck's <x-import>
|
||||
mount (a one-line tweak — it renders on the <deck-stage>); to change
|
||||
the text, edit --page-foot-note in
|
||||
the deck's token block. The imprint sits where this board documents its
|
||||
imprint's band: flush left on the axis, baseline ON the 936 caption rule
|
||||
(the last caption row [936,960] of the field), at the meta row's scale
|
||||
and 55% ink, the number tabular. Carried by the content slides (hero,
|
||||
quote, split and the half-bleeds included — on the half-bleeds it
|
||||
follows the copy half, because small muted type cannot pass the
|
||||
type-over-photography rule) AND by the dividers: a blueprint sheet
|
||||
carries its imprint on every ground, so the dividers keep it with the
|
||||
ink re-derived to the page-corner marks' 55% paper (measured against
|
||||
the steel ground in the render audit). The cover and close keep their
|
||||
meta rows on the same rule instead, and the full bleed's photograph
|
||||
owns its edges. Every slide still counts, so the printed number stays
|
||||
truthful to position. */
|
||||
deck-stage { counter-reset: page; }
|
||||
.slide { counter-increment: page; }
|
||||
.page-foot {
|
||||
position: absolute; left: var(--pad-x); bottom: calc(var(--pad-bottom) + var(--baseline) / 2); /* baseline ON the 936 caption rule, like .pin-bottom */
|
||||
font-size: var(--type-kicker);
|
||||
color: color-mix(in srgb, var(--color-text) 55%, transparent);
|
||||
text-box: trim-both cap alphabetic; /* bottom edge = baseline */
|
||||
}
|
||||
.page-foot::before { content: counter(page) " · "; font-feature-settings: "tnum" 1; }
|
||||
.page-foot::after { content: var(--page-foot-note); }
|
||||
deck-stage[data-no-page-furniture] .page-foot, deck-stage[data-no-page-furniture] .page-head { display: none !important; }
|
||||
.divider .page-foot { color: color-mix(in srgb, var(--color-bg) 55%, transparent); } /* the imprint survives the steel sheet in the page corners' paper-alpha ink */
|
||||
.half-bleed:not(.flip) .page-foot { left: 984px; } /* the imprint follows the copy half, seated on column 3's rule — type never sits on the photograph (deck-templates.md law) */
|
||||
|
||||
/* — cover and close — */
|
||||
/* The Grid Systems cover, in industry's inks: the full board behind a
|
||||
display line seated baseline-ON-rule (row-group 5's top, y 600), with the
|
||||
description split into two caption columns under it — a short left cell
|
||||
on the axis, the long cell on column 2 — first baselines ON the 696
|
||||
caption rule, clear of the display's descenders (~55px below 600). The
|
||||
kicker rides flush right above the field; the meta sits on the last
|
||||
caption rule (936), inside the field. Most of the grid stays empty on
|
||||
purpose. */
|
||||
.cover { justify-content: flex-start; }
|
||||
.cover .rise { position: absolute; inset: 0 var(--pad-x); }
|
||||
.display {
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: var(--type-display); line-height: calc(6 * var(--baseline)); letter-spacing: 0; margin: 0;
|
||||
margin-left: -0.052em; /* optical left alignment, em-scaled — see .slide-title */
|
||||
margin-top: calc(12.5 * var(--baseline) - 1cap); /* baseline exactly on the group-5 top rule (600) */
|
||||
text-box: trim-both cap alphabetic;
|
||||
}
|
||||
.cover-sub { font-size: var(--type-small); line-height: var(--baseline); margin: 0;
|
||||
position: absolute; left: 0; max-width: 768px;
|
||||
top: calc(14.5 * var(--baseline) - 1cap); /* first baseline ON the 696 caption rule —
|
||||
clear of the 288px display's descenders (~55px below 600) */
|
||||
text-box: trim-both cap alphabetic; }
|
||||
.cover-sub-a { left: 0; max-width: 360px; }
|
||||
.cover-sub-b { left: 432px; max-width: 816px; } /* column 2's left edge (x 552) */
|
||||
|
||||
/* — contents — */
|
||||
/* Contents as the cover's caption rows: no panel, no added rules — the
|
||||
board IS the ruling. Each entry's baseline sits ON a caption rule
|
||||
(456 / 576 / 696 / 816), the 24px caption row beneath reading as the
|
||||
doubled line of the reference cover. Numbers hold the axis; labels start
|
||||
on column 2 (x 552) — secondary starts in this deck always sit on a
|
||||
column edge. */
|
||||
.toc { position: absolute; inset: 0 var(--pad-x); font-size: var(--type-subtitle); }
|
||||
.toc-row { position: absolute; left: 0; right: 0; }
|
||||
.toc-row > span { text-box: trim-both cap alphabetic; position: absolute; top: 0; }
|
||||
.toc-row > .toc-label { left: 432px; }
|
||||
.toc-num { font-size: var(--type-kicker); color: var(--color-accent); font-feature-settings: "tnum" 1; }
|
||||
.toc-row { top: calc(9.5 * var(--baseline)); } /* baseline on the 456 caption rule; the rows
|
||||
re-seat below via nth-child so markup stays the reviewed deck's */
|
||||
.toc-row:nth-child(2) { top: calc(12 * var(--baseline)); }
|
||||
.toc-row:nth-child(3) { top: calc(14.5 * var(--baseline)); }
|
||||
.toc-row:nth-child(4) { top: calc(17 * var(--baseline)); }
|
||||
.toc-row > span { top: calc(-1cap); } /* each span trims to its cap; the row's
|
||||
top IS the rule, so the baseline lands on it */
|
||||
|
||||
/* — section dividers — */
|
||||
/* Dividers keep their own ground — the deep steel blueprint sheet — and the
|
||||
variant draws the board through it in paper-alpha hairlines: the section
|
||||
break is a fresh sheet of the same grid. Ghost numeral and title seat
|
||||
baseline-ON-rule like everything else (ghost on 600, title on 816), both
|
||||
flush on the axis; the "+" page corners keep their registration spots.
|
||||
Contrast re-derived for the steel ground: paper type 12.6:1, ghost at
|
||||
~2.2:1 (a drawing showing through the sheet), board rules decorative at
|
||||
9% paper (halved in round 10's pre-ship fade). */ /* seats: ghost baseline ON the group-5 top rule (600),
|
||||
title ON the 816 caption rule — see each declaration */
|
||||
.divider { justify-content: flex-start; background: var(--color-accent-900); color: var(--color-bg); }
|
||||
.divider .board { --board-rule: color-mix(in srgb, var(--color-bg) 9%, transparent); } /* half of the pre-round-10 18% — the fade keeps the per-ground ratio */
|
||||
.divider .board > .corner { color: color-mix(in srgb, var(--color-bg) 55%, transparent); }
|
||||
.divider .rise { position: absolute; inset: 0 var(--pad-x); }
|
||||
.page-corner {
|
||||
position: absolute; width: 15px; height: 15px;
|
||||
color: color-mix(in srgb, var(--color-bg) 55%, transparent);
|
||||
}
|
||||
.page-corner::before, .page-corner::after { content: ""; position: absolute; background: currentColor; }
|
||||
.page-corner::before { left: 7px; top: 0; width: 1px; height: 100%; }
|
||||
.page-corner::after { top: 7px; left: 0; width: 100%; height: 1px; }
|
||||
.page-corner.tl { top: 41px; left: 41px; }
|
||||
.page-corner.tr { top: 41px; right: 41px; }
|
||||
.page-corner.bl { bottom: 41px; left: 41px; }
|
||||
.page-corner.br { bottom: 41px; right: 41px; }
|
||||
|
||||
/* — registration crosses (the cell-corner grammar, kept) — */
|
||||
.cell { position: absolute; border: 1px solid var(--color-divider); pointer-events: none; }
|
||||
.cell > .corner, .board > .corner { position: absolute; width: 15px; height: 15px; color: color-mix(in srgb, var(--color-text) 55%, transparent); }
|
||||
.cell > .corner::before, .cell > .corner::after,
|
||||
.board > .corner::before, .board > .corner::after { content: ""; position: absolute; background: currentColor; }
|
||||
.cell > .corner::before, .board > .corner::before { left: 7px; top: 0; width: 1px; height: 100%; }
|
||||
.cell > .corner::after, .board > .corner::after { top: 7px; left: 0; width: 100%; height: 1px; }
|
||||
.cell > .corner.tl, .board > .corner.tl { top: -8px; left: -8px; }
|
||||
.cell > .corner.tr, .board > .corner.tr { top: -8px; right: -8px; }
|
||||
.cell > .corner.bl, .board > .corner.bl { bottom: -8px; left: -8px; }
|
||||
.cell > .corner.br, .board > .corner.br { bottom: -8px; right: -8px; }
|
||||
/* -8px = the 7px arm offset + the 1px border: absolute offsets resolve from
|
||||
the PADDING box, inside the border — each cross centers exactly on its
|
||||
rule intersection, the reviewed deck's convention. */
|
||||
.ghost-num {
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: 480px; line-height: 1; letter-spacing: 0;
|
||||
color: var(--color-accent-700);
|
||||
position: absolute; top: calc(12.5 * var(--baseline) - 1cap); /* baseline on the
|
||||
group-5 top rule (600) */
|
||||
text-box: trim-both cap alphabetic;
|
||||
margin-left: -0.036em; /* ghosts lead with "0" — optical value from the reviewed deck, em-scaled */
|
||||
}
|
||||
.divider .slide-title { position: absolute; top: calc(17 * var(--baseline) - 1cap); } /* baseline on the 816 caption rule */
|
||||
|
||||
/* — content slides — */
|
||||
.content { padding-top: calc(5 * var(--baseline)); /* title baseline on the 5th gridline —
|
||||
row 2's top rule (240), clear of the pinned kicker row */ }
|
||||
.content > .slide-title, .content > .chart-head { margin-top: -1cap; } /* cap-trimmed: the baseline, not the cap top, sits on the rule */
|
||||
.content > .bullets { margin-top: calc(2.5 * var(--baseline) - 1cap); } /* first baseline on
|
||||
the group-3 top rule (360), one row group below the title's */
|
||||
.content > figure { margin-top: calc(2 * var(--baseline)); } /* svg top on the 336 caption
|
||||
rule; the plots' axis line (svg y 360) lands ON the 696 caption rule */
|
||||
.content > .table { margin-top: calc(0.5 * var(--baseline)); } /* table top at 264: the 96px
|
||||
header row closes its baseline ON the group-3 top rule (360) */
|
||||
.content > .chart-caption { margin-top: calc(2 * var(--baseline) - 1cap); }
|
||||
.bullets { display: flex; flex-direction: column; max-width: 1220px; margin: 0; padding: 0; list-style: none; font-size: var(--type-body); }
|
||||
.bullets li { position: relative; line-height: var(--baseline); text-box: trim-both cap alphabetic; }
|
||||
.bullets li + li { margin-top: calc(2.5 * var(--baseline) - 1cap); } /* one thought per
|
||||
row group: single-line bullets seat on successive group-top rules
|
||||
(360 / 480 / 600) — the variant's pitch (the reviewed deck: every other
|
||||
gridline) */
|
||||
.bullets li::before, .bullets li::after { content: ""; position: absolute; background: var(--color-accent); }
|
||||
.bullets li::before { left: -37px; top: calc(0.5cap - 8px); width: 2px; height: 16px; }
|
||||
.bullets li::after { left: -44px; top: calc(0.5cap - 1px); width: 16px; height: 2px; }
|
||||
|
||||
/* — column layouts — */
|
||||
/* Columns are the board's own bays: the two-column setting takes two
|
||||
modules per column (x 120 and 984, 816px each, the drawn 48px gutter
|
||||
between), and the three-column setting takes one module apiece (x 120,
|
||||
552, 984) leaving module 4 DELIBERATELY empty — the Grid Systems cover's
|
||||
empty-cell statement; on a four-module board three equal full-width
|
||||
columns cannot seat on drawn rules, so the grid wins and the measure
|
||||
narrows (a module runs ≈21 characters of condensed head, ≈26 of small
|
||||
note — notes, not essays). No rules are added: the board is the ruling.
|
||||
Seats: head baselines ON the group-3 top rule (360), note baselines ON
|
||||
the 456 caption rule, wrapped lines riding the 48px lattice below. */
|
||||
.cols { display: grid; column-gap: var(--baseline); margin-top: calc(2.5 * var(--baseline)); /* container top ON the group-3 rule; the cap term lives on the h3, where it resolves in the heading face (the two-family decks' -1cap lesson) */ }
|
||||
.cols-2 { grid-template-columns: 816px 816px; }
|
||||
.cols-3 { grid-template-columns: repeat(3, 384px); }
|
||||
.cols h3 { font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: var(--type-subtitle); line-height: var(--baseline); margin: 0;
|
||||
margin-top: -1cap; /* baseline ON the group-3 top rule (360); 1cap in the h3's own face */
|
||||
text-box: trim-both cap alphabetic; }
|
||||
.cols p { font-size: var(--type-small); line-height: var(--baseline); margin: 0;
|
||||
margin-top: calc(2 * var(--baseline) - 1cap); /* first baseline ON the 456 caption rule */
|
||||
text-box: trim-both cap alphabetic; }
|
||||
|
||||
/* — quadrants — */
|
||||
/* The board IS the matrix — no division is drawn because every division
|
||||
is already there: the vertical axis is the columns 2/3 gutter (center
|
||||
960), the horizontal axis is the group-5 top rule (600). Cells are
|
||||
two-module x two-row-group bays: heads seat their baselines ON the band
|
||||
top rules (360 upper, 600 lower — the lower heads hang from the crossing
|
||||
rule itself, the way every seated element does), one-liners ON the
|
||||
caption rules below (456 / 696), wraps on the lattice. The axis pair
|
||||
seats ON the group-7 top rule (840), left label on the axis, right label
|
||||
flush right (the cover kicker's k-right precedent), one row group clear
|
||||
of the 936 imprint. Left column = lower x; the y reading (top row
|
||||
smaller work) is carried by the cell copy — a y pair has no seat that
|
||||
doesn't fight the imprint band or the axis, so the horizontal pair does
|
||||
the labeling (the shared-spec minimum). */
|
||||
.quad { display: grid; grid-template-columns: 816px 816px; column-gap: var(--baseline);
|
||||
grid-template-rows: calc(5 * var(--baseline)) calc(5 * var(--baseline));
|
||||
margin-top: calc(2.5 * var(--baseline)); /* matrix top = the group-3 top rule (360) */ }
|
||||
.quad h3 { font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: var(--type-subtitle); line-height: var(--baseline); margin: 0;
|
||||
margin-top: -1cap; /* baseline ON the cell's band-top rule (360 / 600) */
|
||||
text-box: trim-both cap alphabetic; }
|
||||
.quad p { font-size: var(--type-small); line-height: var(--baseline); margin: 0;
|
||||
margin-top: calc(2 * var(--baseline) - 1cap); /* one-liner ON the caption rule (456 / 696) */
|
||||
text-box: trim-both cap alphabetic; }
|
||||
.quad-axis { display: flex; justify-content: space-between;
|
||||
margin-top: -1cap; /* label baselines ON the group-7 top rule (840) */
|
||||
font-size: var(--type-kicker); letter-spacing: 0.08em; text-transform: uppercase;
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
color: color-mix(in srgb, var(--color-text) 55%, transparent); }
|
||||
.quad-axis span { text-box: trim-both cap alphabetic; }
|
||||
|
||||
/* — data table (component class at projection scale) — */
|
||||
/* The board rules the table: the component's own hairlines are suppressed
|
||||
(a variant style call — no rules are drawn twice) and the rows take the
|
||||
board's 120px row groups ONE-PER-ROW, each row's text baseline ON its
|
||||
caption rule (456 / 576 / 696 / 816), the header on the group-3 top rule
|
||||
(360). Columns seat on the grid columns — Role on the axis, Value on
|
||||
column 2 (552), ground on column 3 (984), Use on column 4 (1416) — and
|
||||
the swatch hangs LEFT of the axis like every other mark, its bottom edge
|
||||
on the row's rule. */
|
||||
.slide .table { max-width: 1680px; width: 1680px; font-size: 29px; font-feature-settings: "tnum" 1;
|
||||
table-layout: fixed; border-collapse: collapse; }
|
||||
/* Column plan: three 432px columns — one grid module each — and the rest
|
||||
to Use. Carried on the header row's cells (table-layout: fixed reads row
|
||||
one) rather than a <colgroup>: the Design Component pipeline parses the
|
||||
template outside a real <table> context, where col elements are dropped,
|
||||
and a fixed-layout table without them would fall back to equal columns. */
|
||||
.slide .table th:nth-child(-n+3) { width: 432px; }
|
||||
.slide .table thead tr { height: calc(2 * var(--baseline)); }
|
||||
.slide .table tbody tr { height: calc(2.5 * var(--baseline)); } /* one board row group per data row */
|
||||
.slide .table th, .slide .table td {
|
||||
text-box: trim-both cap alphabetic; text-align: left; font-weight: 400;
|
||||
border: none; background: none; vertical-align: bottom;
|
||||
padding: 0 24px calc(0.5 * var(--baseline)) 0;
|
||||
}
|
||||
.slide .table th { font-size: var(--type-kicker); }
|
||||
.slide .table thead th { padding-bottom: 0; } /* bottom-anchored: the header row closes ON the
|
||||
group-3 top rule (360), each data row's LAST baseline sits 24px above its row's bottom —
|
||||
on the caption rules 456 / 576 / 696 / 816 — and a wrapped cell grows upward into
|
||||
its own cell instead of past the field (the vertical budget, kept by construction) */
|
||||
.slide .table tbody tr:hover { background: none; }
|
||||
.slide .table th:first-child, .slide .table td:first-child { padding-left: 0; position: relative; }
|
||||
.slide .table th:last-child, .slide .table td:last-child { padding-right: 0; }
|
||||
.slide .table .swatch { position: absolute; left: -72px; bottom: calc(0.5 * var(--baseline)); } /* hangs
|
||||
left of the axis like every mark; bottom edge ON the row's rule */
|
||||
.swatch { display: inline-block; width: 48px; height: 48px; border-radius: 0; /* square-corner
|
||||
doctrine; 48px = one grid unit, bottom edge on the row's rule */ box-shadow: var(--shadow-sm); }
|
||||
|
||||
/* — hero figure — */
|
||||
/* The variant's loudest size contrast: the figure at 432px, flush on the
|
||||
axis, baseline ON the group-5 top rule (600); the caption moves to column
|
||||
3 (x 984), its first baseline ON the 696 caption rule — the number and
|
||||
its note read corner-to-corner across the empty grid. */
|
||||
.hero { justify-content: flex-start; }
|
||||
.hero-num {
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: 432px; line-height: 1; letter-spacing: 0; margin: 0;
|
||||
color: var(--color-accent);
|
||||
position: absolute; left: var(--pad-x); top: calc(12.5 * var(--baseline) - 1cap);
|
||||
text-box: trim-both cap alphabetic;
|
||||
margin-left: -0.010em; /* leads with the near-bearingless "1" — reviewed value, em-scaled */
|
||||
}
|
||||
.hero-caption { font-size: var(--type-small); line-height: var(--baseline); margin: 0;
|
||||
position: absolute; left: 984px; top: calc(14.5 * var(--baseline) - 1cap); max-width: 816px;
|
||||
text-box: trim-both cap alphabetic; }
|
||||
|
||||
/* — charts (static SVG on the tokens; no script, no chart library) — */
|
||||
/* The plots seat their anatomy ON drawn rules — svg top at 336 (a caption
|
||||
rule), the x-axis ON the 696 caption rule, and the line chart's 10k
|
||||
gridlines (120px apart, the row-group pitch) phased by the axis onto the
|
||||
drawn caption rules (576 / 456). Bar x-geometry is derived for the 1680
|
||||
field. The board's column rules pass behind the plots — the drawing
|
||||
stays on its grid. */
|
||||
.chart { display: block; width: 100%; height: auto; overflow: visible; }
|
||||
.chart text {
|
||||
font-family: var(--font-body); font-size: 24px;
|
||||
fill: color-mix(in srgb, var(--color-text) 55%, transparent);
|
||||
font-feature-settings: "tnum" 1;
|
||||
}
|
||||
.chart .grid, .chart .axis { stroke: var(--color-divider); stroke-width: 1; }
|
||||
.chart .bar { fill: none; stroke: var(--color-neutral-600); stroke-width: 1; }
|
||||
.chart .bar-hi { fill: var(--color-accent); stroke: none; }
|
||||
.chart .val { fill: color-mix(in srgb, var(--color-text) 70%, transparent); }
|
||||
.chart .ref { stroke: var(--color-accent-700); stroke-width: 1; stroke-dasharray: 8 8; }
|
||||
.chart .ref-label { fill: var(--color-accent-700); }
|
||||
.chart .hi-label { fill: var(--color-accent-700); }
|
||||
.chart .series-a, .key .series-a { stroke: var(--color-accent); stroke-width: 3; fill: none; }
|
||||
.chart .series-b, .key .series-b { stroke: var(--color-neutral-800); stroke-width: 3; fill: none; stroke-dasharray: 10 8; }
|
||||
.chart-caption { font-size: 25px; line-height: var(--baseline); max-width: 88ch; margin: 0; text-box: trim-both cap alphabetic; }
|
||||
.chart-head { display: flex; align-items: baseline; justify-content: space-between;
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: var(--type-title); }
|
||||
.chart-legend { display: flex; align-items: baseline; gap: 16px; font-family: var(--font-body); font-weight: 400; font-size: var(--type-kicker); color: color-mix(in srgb, var(--color-text) 55%, transparent); }
|
||||
.chart-legend span { text-box: trim-both cap alphabetic; }
|
||||
.chart-legend .key { width: 60px; height: 4px; overflow: visible; position: relative; top: -7px; }
|
||||
.chart-legend .key:not(:first-child) { margin-left: 24px; }
|
||||
.chart .tl-line { stroke: var(--color-divider); stroke-width: 1; }
|
||||
.chart .tl-node { stroke: var(--color-neutral-600); stroke-width: 1.5; }
|
||||
.chart .tl-node-hi-fill { fill: var(--color-accent); }
|
||||
.chart .tl-node-hi { stroke: var(--color-bg); stroke-width: 1.5; }
|
||||
.chart .tl-date { fill: color-mix(in srgb, var(--color-text) 55%, transparent); letter-spacing: 0.08em; }
|
||||
.chart .tl-date-hi { fill: var(--color-accent-700); letter-spacing: 0.08em; }
|
||||
.chart .tl-label { fill: var(--color-text); font-size: 30px; font-family: var(--font-heading); font-weight: var(--font-heading-weight); }
|
||||
/* The timeline figure drops to the mid-field so its line sits ON the
|
||||
group-4 top rule (480): svg top at 384, dates above, labels below, the
|
||||
notes' baselines landing exactly ON the group-5 top rule (600). Node
|
||||
pitch is 360 — milestone positions are data, not grid furniture. The
|
||||
column-seated alternative (pitch 432, nodes on 120/552/984/1416/1800,
|
||||
re-checked for the round-2 geometry) stays rejected: the fifth
|
||||
milestone's ~340px notes would either overflow the stage or,
|
||||
right-anchored, collide with the fourth's — and mixed anchoring
|
||||
re-breaks the reviewed one-left-edge-per-milestone rule. */
|
||||
.fig-timeline { margin-top: calc(3 * var(--baseline)) !important; }
|
||||
|
||||
/* — image slide — */
|
||||
/* The photograph becomes a grid object: columns 3-4 by row-groups 2-7
|
||||
exactly (x 984..1800, y 240..936), the blueprint frame's "+" marks seated
|
||||
on board intersections. The copy keeps the axis in columns 1-2. */
|
||||
.split { flex-direction: row; align-items: flex-start; gap: 0; padding-top: calc(5 * var(--baseline)); }
|
||||
.split-copy { flex: none; width: 768px; display: flex; flex-direction: column; }
|
||||
.split-copy .slide-title { margin-top: -1cap; }
|
||||
.split-copy .note { font-size: var(--type-small); line-height: var(--baseline); margin: calc(2.5 * var(--baseline) - 1cap) 0 0;
|
||||
text-box: trim-both cap alphabetic; max-width: 768px; }
|
||||
.split-figure { position: absolute; left: 984px; top: calc(5 * var(--baseline)); width: 816px; height: calc(14.5 * var(--baseline)); margin: 0; }
|
||||
.split-figure image-slot { width: 100%; height: 100%; } /* the grid-object box (columns 3-4 ×
|
||||
row-groups 2-7) does the framing; cover is the component's own default */
|
||||
.split-figure > .corner { pointer-events: none; } /* the registration crosses overlap the
|
||||
slot by a few px — decorative marks must not eat its hover/drop events
|
||||
(image-slot usage contract); scoped here rather than in styles.css, whose
|
||||
.corner serves the whole system */
|
||||
|
||||
/* — full-bleed image slide — */
|
||||
/* The board is drawn OVER the photograph in paper-alpha — the blueprint
|
||||
laid onto the image — and UNDER the scrim, so the rules fade out exactly
|
||||
where the type needs its measured ground. Type treatment unchanged from
|
||||
the reviewed deck (it passes the type-over-photography rule): full-ink
|
||||
note, kicker stepped to accent-700. */
|
||||
.bleed .board { --board-rule: color-mix(in srgb, var(--color-bg) 13%, transparent); /* half of the pre-round-10 25%, rounded to a whole step */
|
||||
z-index: auto; /* the one slide where the board rides ABOVE its photograph:
|
||||
DOM-order painting — after the positioned figure, before the positioned
|
||||
scrim — so photo → board → scrim → copy stack as documented */ }
|
||||
.bleed .board > .corner { color: color-mix(in srgb, var(--color-bg) 55%, transparent); }
|
||||
.bleed-figure { position: absolute; inset: 0; margin: 0; }
|
||||
.bleed-figure image-slot { width: 100%; height: 100%; } /* framing is the component's (fit=cover default) */
|
||||
.bleed-scrim {
|
||||
position: absolute; inset: 0; pointer-events: none; /* the slot beneath is interactive (hover controls, drops) — overlays must not eat its events (image-slot usage contract) */
|
||||
background:
|
||||
linear-gradient(to top,
|
||||
color-mix(in srgb, var(--color-bg) 98%, transparent),
|
||||
color-mix(in srgb, var(--color-bg) 95%, transparent) 24%,
|
||||
color-mix(in srgb, var(--color-bg) 60%, transparent) 42%,
|
||||
transparent 66%),
|
||||
linear-gradient(to bottom,
|
||||
color-mix(in srgb, var(--color-bg) 92%, transparent),
|
||||
color-mix(in srgb, var(--color-bg) 80%, transparent) 12%,
|
||||
transparent 26%);
|
||||
}
|
||||
.bleed-copy { position: absolute; left: var(--pad-x); right: var(--pad-x); bottom: var(--pad-bottom); pointer-events: none; } /* text over the slot — must not eat its hover/drop events */
|
||||
.bleed .kicker { color: var(--color-accent-700); pointer-events: none; /* sits on the photograph — same usage contract as the scrim */ }
|
||||
.bleed-copy .note {
|
||||
font-size: var(--type-small); line-height: var(--baseline); max-width: 56ch;
|
||||
margin: calc(2 * var(--baseline) - 1cap) 0 0;
|
||||
text-box: trim-both cap alphabetic;
|
||||
color: var(--color-text);
|
||||
} /* bottom-anchored block: the note's LAST baseline sits ON the field's 960
|
||||
bottom rule; its earlier baselines (864/912) and the title's (768) ride the
|
||||
48px lattice, not drawn rules — over a photograph the scrim, not the board,
|
||||
is the ground (the board fades out beneath it) */
|
||||
|
||||
/* — half-bleed image slides — */
|
||||
/* The photograph takes grid columns, not a raw half-stage: it bleeds to
|
||||
three edges and stops at the gutter (base: columns 1-2, inner edge on
|
||||
the 936 gutter rule; .flip mirrors to columns 3-4, starting exactly on
|
||||
column 3's rule at 984), and the copy starts on a column rule — x 984
|
||||
(column 3) for the base, the axis for the mirror. The board draws first,
|
||||
the photograph covers its half. */
|
||||
.half-bleed { padding-top: calc(5 * var(--baseline)); }
|
||||
.half-bleed > .slide-title { margin-top: -1cap; max-width: 816px; }
|
||||
.half-bleed .note {
|
||||
font-size: var(--type-small); line-height: var(--baseline); max-width: 816px;
|
||||
margin: calc(2 * var(--baseline) - 1cap) 0 0;
|
||||
text-box: trim-both cap alphabetic;
|
||||
}
|
||||
.half-bleed .bullets { margin-top: calc(2.5 * var(--baseline) - 1cap); max-width: 816px; }
|
||||
.half-bleed .bullets li + li { margin-top: calc(4 * var(--baseline) - 1cap); } /* items here
|
||||
run up to two lines: the 4-unit gap from a two-line item's last baseline seats
|
||||
each bullet's FIRST baseline back on a group-top rule (360 / 600 / 840), and a
|
||||
one-line item simply leaves more air before the next */
|
||||
.half-bleed-figure { position: absolute; inset: 0 auto 0 0; width: 936px; margin: 0; }
|
||||
.half-bleed-figure image-slot { width: 100%; height: 100%; } /* framing is the component's (fit=cover default) */
|
||||
.half-bleed:not(.flip) > .slide-title { margin-left: calc(864px - 0.052em); } /* column 3 (x 984), preserving the optical shift */
|
||||
.half-bleed:not(.flip) .note,
|
||||
.half-bleed:not(.flip) .bullets { margin-left: 864px; }
|
||||
.half-bleed:not(.flip) .kicker { left: 984px; }
|
||||
.half-bleed.flip .half-bleed-figure { inset: 0 0 0 auto; width: 936px; }
|
||||
/* With the photograph ending on the 936 gutter rule and the copy on column
|
||||
3 (984), the 48px gutter is the hanging margin: the crosses center on the
|
||||
gutter's own centerline (x 960) with 16px of paper on either side —
|
||||
"whatever sits behind them" now means the gutter itself. */
|
||||
.half-bleed:not(.flip) .bullets li::before { left: -25px; }
|
||||
.half-bleed:not(.flip) .bullets li::after { left: -32px; }
|
||||
|
||||
/* — quote — */
|
||||
/* Flush on the axis, airy MB leading: 64px poster lines on a two-unit
|
||||
(96px) leading, first baseline ON the group-3 top rule (360; the deck's
|
||||
copy sets in two lines, 360/456 — top rule and caption rule); the
|
||||
attribution drops to the 696 caption rule — see the figcaption note. */
|
||||
.quote { justify-content: flex-start; }
|
||||
.quote .rise { position: absolute; inset: 0 var(--pad-x); }
|
||||
.quote blockquote {
|
||||
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
||||
font-size: 64px; line-height: calc(2 * var(--baseline)); letter-spacing: 0;
|
||||
max-width: 1200px; margin: 0;
|
||||
margin-top: calc(7.5 * var(--baseline) - 1cap); /* first baseline on the group-3 top rule (360) */
|
||||
text-box: trim-both cap alphabetic;
|
||||
text-indent: -0.316em; /* hang the opening “ (measured advance in the Condensed 600) */
|
||||
}
|
||||
.quote figcaption { font-size: var(--type-small); margin: 0;
|
||||
position: absolute; top: calc(14.5 * var(--baseline) - 1cap); /* baseline on the 696
|
||||
caption rule — a full row-group below the quote's two-line setting (360/456),
|
||||
chosen for air over the nearer 576 rule; re-seat if the quote re-wraps */
|
||||
text-box: trim-both cap alphabetic;
|
||||
text-indent: -0.885em; /* hang the leading em-dash + space (measured advance in Barlow Regular) */ }
|
||||
|
||||
/* Review aid: the baseline grid drawn as a hairline under every --baseline
|
||||
step. Debug-only — toggled by ?baselines or the B key; not part of the look. */
|
||||
deck-stage[data-baselines] .slide::after {
|
||||
content: ""; position: absolute; inset: 0; pointer-events: none;
|
||||
background:
|
||||
repeating-linear-gradient(to bottom,
|
||||
color-mix(in srgb, var(--color-accent) 35%, transparent) 0 1px,
|
||||
transparent 1px var(--baseline)),
|
||||
repeating-linear-gradient(to bottom,
|
||||
transparent 0 calc(var(--baseline) / 2),
|
||||
color-mix(in srgb, var(--color-accent) 16%, transparent) calc(var(--baseline) / 2) calc(var(--baseline) / 2 + 1px),
|
||||
transparent calc(var(--baseline) / 2 + 1px) var(--baseline));
|
||||
}
|
||||
|
||||
/* Entrance — end-state is the base style; animate from hidden, gated on the
|
||||
active slide and the motion preference, so print and reduced-motion are safe. */
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
[data-deck-active] .rise { animation: rise 0.45s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
|
||||
@keyframes rise { from { opacity: 0; transform: translateY(14px); } }
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
// Review aid: baseline-grid overlay — add ?baselines to the URL, or press B to toggle.
|
||||
// This runs from <helmet>, before the deck renders, so the stage is looked up when it is
|
||||
// needed instead of captured up front; the window flag keeps a second evaluation of
|
||||
// this helmet script (a recreated script node) from binding the B key twice.
|
||||
(() => {
|
||||
if (window.__deckBaselineAid) return;
|
||||
window.__deckBaselineAid = true;
|
||||
const stage = () => document.querySelector('deck-stage');
|
||||
if (new URLSearchParams(location.search).has('baselines')) {
|
||||
let tries = 600; // wait out the deck's first render (up to ~10s of frames)
|
||||
const arm = () => { const s = stage(); if (s) s.setAttribute('data-baselines', ''); else if (tries-- > 0) requestAnimationFrame(arm); };
|
||||
arm();
|
||||
}
|
||||
addEventListener('keydown', (e) => {
|
||||
const t = e.target;
|
||||
if (t && (t.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(t.tagName))) return; // typing guard, as in deck-stage's own keys
|
||||
if ((e.key === 'b' || e.key === 'B') && !e.metaKey && !e.ctrlKey && !e.altKey) stage()?.toggleAttribute('data-baselines');
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</helmet>
|
||||
<x-import component-from-global-scope="deck-stage" from="./deck-stage.js" width="1920" height="1080" hint-size="100%,100%">
|
||||
|
||||
</x-import>
|
||||
</x-dc>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user