Design system preview · v0.1.0

Idealmac

Generated from the spec on 2026-10-31. Source: Sito IDEALMAC.pdf (6 full-page screenshots at 1920px) -> rebuild/ -> sources/2026-10-23-rebuilt. Highlighted steps are decided; the others are still pending.

Decisions

Every choice made at the checkpoints, in order. Re-running the skill applies them again.
#TopicDecisionReason
D1Source of truthThe design system is derived from the PDF alone; no live site is captured. The six JPEGs are a *brief*, not a capture: they answer colour and 1920px geometry and nothing elseThe user has no site to capture for this version
D2Pipeline entryThe PDF is reconstructed as static HTML in `sources/<date>-rebuilt/`, which is then captured with `capture.mjs` and becomes the project's real capture. `inventory.py`, `detect_layout.py` and `validate.py` run on that capture as usualKeeps the deterministic half of the system: a raster cannot be measured, authored HTML can. Every value the rebuild invents is a decision here, so the spec never silently inherits a guess
D3Measured vs. authoredColours and 1920px band geometry are taken from the pixels and are exact. Type scale, spacing scale, breakpoints, hover/focus states and motion do not exist in the source and are authored — each with its own D-numberSeparates fact from proposal; the user approves only the proposals
D4Perimeterv0.1.0 covers the six pages of the PDF, Italian only: Home, Presse per gallette, Azienda, Macchinari accessori, Servizi, Fiere ed eventiThe PDF's contents
D5NavigationThe header keeps all seven menu entries, Contatti included, although no Contatti page exists in this version. The link is inert in the preview and listed under open issues in `DESIGN.md`The header is one site-wide pattern and must match the material; inventing a page is out of scope
D6PhotographyPhotographs are cropped from the page screenshots at measured coordinates. They are page *content*, not system assets, so their resolution does not constrain the specOriginals are not available; preview fidelity is enough for approval
D7Leaf motif and iconsThe leaf motif is redrawn as clean, scalable SVG and becomes a versioned system asset — it recurs in the title band, the bulleted lists and as background decoration. Logo and the pictogram sets (6 Green Puff features, 4 "valori") are cropped as PNG until the originals arriveA decorative shape carried as a blurry crop cannot scale or take a token colour; a geometric motif can be rebuilt exactly
D8Type familyRoboto Condensed, and only two weights exist in this design: 400 and 700. Loaded as four static woff2 subsets (400/700 × latin/latin-ext, 69 KB in all) beside the user's `RobotoCondensed-Regular.ttf` in `sources/fonts/`. Apache 2.0, web use allowedThe user supplied the family; the match is verified against the raster, not assumed — three body lines imply 23.46 / 23.47 / 22.87 px from their advances, and the stem runs across `MISCELATORI` match weight 700 run for run (400 and 500 are a pixel light, 900 a pixel heavy). Evidence in `sources/fonts/README.md`. The first rebuild guessed 500 for the button label, the `SCOPRI` label and the Green Puff feature labels; stem width disproves it (0.15 em against 0.098 for a 500), and correcting them also corrected their size and tracking — 37px / 0.04em / 45px line pitch, not 34px / 0.08em
D9Reference viewportThe rebuild reproduces the PDF 1:1 at a 1920px viewport: every size in the spec is the size measured on the raster. At 1920 that means body 23.5px, headings ~53px, small text 19.6px, footer 25.6px, body line-height 37pxThe capture scale of the screenshots is unknowable from a raster — body lands on no round CSS size at any plausible device-pixel ratio (15.6 at 1.5, 18.8 at 1.25), which is itself a sign the original type is fluid (vw-based). Anchoring at the one viewport we can actually verify keeps `validate.py`'s original-vs-rebuilt height check meaningful
D10Fluid scaleType and section padding are authored as fluid values anchored at 1920 (the measured values) and at 390 (authored, D3). Nothing between those two anchors is evidenceThe source has no responsive information at all; the curve has to be invented, so it is invented once, explicitly, and reviewed at checkpoint 2
D11White on yellowKept as it is. `#FFFFFF` on `#E9A901` is 2.07:1 and stays on the title band, the yellow content bands, the "I valori" list and the section tabs. It is recorded in `DESIGN.md` as a brand choice taken with the number in hand, not as an oversightThe user's decision at checkpoint 1. The pairing is the brand's voice on every page; changing it would change the look of the whole site. The consequence is explicit: the site is not AA on those surfaces, and `validate.py` must report the failure rather than hide it (see the open item on the waiver)
D12HeaderOne header with a real sticky state. The resting header (logo 416×152) is the system's header; a `header--compact` state (logo 296×108, the menu unchanged, the 0.71 ratio measured on the five inner pages) shrinks it on scroll. Both live in `spec/styles.json`, and the preview implements the behaviourThe user's decision at checkpoint 1. The two logo sizes in the PDF are one header caught in two states, not two headers
D12aWhere the sticky livesThe rebuild stays at rest: no scroll behaviour, no JS. `capture.mjs` scrolls every page before it reads the computed styles, so a shrinking header would be measured in its compact state and the inventory would record the wrong headerThe rebuild is a measuring instrument (D2); behaviour belongs to the spec and the preview, not to the ruler
D13Hard line breaksThe rebuild keeps the `<br>` inside paragraphs (five in one paragraph of *Presse per gallette*); `pages/*.json` drops them. The measure of a line is set by the patternThe user's decision at checkpoint 1. Keeping them in the rebuild preserves the height comparison against the PDF; keeping them in the content would stop the text reflowing
D14Green Puff badge`#80BA27` with white text (2.34:1) is kept unchanged: it is a product mark with two uses in the site, not an interface colour. Recorded in `DESIGN.md` beside D11The user's decision at checkpoint 1
D16Contrast declarationsThe two failing pairs are declared as what they are: `text`, with their real ratios. `validate.py` will report them red and `validation.json` will not pass, so `dso.py release` refuses v0.1.0 until someone changes the colour or the validator. No waiver, no `decor` relabelling, no omissionThe user's decision. The validator must keep saying what is true; a release that stays open is a visible consequence, and a far better one than a report that says "ok" about a 2.07:1 pairing. The waiver in `core/validate.py` stays a proposal, not a change
D15Font filesTwo static weights, not one variable file. Four subsets (400/700 × latin/latin-ext) replace the variable woff2 the first rebuild usedThe user's decision. The design needs exactly two weights (D8), for which the static files are *smaller* — 69 KB against 85 KB — and a static `@font-face` carries a single `font-weight`, so `inventory.py`'s family check works and the false `font-not-loaded` disappears. The findings went from 13 to 12 with no change to shared `core/`
D17CalibrationThree values the rebuild had invented were re-measured on the raster before any token was written, and the capture was re-run: the rule beside a category tab is `#d6d6d6` 2px on the tab's bottom edge (not `#e3e3e3` 1px centred), the button's border is `#c2c2c2` with no shadow (not `#d9d9d9` plus a soft shadow), and the `\` of the language switch is `#7a7a7a` (not `#999999`)A guess that reaches the token file becomes a fact about the client's brand. Re-measuring removed a whole colour cluster and the entire shadow scale, both of which were mine
D18One inkAll text is `#2e2d2b`. `#333333` (menu) merges into it at ΔE00 3.10; `#1d1d1b` disappears, because the rebuild had taken it from the logo's wordmark while the PDF's headings measure `#2e2d2b`The design looked like it carried three near-blacks and carries one
D19Type scale14 measured sizes collapse to 9 steps, worst deviation 1px, and the scale keeps the design's own irregular ratios instead of being forced onto a modular scaleForcing a ratio would move text by several px and spend the 1:1 fidelity D9 buys. The irregularity is a fact about the design, recorded rather than smoothed away
D20No shadowsThe system has no shadow at all; `radius.pill` is the only radius, because every measured radius was exactly half its element's heightMeasured (D17). The single shadow in the inventory was invented by the rebuild
D22Control borderThe spec uses `#949494` (3.03:1) where the raster measures `#c2c2c2` (1.78:1). The rebuild keeps the measured value: a design correction belongs in the spec, never in the instrument that measuresThe user's decision at checkpoint 2. Unlike D11 and D14 this hairline is not a brand signature, and it is the button's only boundary
D21Muted text`#757575` instead of the measured `#7a7a7a`: one step darker, 4.29:1 → 4.61:1The only correction made for accessibility in this checkpoint, and it costs nothing visually. Contrast on *brand* surfaces is a different matter, settled by D11 and D14
D23Focus and hoverAuthored, because no screenshot can show them: focus is a 3px accent-yellow ring at 2px offset, turning to ink on the yellow and green surfaces; hover inverts the button (yellow fill, ink leaf) and puts a yellow rule under a menu item. Links carry no underline — measured on the raster, in the menu and in the footer alikeThe raster cannot answer, so the system has to. The yellow is already the design's signal (rules, leaves, tabs), and the inverted button reuses a pairing the design already contains. Proposed at checkpoint 3; the user may reverse it there
D24Decorative leaves`.decor` is a system component: colour and behaviour in the spec, position and size passed by the patternThe leaf at four scales is the design's most recurring device. Where a decoration sits belongs to the band, not to the shape
D25Page title band`.page-title` is a component, not a pattern: one slot, a measured height of 113px, identical on all six pagesA pattern with a single slot repeated six times is a component
D26Green PuffThe badge carries a wordmark image, not a text label: the lettering is a wide, heavy face that is not Roboto Condensed (cap height implies 28.7px, glyph widths imply 38.9 — a 1.4 ratio no tracking can explain). It is a product logo and ships as an asset, extracted with alpha from the rasterMeasured. Two consequences: the type scale no longer carries a "badge" size that never existed, and the contrast question changes shape — a logotype is outside WCAG 1.4.3, so what remains to declare is the pill against the page (2.34:1, `ui`, kept by D14)
D27No cardThis design has no card component. The blocks that look like cards carry no box, border, padding or background: they are compositions of `.heading-rule`, text and `.btn` inside a stackNaming a component that does not exist invites the next author to put padding inside it, and the system has none to give
D28The leaf assetThe mask travels as a data URI inside the CSS (307 characters) rather than as a file referenceA relative `url()` does not survive the move into WordPress global styles, and the preview resolves assets from the capture, not from the spec
D29Rules under features and valuesThey are separators between stacked items, not underlines on a label. `.feature--divided` and `.value--divided` carry them; the last item of a column has noneThe yellow rules sit at y 1384 and 1570 between the three rows of each column, 335 × 8, aligned with the label column. The white one sits once, at y 2366, between the two rows of values, 334 × 12
D30The button is not a pillRadius 20px, measured on the corner curve, which runs 18–20px along each edge. The label sits low in the box, 17px above the bottom edge. The leaf is mirrored: its long axis runs bottom-left to top-rightThe left edge reaches its final x only 18px below the top edge; a pill on a 75px box would take 37. The leaf's principal axis measures 135° against the base leaf's 45°
D31h1`h1` is the largest step (4xl, 52px); `.page-title__text` overrides it to 2xl (40px) for its bandA heading element must keep the document's hierarchy. The band is a component and states its own exception, instead of the element being bent to the one place it appears in
D32Sizes correctedPerson name 40 (was 37), role 30 (was 27); event title 52 (was 45), subtitle 37 (was 30); all of them tight-leaded. The heading rule sits 4px under the line box (was 12). The list leaf is 33px at the top of the first line (was 30px, pushed down 8). The navigation gap is 72pxCap heights and glyph advances: name 40.0/42.4, role 30.0/31.5, event title 53.3/54.8, subtitle 33.9/37.0. Heading ink bottom 2561 → rule 2577. Leaf 3950–3983 against the line's ink 3965–3986. Menu items 72–85px apart
D33Menu hoverThe hover rule is drawn with `text-decoration` at a 6px offset, not as a box-shadow on the line boxAuthored (D23). The box-shadow sat on the bottom of the 54px row, far from the text; the underline follows the glyphs
D34One pattern, many sections`band-split` carries 17 of the site's sections, with options for surface, padding, media side and whether the heading keeps its rule. Nine of the fifteen patterns are single-useThe site is four pages of alternating text-and-media bands plus three pages that are each their own thing. Inventing shared patterns for the second group would mean options nobody would ever combine
D35The hero inside the page modelThe hero keeps the content column like every other band and its photograph covers the band through `position: absolute; inset: 0`A full-bleed image otherwise forces the negative margins rule 9 forbids, and `screenshot.mjs` flagged seven misalignments per page. After the change: zero, on six pages at three viewports
D36`.pair`A project layout class states the two columns the four approach blocks, the four values and the six features sit inThe core grid auto-fits on a minimum and offers `--3`, `--4`, `--5` but no `--2`; with four blocks it made four columns. The class took the drift on Azienda from −16% to −2.7%
D37Decorative placementA pattern places a leaf by naming one of four placements (`--left-top` and the rest), never by coordinatesPatterns carry global classes only. The leaves land near, not on, the PDF's positions, and that is the price
D38Section padding from the instrument`extract_pages.py` reads the padding the rebuild carries on each section and picks the nearest step of the spacing scaleThe alternative was one default for every band, which flattened the page's rhythm. The step is chosen from a measurement rather than by eye, and the residual drift is the system's own rhythm
D39How close is close enoughThe spec composes the six pages to a mean 3.9% of the PDF's height (−0.1% to +8.8%), against the rebuild's 0.3%. Accepted as the cost of a systemA design system whose sections breathe on a thirteen-step scale cannot also carry a page builder's 23, 57, 103 and 188px paddings. Pixel parity would mean per-section values in the content, which is not a system
D40The three brand coloursThe client's own values replace the measured ones: yellow `#E9A901` → `#EAA900`, cream `#FAECC9` → `#FAECC8`, ink `#2E2D2B` → `#2E2D2C`. The rebuild keeps the measured values: a correction belongs in the spec, never in the instrument that measures (D22)A raster carries JPEG noise; the brand carries the truth. The differences are ΔE00 under 1, so nothing else moves: contrast goes 2.07 → 2.06 on the pair D11 keeps, and every other check is unchanged
D41Typography in the previewThe shared preview now shows every scale step in capitals as well as sentence case, prints each fluid step's two endpoints (its size at the smallest and at the largest viewport of the project's own range), and carries a viewport slider from 100px to the fluid maximum plus 500 that moves the fluid steps exactly as the clamp wouldThis design is uppercase almost everywhere, and a scale judged only in sentence case hides what the pages actually look like. The endpoints and the slider answer the question the clamp otherwise leaves open: what the type does *between* the two anchors. It is a change to shared `core/`, so it reaches every project — the other three were re-rendered as a smoke test and all still produce 10/10 sections
D42LeadingTwo steps only: `tight` 1.0 for display type (headings, the title band, the menu, every label and tab — measured between 1.0 and 1.09) and `normal` 1.2 for everything that runs over more than one line. The measured 1.22, 1.34, 1.57, 1.6 and 1.84 all collapse into `normal`Running text is the one that moves: the raster has it at 1.57 (37px of pitch at 23.5px) and the system now sets 1.2, so paragraphs read tighter than the PDF does. It is a deliberate simplification of the system, not a measurement — stated here because the pages will look denser than the source
D43TrackingTwo steps only: `normal` 0 and `wide` 0.1em. The 0.02 measured on the button label and the 0.04 on the feature labels both become 0; 0.1 stays for the page-title band, the one place the design spaces its lettersA feature label loses about 1.5px per character of air. The band keeps its character
D44The three widths`layout.content` 1584 → 1366, `layout.content-header` 1334 → 1366 (the header now shares the content column exactly), `layout.page` 3168 → 3500 (no longer derived as twice the content width). Authored, not measuredThree collapse thresholds had been set against the old column and had to follow it, or the design folded: `.pair` 680 → 560 per column (two columns plus the 96px gap need 1216px, and 680 each made every pair one column), `layout.grid-min-wide` 460 → 400 (three across a 1366px band are 418px once the gutter and the gaps are out, so the measured 460 collapsed the product row to two), `layout.sidebar-narrow` 304 → 288 — the design measures both, and at a 667px card a 304px picture leaves the text less than the half-card the sidebar primitive insists on, so the picture stacked. With all three followed, mean drift against the PDF goes 3.9% → 3.5%
D45Elements the design does not haveh4, h5 and h6 are removed from the spec. The design has one heading size and three levels; the three extra levels were defined speculatively at 45, 37 and 30px. The shared preview now shows only the heading levels the spec sizes, and names the missing ones in the block's caption instead of drawing a specimen for eachA page that needs a fourth level is a question for the client, not a size to invent. 104 styles → 101. The core change improves every project: htc, which also sizes only h1–h3, stops showing three "not defined by the spec" specimens
D46The Elements sliderThe viewport slider is now shared, and the Elements block has one too. It works differently there by necessity: the element specimens take their sizes from the project's own stylesheet, so the slider redefines the fluid tokens on the specimen scope rather than the elements — the same arithmetic the `clamp()` doesOne control, two modes (`samples`, `vars`), one script. Reaches every project; the other three were re-rendered and all still produce 10/10 sections
D47The heading scaleh1 = `font.size.lg` (30px), weight regular, tracking wide — the title band's own voice, with `<strong>` for the word or two that are bold. h2 = `4xl` (52px), the largest type in the system. h3 = `3xl` (45px), one step below. `.page-title__text` is deleted: it said exactly this and said it twiceThe h1 is authored, not measured: the band measures 40px (`2xl`) in the PDF, and the system now sets 30. The band is a fixed 113px, so nothing moves — the sentence simply sits smaller inside it than the source shows. Say the word and it goes back to `2xl`: one token reference
D48The current menu itemIt was already marked (`.is-current`, set by the composer from the page's slug); it is now told apart from a hover — bold over a 12px yellow rule, where a hover draws the same rule at 8px and no bold — and the composer adds `aria-current="page"`Authored: the PDF's menu marks nothing, so this is an addition in the same family as hover and focus (D23), not a measurement. The attribute is what a screen reader announces; the class is only for the eye
D49Specimens that were proseSix styles were being drawn in the preview as a paragraph of sample text — `.masthead__logo-link`, `.btn:hover .btn__leaf`, the four `.decor--*` colours and `.value__label`. The shared preview's rule was "every property is typographic ⇒ it is a text component", and `color` alone or `line-height` alone passed it. A style now has to name the text (`font-size`, `font-weight`, `font-family`, `text-transform`, …) to countFixed in `core/`, so every project gets it. Each of the six also gained a real example: the logo inside its link, the hovered button with its ink leaf, the four leaves each on the surface it is meant for, and the value label beside its pictogram
D50`space.3xl+`, `4xl+`, `5xl+`, `6xl+`Renamed. The ladder is continuous: `2xs` 4 · `xs` 8 · `s` 12 · `m` 16 · `l` 20 · `xl` 24 · `2xl` 32 · `3xl` 40 · `4xl` 48 · `5xl` 56 · `6xl` 64 · `7xl` 72 · `8xl` 88 · `9xl` 96 · `10xl` 112 · `11xl` 128 · `12xl` 192`. Seventeen measured values, seventeen names, no `+`They were not decoration: two of them were broken. `+` is not allowed in a CSS identifier, so `--space-4xl+: 4rem` was an invalid declaration the browser dropped — and the compiler's own reference pattern does not match a name with a `+` either, so `{space.4xl+}` was copied into the stylesheet as text. `.section--pad-s` and `.section--pad-l` therefore had no padding at all and fell back to the default band. `3xl+` and `5xl+` were used by nothing
D51The site menu, revertedD48 is withdrawn. The current page keeps the single yellow rule it shared with a hover; no bold, no thicker rule. `aria-current` stays, because it is not a style: it is what a screen reader announces, and nothing on screen changesThe request was about the preview's own fixed bar, not the site's menu. That bar now marks the section being read — bold, full-strength label, the accent rule — in both navigations, the pills in the hero and the sticky bar. It is a `core/` change, so every project's preview has it
D52One logo size`.masthead__logo` is always 296px (`layout.logo`). The compact state no longer resizes itThe PDF shows the mark at 416px on the home and at 296 on the inner pages — where the capture simply caught the header already scrolled. A logo that changes size while you read is an effect, not a rule. The home's header is therefore 46px shorter than the source, which is most of the drift that moved below
D53Only the menu is pinnedThe header stays in the flow and scrolls away with the page. On scroll, only the menu band leaves it and fixes to the top of the window. A new element, `.masthead__navband`, is the full-width band that pins; `.masthead__bar` stays the 1366px column inside it, so the white runs edge to edge while the menu keeps its placeMeasured, not guessed: at rest the header is 182px and the first section starts at 182; after scrolling 700px the band is fixed at 0, 55px tall with its hairline below, and the first section still starts at 182 — the padding under the header replaces exactly what the band took with it, so nothing jumps. The hairline moves from above the menu to below it, since at the top of the window a rule above the menu separates nothing
D54`layout.logo``clamp(150px, 14vw, 210px)`, stated as CSS. The mark grows with the window, stops at 210px from 1500px up, and never falls below 150It is not the system's fluid shape: a fluid token interpolates between the project's two viewports (390 → 1920) and would have compiled to `clamp(150px, 134.7px + 3.92vw, 210px)`, which is a different curve. So the token says the value outright, and `core/` gained the one rule that allows it: a dimension written as a string travels verbatim. Measured widths: 150 at 390 and 900, 179 at 1280, 210 from 1500 up
D55No fixed heights in the header`.masthead__bar` loses `height`, `.masthead` loses its padding, and each row carries its own: `xs` (8px) on `.masthead__top`, `s` (12px) on `.masthead__navband`. `layout.nav-bar` is deleted — a height that is never set needs no tokenThe menu band lands at 54px at 1920 — the measured value, now arrived at rather than asserted (30px of menu + 2×12), and free to grow with a longer menu or a larger text size. The header is 147px at 1920, 132 at 1280, 184 at 390
D56Where the header width is stated`.masthead` carries `max-width: {layout.content-header}` and centres itself. `.masthead__top` drops its own copy of that width, and the two rows simply inherit itThe width was stated twice and could have drifted apart. The header is now 1366px wide and centred; the menu band inside it is 1366 at rest and goes to the full window only when it pins, which is exactly the one moment it has to
D57The hairlineMoved from `.masthead__bar` to `.masthead__navband`The rule opens the band, so it belongs to the band — and that is what keeps it spanning the whole header when the band pins and goes full width. On the column it would have stopped at the column's edges. When pinned the top rule is made transparent and a bottom one takes over: at the top of the window a rule above the menu separates nothing
D58The menu's type`.site-nav` is `font.size.xs` (20px) and boldAuthored: the raster measures the menu at 21.5px regular. 20px bold reads as a navigation instead of as running text that happens to sit in the header, and it holds up at the smaller sizes the menu reaches on a narrow window
D59The header's first row`.masthead__top` aligns its three parts to the bottom of the rowThe contact lines and the social marks now sit on the foot of the logo, whatever height the logo's clamp gives it
D60The language switch`.site-nav__lang` is xs and bold, like the menu (D58)It shares the line with the menu and now shares its voice
D61The gutter`max(32px, 7vw)`, and it is now a minimum margin instead of a tax on the column: `.section` is `max-width: calc(content + 2 × gutter)` with the gutter as padding, and `.section--wide` pads by `max(gutter, (100% − content) / 2)`Two things had to change together, and the second is the interesting one. `vw`, not `%`: the same token pads a plain section (whose box is the column) and a full-bleed band (whose box is the page), and a percentage resolves against each in turn — the two columns would stop aligning, which is the one thing component rule 9 forbids. Minimum, not addition: the old formula subtracted the gutter from the column, invisible at 24px but 268px at 1920 once the gutter grew. The column fell to 1097, the pair and the product grid dropped below their thresholds, and two pages grew by a fifth before the formula was corrected
D62When the band pins`.is-pinned`, set by the script when the menu band's top reaches the top of the window — not on the first pixel of scroll. The old `.is-scrolled` stays at `scrollY > 8` for the projects that use itMeasured on Azienda: at 0 the band sits at 93, at 50 it has scrolled naturally to 43, at 92 it fixes at 0 and stays. The header scrolls away with the page, the band arrives at the top, and there is nothing to see in between
D63The current menu itemThe underline is replaced by the leaf: accent yellow, one em tall, to the left of the label. A hover keeps its underline, so the two signals are different in kind, not in degreeThe design's own motif does the marking. It is a `::before` over the same mask every other leaf in the system uses — no extra markup, and the composer still sets nothing but `.is-current` and `aria-current`. Measured at 1920: label 20px, leaf 19.98 × 19.98, `#EAA900`, `text-decoration: none`. One more portability note (a pseudo-element with `content`), which the system already carries for `.tab-row` and `.leaf-list`
D64The title band's heightNo height. The band is as tall as what it holds plus `space.2xl` above and below. `layout.title-band` (113px) is deleted — a height that is never set needs no tokenIt is the leaf that sets the height, not the text. At 1920 the band is 116px = max(text 30, leaf 52) + 2×32, against the 113 measured in the PDF — three pixels, by a route that now survives a longer title: at 390 the sentence wraps to two lines, the text becomes 57px and the band opens to 121 instead of clipping. If you want the band to follow the text literally, the leaf has to come down to the text's height (1em, as in D63), and the band would land at 94px — further from the raster, so I left the leaf at its measured 52
D65HoverThe leaf marks the hover too. The underline is gone from the menu entirelyThe leaf sits in the line box of every item, transparent until it is wanted, so hovering colours a shape that is already there. Measured: the label's left edge is at 410px at rest and at 410px hovered — the pointer never pushes what it is pointing at. Hover and the current page now look the same; the current one is also announced by `aria-current`, which is the part that was never a style
D66The menu row`.site-nav__list` is left-aligned with a 32px column gap (`space.2xl`), and a 16px row gap for when it wrapsIt no longer spreads across the header: it starts where the content starts. The 72px gap the raster measures was an artefact of six items spread over 1334px
D67The title bandPadding `space.m` (16px) instead of `2xl`The band is 84px at 1024 and above (the 52px leaf plus 2×16; the leaf still sets it, D64), and 89px at 390 where the sentence wraps to two lines. Against the PDF's 113 that is 29px per page, on all six
D68The gutter`max(2rem, 4vw)`In `rem`, so the margin follows the reader's own text size, not only the window's. Columns, all three kinds on the same one: 326 / 828 / 1178 / 1366 at 390 / 900 / 1280 / 1920 — below the reference width the column is now wider than it was at 7vw (1178 against 1101 at 1280)
D69The mobile menuCollapses at 1024px instead of 900Measured at the edge: the toggle is in at 1024 and out at 1025. A tablet in portrait now gets the menu behind the button, which is where six uppercase items at 20px bold belong
D70The menu bar`.masthead__bar` gets a 48px column gap (`space.4xl`)3rem, which is also the gap the compact state wants between the language switch and the menu button — so that distance is stated once
D71The leafMoves to the right of the label and is mirrored on its horizontal axis (`scaleY(-1)`)The shape is a lens on a diagonal, so mirroring turns its axis the other way, as the two leaves of the title band already do. Hover and current still differ from the rest only by the leaf's colour, and the label still does not move: measured, left edge 410px at rest and 410px hovered
D72The breakpoint1200px (was 1024)Measured at the edge: compact at 1200, full at 1201
D73The open menu`.site-nav__panel` reads at `font.size.sm`17px at 390, 22 at the top of the range, against the 15–20 of the bar. A menu you have opened on purpose is the page's content for that moment
D74The compact headerBelow the breakpoint the header is a different shape, not a squeezed one: `.masthead__top` is hidden — contacts and social marks with it — the logo moves into the menu band on the left, and the language switch and the menu button sit together on the right, 48px apartMeasured at 390: logo 32→180, language 228→266, button 314→358, gap exactly 48px, the whole row inside the 326px column. The pattern carries a second logo link in the band, shown only here; `.is-mobile` now lands on the header as well as on the navigation (a `core/` change), so the header lays itself out from the breakpoint the pattern already declares, with no media query of its own and no `:has()`
D75The open menu's box`.site-nav__panel` opens with `space.6xl` (64px) above the list and `space.m` belowThe panel's top edge is at 68px and the first item at 132px: the menu does not start under the button that opened it
D76HoverThe hovered leaf is cream, the current page's stays accent yellowMeasured: `rgb(250, 236, 200)` under the pointer, `rgb(234, 169, 0)` on the page being read. D65 had made the two identical; colour tells them apart again, and the hover is the quieter of the two
D77The switch below 500pxIt leaves the bar and appears at the end of the open menu, under the last itemA stylesheet cannot carry an element from one box to another — the panel is inside the navigation, the bar's copy beside it — so the pattern carries two, and a media query shows one or the other. It needed a `core/` change: a navigation's panel could hold nothing but the list, and now takes the pattern's own nodes after it (`after`), built like any others. Measured: in the panel at 390 and 499, in the bar at 500 and above. The menu button keeps the right-hand end, taking over the auto margin the switch used to carry
D78The title band`text-align: center`At 390 the sentence wraps to three lines and they stack centred, not ragged against the leaf on their left
D79The header's bottom line`.masthead__contact` and `.masthead__social` carry `space.xs` of padding belowThe row sits on its bottom edge (D59); the padding is what lifts the last contact line and the three marks clear of the logo's foot
D80The buttonNo width, no height. Padding `xs` above and below, `m` left, `s` right — less on the side the leaf is on, because the leaf carries its own air. Radius 15pxMeasured: 233 × 66 at 1920, 179 × 52 at 390, against the raster's 244 × 76. The radius is authored against the measurement: the curve runs 18–20px in the PDF, and `radius.m` now says 15. Radii coverage falls from 100% to 29% — the one number in the validation report that this decision pays for, and it is the right kind of failure: the system says what it chose, and the report says it differs from the source
D81The leaf in the button`2em` instead of 47px48px beside a 24px label, 34px beside a 17px one: it grows with what it sits next to. The selector had to become `.btn .btn__leaf`, because `.leaf` sets a width of its own and is declared later — same specificity, and source order was winning
D82The section under the title band`.page-title + .section`: 64px above, 40px belowEvery page opens the same way, so the rule is a position rather than an option in six pages' content
D83The seamIts height is `space.xs` (8px), not `border.underline` (4px)It is a shape with a size, not a rule under text. It doubles in thickness, and the token it uses now says what it is
D84The colophon`font.size.xs` (20px, was `md` 27)The footer stops competing with the page
D85The leaf's bodyThe short axis grows by 30%, the long one does not move. The motif is a lens: two circular arcs between the same two points, and how far they bow apart is the arc's radius. Keeping the chord and widening the bow means a smaller radius, not a bigger one: 57 → 48.09 in the 64-unit boxOne change reaches every leaf in the system — the title band's pair, the list bullets, the one in the button, the four decorative sizes, the mark on the menu — because they are all the same mask over `currentColor`. Measured on the rendered pixels, not on the arithmetic: long axis 78.97 → 78.97, short axis 31.90 → 41.41, a ratio of 1.298. The ink goes from 42.5% to 56.4% of its box; the box itself is unchanged, so nothing around a leaf moves
D86The buttonPadding-right `xs`, gap `2xs`, content on the bottom, leaf 1.7emMeasured at 1920: 210 × 59, padding 8/8/8/16, gap 4, leaf 41 × 41. The label keeps the low line the raster shows and the leaf rises beside it, instead of both being centred on a box that no longer has a height of its own
D87The leaf beside a titleStated as a height of 2em with no width: `height: 2em`, `width: auto`, `font-size: 1em`48px at 1920, 42 at 1280, 34 at 390 — it scales with the type around it instead of holding the 52 it measured at one viewport. The width comes from the square aspect ratio `.leaf` already carries. `width: auto` is the working part: `.leaf` sets a width, and leaving one out of `.leaf--mark` would have left that one standing
D88The seamAstride the join: half on the band above, half on the band below, by a negative margin of half its height at each end, and raised one layer so the band that follows does not paint over itMeasured on the home: the two bands meet at y 1228 and the seam runs 1224 → 1232. The row it lives in takes no vertical space at all
D89The footer`.colophon` carries the page's guttersIts three lines stop touching the window's edge on a phone
D90Leaves on a product band`band-split` takes a list of leaves instead of one on/off switch: each item names its colour, size and placement (`{"variant": ["white", "xl", "inset-right-top"]}`). The home's band declares fourMeasured on the PDF's own pixels, in a band 1920 × 942: white 749 × 805 at x 854, y 62 · accent 211 × 211 at x 1390, y 626 · white 471 × 387 at x 140, y 496 · accent 107 × 107 at x 322, y 366. The four sizes the spec already carried — `xl`, `l`, `m`, `s` — turn out to be exactly these four leaves: they were defined at checkpoint 2 and never emitted, the gap noted at D45
D91Who sets a band's heightA new option, `height: mediatext`. With `text`, the media column stretches and the picture fills it without adding to itThe home's product band goes from 942px in the raster to 559: it is now the text plus its padding, and the machine fits that height instead of setting it. That is the whole of the home's extra drift
D92The splitA new option: the text half takes three fifths of the row and 7rem of air on the left, above and belowMeasured at 1920: row 1366, text 845px (61.9%) from x 798, picture half 489. The switcher gives both halves the same basis and lets them grow, so 3 against 2 is 60/40 above the threshold and one column below it. `max-width: none` had to come with it, and the selector had to carry the column's own class: `.measure` is on that column and is declared later, so 54ch was holding it to 47% of the row however hard it was told to grow — the same trap as the leaf in the button (D81)
D93Whose background the leaves areThe leaves belong to the two halves, not to the band: `leavesText` sits in the text column, `leavesMedia` in the picture'sEach column is a stacking context with no background of its own, so a leaf one layer down is behind that column's words and still above the band. The placements now resolve against the half they are in, which is what makes them read as its background
D94The pictureRuns a quarter of its column's width past the right edge, over the gap between the halvesMeasured: column 489, picture 611, overflow 122px = 25.0%
D95`.btn` and `.label``font.size.sm`22px at 1920, 17 at 390
D96The size of an inset leafA leaf inside a half of a band is a fraction of that half: `height` in per cent, `width: auto`, `aspect-ratio: 1` — the placement class states its size, overriding `--xl`/`--l`/`--m`/`--s`, and is placed from the far edge. The big white leaf is 116% tall, mirrored, offset −12% / −14%; the accent one under the text 30%, mirrored, from the middle; the white leaf under the machine 65%, tilted −20°, 7% below the foot; the small accent one 15%Measured at 1920 against halves 627 wide and 652–836 tall: 756, 196, 424 (543 as a box once rotated) and 125 across. The composition now holds at 1920, 1280 and 390 instead of being four fixed sizes that only fitted one band
D97The two halvesEqual width. Both grow at 2.5, and the 7rem of air between them is the row's column gap, not the text's paddingWith the air as padding the halves measured 723 against 611 at 1920 — exactly the 112px of padding apart. Flex hands out the *free* space by `flex-grow` and adds an item's padding outside its share, so equal grow cannot give equal boxes while one of them is padded. As a gap the air lands where it belongs, between the halves, and both come out 627 at 1920, 533 at 1280, 326 at 390
D98Which half is in frontThe picture's half sits a layer above the text'sSo a machine that runs past the edge of its column crosses over the text instead of disappearing beneath it
D99The machine`width: auto`, anchored by `right: -12%`: the box is the picture, hanging 12% of its column past the right edgeMeasured 12.0% at all three widths. Two things had to come with it. The column needs `aspect-ratio: 3 / 4`, because once the switcher has stacked the halves the column is on its own line with nothing in its flow: it measured 326 × 0 at 390 and the machine was gone from the phone. And the picture must load eagerly — a box sized by the picture is 0 × 0 until it loads, a zero-area box never intersects the viewport, so a lazy one would never load at all. The composer now takes `"eager": true` on an image for exactly this case
D100The compositionTuned on the rendered band, against the raster: the big white leaf to `left: -35%`, `top: -12%`; the accent leaf under the text to `left: 45%`; the leaf under the machine to `right: 24%`, `bottom: -5%`, `rotate(348deg)`; the small accent leaf to `top: 30%`Measured at 1920 on halves 627 wide and 652 tall: 756, 196, 424 and 98 across, as before — only the placements moved
D101The size of the Green Puff badgeThe badge is sized against the label above it: it carries `font.size.sm`, the step SCOPRI is set in, and all three of its measures are in em of that step — wordmark `7.75em`, pill `9.39em x 1.97em`. The wordmark is two and a half times the width of SCOPRI, by requestMeasured: the label is a constant 3.10em wide at every viewport (68px at 1920, 64 at 1500, 62 at 1280), so 2.5 x 3.10 = 7.75em holds the ratio wherever the type goes. The wordmark drops 212 -> 170px at 1920 and the ratio reads 2.500 at 1920, 1700, 1500 and 900, 2.48–2.49 where the fluid font size lands on a fraction. In pixels the badge was the only thing in the band that did not breathe: 257 x 54 from 1920 down to 1280 while the label shrank under it. `.badge--lg` follows in em and is pixel-identical at 1920 (408 x 88, wordmark 334)
D102What sizes the leaves of the text halfThe two leaves behind the text are a fraction of the half's width, not its height: big white `120.6%`, accent `31.3%`, `height: auto`, `aspect-ratio: 1`. The big one is anchored on the centre of its half and offset by a fraction of itself — `top: 50%; transform: translateY(-53.44%)` — so nothing in the composition is measured against a dimension the text does not answer toThis revises D96 for the text half only. D96's rule — height in per cent — is right for the machine's half, where the machine is itself 100% of the column and leaves and product scale together. It is wrong here: the text is as wide as the column and only as tall as the type makes it. Sized by height the leaf lost 756 -> 718px between 1920 and 1500 while the text kept all of its 627, and the second line of the heading crossed out of the white onto the cream. Measured after: the leaf is 756 x 756 at 1920, 1700 and 1500 alike, and the text sits in it the same way at all three (the heading's longest line clears the leaf's box by the same 90px, 14.4% of the half, which stays 14.3% at 1366 and 1280 where the column itself narrows). Below the threshold the leaf and the text shrink together
D103What it costMean drift 8.7%, unchanged; the home -10.0%, 10px lower than beforeThe band is 10px shorter because the badge is 11px shorter. Validation is unchanged: integrity 0, colours 100%, font sizes 100%, spacing 96%, layout 0 issues in 18
D104Where the band changes1200px — the width the header already changes shape at (D72, D74) — and 977px, where the switcher stacks the two halves977 is not a number anyone chose: the row is `0.92 × viewport` once the gutter is `4vw`, and `layout.threshold` is 900px, so the switcher flips at the first width whose row is under 900. Measured: 978 side by side, 977 stacked
D105The row below 977A column, stated: `flex-direction: column`, `nowrap`, `align-items: stretch`, and the children's basis back to `auto`The switcher already reached this arrangement by wrapping, but wrapping leaves the row's machinery in place: the basis `calc((900px - 100%) * 999)` would resolve against the height in a column, and `--middle`'s centring would shrink each half to its content. Saying column means the three things that only make sense across a row stop applying instead of being worked around
D106The big white leaf, stacked135% of its half's height, width auto, square — height-driven again, like every other inset leaf (D96), and centred on its half both ways456px at 977, 432 at 768, 389 at 390, against the 1573 / 1232 / 571 that covering the words cost. It reads as a leaf again
D107Where the band turns978px, not 977977 was never chosen: it is where the switcher's own arithmetic flips, the first width whose row falls under `layout.threshold` once the gutter is `4vw`. Since D105 the media query states the column outright, so the media query is the breakpoint and the switcher no longer decides. Measured: 979 side by side with the picture out of the flow, 978 stacked with it back in
D108The product photograph`puffing-machine.png` replaces `press-green-puff.png`A cleaner cut-out of the same press, 400 x 701 against 452 x 800, and without the grey shadow the old one carried under its wheels — which on the cream band read as dirt rather than as ground. The band is unchanged at 1920 (769px, the text sets the height, D91) and shorter where the picture sets it: 1322 → 1223 at 978, 1049 → 1044 at 390. Drift unmoved at 8.7%
D109The white leaf of the picture's half, stacked45% of its half's height, anchored to the half's left edge (`left: 0`, `right: auto`) instead of measured in from the rightAt 65% and `right: 24%` it sat squarely behind a picture that now fills its half, and read as a white smear under the machine rather than as a mark. Measured at 978: the leaf is clear of the machine's left edge and is drawn as a leaf; at 390 it stays behind the picture's transparent margin, which is all the room a phone has
D110The dead and the overridden leaf classes (proposal 4 of the D101-D109 review, applied)`.decor--left-bottom`, `.decor--xl` and `.decor--s` are dropped from `styles.json`, and the four leaves of the product band stop naming a size in `pages/index.json`Counted on the composed pages, by `class` attribute and not by the inlined stylesheet: `--left-bottom` 0 uses, `--xl` 1, `--s` 1, `--l` 3, `--m` 3. The single use of `--xl` and of `--s` is the product band, where the `--inset-*` placement sets width *and* height and throws the declared size away — so once the content stops naming it, both classes have no user left. 120 → 117 styles. `--l` and `--m` stay: two of their three uses come from the patterns (`moulds` declares `decor--l`, the feature grid `decor--m`) with an edge placement that sets coordinates only, so there the size is the only thing that gives the leaf a box
D111The home's product band (proposal 1 of the D101-D109 review, approved)Lifted out of `band-split` into its own pattern, `product-band`, with no optionsIt was the only user of `split: text` and `height: text`; the four leaf slots, nine of the styles and seven of the media queries served it and nothing else, while eleven other `band-split` sections used none of it. The composition is now the pattern: cream surface, short padding, picture first, text half inset in its white leaf, picture half as tall as the text. 16 patterns instead of 15, and the composed markup is byte-identical — the options only ever baked classes into the tree, so baking them in by hand changes the spec and not the page
D112The top padding of the product band144px (`space.12xl`, a new step) while the halves are side by side; 96px (`space.9xl`) once they stack`.section--pad-s` gives 64, and the band is the one section where that is wrong: the white leaf the text is written on runs past the top of the band, so the words have to start lower than the band does or they sit on the leaf's edge. Measured against the source on the text half only — the half where the words are, because the machine's dark panels are not type: the PDF puts the first letter of the heading 271px below the band's top edge; at 64 the render put it at 184, at 144 it puts it at 264. Seven pixels from the raster
D113The two cards of `card-row`They are one row, not two blocks: the taller card sets the height, both pictures fill it, both buttons sit on the same line at the bottomThe grid already made the two cells equally tall; nothing used it. The picture now takes `width: 100%; height: 100%; object-fit: cover` inside `.card-row__media`, and the button's cluster carries `l-push`, the stack primitive's own "push me to the bottom" (`margin-top: auto`) — no new rule for the button at all. Measured at 1920: both pictures 288 x 408, both buttons' baseline at the same y. Before: 288x408 and 288x316, buttons 90px apart
D114The button of a cardAt the right end of its column, with `space.2xl` of air above it that it will not give upIt was at the left, and `l-push` had left it flush against the paragraph whenever the two columns were nearly the same height — 5px of air on the taller card. `justify-content: flex-end` and a `padding-top` that the auto margin cannot eat. The source puts both buttons at the right of their column, ending within 7px of the text's right edge
D115The button of a card, againNo padding and no margin above it: it follows the paragraph like any other line of the stackD113 had pushed it to the floor of the card with `l-push` and D114 had added 32px above it. Both are gone. The cost, stated plainly: the two buttons no longer end on the same line — 2472 and 2533 at 1920 — because the two paragraphs are not the same length and nothing is left to absorb the difference. The pictures are still the same height, 288 x 408
D116Where a product row folds978px, `layout.break-mid`, not 1024`layout.break-product-row` is deleted the day after it was added: the site already had a breakpoint there and did not need a second one 46px away. Back to 94 tokens. One column below `break-narrow` stays
D117The vertical gutter of both grids+2rem: 32 → 64 (`space.6xl`), in the card row and in the product rowsThe gutter was 64 across and 32 down. It is now 64 both ways: two rows of squares need as much air between them as the squares have beside them, and a stacked card row needs the same
D118When the picture is a squareOnly in state B, when the sidebar is stacked`aspect-ratio: 1` with `align-self: flex-start` is the square; `align-self: stretch` in the two windows where the picture sits beside the text undoes it. Those windows are `min-width: {layout.break-card}` and `max-width: {layout.break-mid}`, and the state in between is exactly the one where the sidebar wraps. D117 had made it square everywhere, which is wrong beside the text
D119The picture itself`width: auto; height: auto; aspect-ratio: 1`, the client's own three linesThe square moves from the box to the picture. Beside the text the flex box still stretches it to the card (288 x 403 at 1920, the ratio ignored, which is right there); stacked, nothing stretches it and it is square to the pixel — 612, 557, 428
D120`.card-row__media > img`No `object-fit`, as askedThe picture is drawn into whatever box it is given, which is `fill`. Flagged, not argued: at 1280 the box is a 557 square and the mixer is 288 x 408, so it is painted 42% wider than it is. At 1920 the box is 288 x 403 against a natural 288 x 408 and nothing shows. One line puts `contain` back if the stretch is not wanted
D121`.heading-rule::after``max-width: 100%` beside its declared 334pxThe 334 is a width, not a promise. Measured: in the home cards the heading column is 331 at 1920 and the rule was sticking out by three pixels; at 390 the column is 326 and it stuck out by eight. It now stops at the heading. Where the column is wider — 579 on a single-column card at 978 — the full 334 still draws, so the measured width is untouched wherever it fits
D122`.tab`20rem wide, label 2rem in from the left, nothing on the right`size.rule.tab` goes 481 → 320. Chosen against the source, which measures the tab 481 wide with the label 86 in; the tab is now a third narrower and the label sits where the padding scale puts it. Measured: 320 x 53 at 1920, and `min(…, 100%)` still holds it inside a 280px window at 216
D123`.product-row > img` below 978`width: auto` beside the `aspect-ratio: auto` of D120The picture is drawn at its own size instead of being blown up to the cell: on two rows a galletta is 280 x 180, not 418 x 418. Anything wider than its cell is still held by the `max-width: 100%` every image on the site carries — at 978 two of the three gallette hit it and sit at 418
D124`.product-row`10% of padding left and rightThe products stop against the tab's own edges and move into the middle of the column, which is how the source draws them. Measured at 1920: the row is 1366 wide, so 137 each side, and the first galletta starts at x 414 instead of 277; three cells of 322 instead of 413. Below 978 the cells become narrower than the pictures' own size, so `max-width: 100%` takes over again and a galletta goes from 280 to 222 at 700
D125What was wrongThe four blocks ran the full width of the band and the leaves ran under themThe source holds them in the middle of the page and gives the margins to the leaves. The render had 635px columns from edge to edge and two cream leaves 420 wide sitting behind the words
D126`.pair`55% of the band, 75% below `break-narrow`A width now, not a cap: 751px at 1920 against the ~825 the source draws, and 75% on a phone so the text is not a ribbon. `max-width: {layout.content-narrow}` goes, it could never bind under 55%
D127`.tab--auto``width: unset`, 3rem of padding on each sideIt hugs its text again, which is what it did before D126 pinned it to `min(20rem, 100%)`. Measured: 450 x 53 at 1920 with the label on one line and its middle on the box's middle; 362 at 978, 307 at 390. The wrap D126 flagged is gone
D128The six leavesTwo containers, `.decor-cluster--left` and `--right`, one per sideEach group is a box with a width and a ratio — 20.9% of the band at 318/448 on the left, 20% at 304/382 on the right — and the three leaves inside it are placed in percentages of that box, not of the section. The group is one drawing that scales; the arrangement cannot come apart
D129`.decor-cluster--left`Taller — 318 / 510 — one gutter in from the edge, `top: 14%`It no longer hangs off the left of the band: the group stands inside the page's own margin at every width. Measured left edge: 77, 48, 39, 32, 32 as the window goes 1920, 1200, 978, 700, 390
D130The two groups below `break-mid`To the far ends of the band — left 5% from the top, right 5% from the bottom — and `max(330px, 40%)` wideOnce the four blocks stack the band is tall and empty at the edges, and a group holding 20% of a phone is a smudge. Measured: 391 wide at 978, 330 at 700 and at 390, against 318 and 251 above the breakpoint. The arrangement inside each group is untouched — still `-10,22 100x5914,0 38x2431,80 29x18` and `0,17 100x8360,2 40x3240,0 20x16` at every width
D131`.pair--values`75% of the band, 6rem between the columns, 0 between the rowsEach value carries its own white rule underneath, and a gap on top of a rule would read as two separate bands of two. Measured 1025 at 1920, 675 at 978, 245 at 390
D132`.value--divided`No padding, no background: the line is an `::after` bar, 75% of the cell, held to its right edgeIt was a `linear-gradient` painted 108px in from the left at a fixed 334px. Now it is a shape with a width, so it follows the cell: 348 of a 464px cell at 1920, and its left end lands just past the pictogram, which is where the source puts it
D133The last row of valuesNo separator under itA separator that runs under the last row is an underline, and the source draws none there. Two columns, so the rule is `:nth-last-child(-n+2)`; one column below `break-mid`, where the second-to-last cell gets its line back and only `:last-child` goes without. Measured: rules on 1 and 2 at 1920, on 1, 2 and 3 at 978 and 390
D134`.value--divided::after`Half the cell, set 3em in from the left, hanging 0.6rem below it; `right` dropped3em of the value's own type is 120px at 1920, which is where the word starts, so the bar sits under the word and never under the pictogram — the source's alignment, now stated as a rule instead of as a 108px offset in a background image. Measured 232 of a 464px cell at 1920, 337 at 978, 122 on a phone
D135A portraitSquare, `max(150px, 35%)` of the row, `object-fit: cover`204 at 1920, 194 at 978, 150 on a phone. Cropped rather than fitted: a head and shoulders survives a crop, and the two photographs in the source are not the same shape
D136`.pair--people``width: auto` at every width, and 5rem above it while the two are side by sideAgainst the auto side margins `.pair` carries, `auto` means *as wide as the two of them, centred*: 1315 at 1920, where 90% was 1229. The 5rem is in a `min-width` query, so a stacked page does not inherit it
D137`.person:first-child``justify-content: flex-end` only at `break-mid` and aboveOnce the grid is a single column there is no second person to close towards, so the first one stays at the left like everything else on the page. Measured offset of the portrait inside its cell: 85px at 1920, 19 at 979, 0 at 390
D138What the source actually drawsAn ear of wheat on each edge — a stalk, two yellow leaves and a black one, growing upwards — not two black leaves thrown at opposite cornersThe render had `decor--ink decor--m decor--left-top` at the top left and `--right-bottom` at the bottom right: two marks of the same size on a diagonal, which is a different drawing
D139The three leaves of an ear`rotate(90deg)` eachThey were growing up and to the right; turned, they open up and to the left on the left ear, which is the way the source draws them, and the `scaleX(-1)` on the group keeps the right one its mirror. The boxes do not move: a square box rotated a quarter turn is the same square
D140The section`section--wide`: full bleedThe ears now reach the edge of the page, not of the band — x 0 and x 1738 at 1920, where before they were pinned to 200 and 1575. That is where the source draws them, and it is what the band was missing. The ear also grows with the section: 182 x 667 at 1920 against 144 x 528, because 9.5% of 1920 is more than 9.5% of 1520
D141`.badge--lg`14 x 2.5em, wordmark 10em acrossDown from 18.55 x 4 with a 15.18em wordmark. Chosen against the raster, which is where those three figures came from. Still in em of the badge's own type, so the three move together: 308 x 55 at 1920, 265 x 47 at 978, 238 x 42 on a phone. It now reads as a label over the features rather than as a second headline
D142`.pair--features`The same declarations as `.pair--values`75% of the band, 6rem across, 1rem down, the whole width once it stacks. It was 72% with the default 4rem/5rem gutters. Measured: 1025 wide at 1920, cells of 464
D143`.pair--features``grid-auto-rows: 1fr` and `width: auto`Every cell now measures 314 x 133 at 1920, where they were 464 x 89 and 464 x 133 by turns: *Struttura e pannellatura completa* sets on three lines and the other five take its height, which is what puts the separators of the two columns on the same line. `auto` against `.pair`'s auto side margins makes the block as wide as its six labels and centred — 725 of the 1920 band, where 75% was 1025
D144`.feature--divided::after`100% of the cell, still 2.5em in from its leftIt runs 2.5em past the cell's right edge, into the 6rem column gap: 314 long on a 314 cell at 1920. The values band keeps its half-width bar — its cells are much wider than their single words, and this grid's are not
D145A cream `band-split`The `alt` surface now names the row as well: `band-row--alt`An option that only painted a background now also says which row it is, so the one section built this way can carry its own figures without a selector reaching in from the section. `product-band` left `band-split` in D111, so nothing else answers to it
D146`.decor--inset-right-top``height: 135%` of the text column, square, 4rem to its left and centred on it — instead of 120.6% of its width at a hand-fitted `translateY(-53.44%)`A width-based figure could not serve two columns of different shapes. Now both are covered: 866 x 866 behind the home's two paragraphs, 727 x 727 behind Presse's four, where before it was 708 and left the last lines outside it. The 72px D145 flagged are closed, and the home is unchanged in composition — only bigger, and still clipped by the band's right edge, as the source clips it
D147`.band-row--alt``flex-wrap: nowrap` at `break-mid` and above`l-switcher` breaks on its own threshold, which the 6rem gutter and the 3rem padding of D145 had pulled above the breakpoint: the row was stacking while the rest of the page was still side by side. Measured: two halves of 410 at 1100 and 354 at 979, where before they had already gone one under the other
D148The rowCentred both ways: `align-items: center` on the row, each picture centred in its own cellThe three cells were top-aligned, so a 332px plate and a 102px block of figures started on the same line and ended nowhere near each other. The source centres them on one another
D149Where the air above a row livesOn the picture, not on the row: `.mould` loses its top padding, `.mould__media` gains 1.5remThe rule is a border on the media cell, so padding above it on the row pushed the rule down and left the picture tight against it. Now the 1.5rem sits under the rule, where it belongs
D150`.mould__spec`2.5rem above, 1rem belowIt still stretches to the row, less those margins: 300 tall in a 356 row, so the yellow block of an even row stands clear of the two rules instead of running into them
D151`.mould`A declared grid: three columns at `break-mid` and above, two below, with the figures spanning the whole of the second row`l-grid--3` and its intrinsic arithmetic are gone — the same move as D115 and D118, and the end of the `--l-grid-gap` trap D150 ran into. Measured: three cells of 423 at 1920 and 268 at 979; at 978 and 390 the two pictures hold the first row and the figures take 900 and 326 of the second
D152Below `break-mid`Every row's figures look the sameThe yellow fill of the even rows is switched off: stacked, the figures are a caption under two pictures, and a block of brand yellow spanning the full width would read as a different kind of row rather than as decoration. Measured: three filled and three empty at 1920, six empty at 978 and 390
D153The figuresThe label of each line in capitals, the value as written: `FORMATO: Ø 90 mm`, `CAPACITÀ: fino a 2700 pz/h``text-transform: uppercase` was shouting the measurements too, and `Ø 90 MM` and `PZ/H` are not how units are written. The label is now marked as a label in the content — `<b>Formato:</b> Ø 90 mm` — and the capitals are a rule in the stylesheet rather than a spelling in the data. Eighteen labels across six rows
D154Three columns`1fr 1.5fr 1fr`: the figures are half as wide again as a pictureMeasured 363 / 544 / 363 at 1920 and 230 / 345 / 230 at 979, where the three were equal. The yellow block of an even row has the width its three lines want, and the two pictures stop floating in cells wider than they are
D155Under `break-tiny`The figures go back between the two pictures`grid-column` and `grid-row` are returned to `auto`, so the placement is dropped and the markup's own order — plate, figures, product — is the order on the page. Measured at 360: plate at y 2573, figures at 2912, product at 3003. The row no longer needs a rule for where its parts go, because in one column there is nothing to decide
D156`.mould__media``width: 100%``l-center` carries auto side margins, and auto margins on a grid item stop the stretch, so the cell was shrinking to its picture: 360 and 300 inside columns of 363, with the rule under each one short by that much and the two rules of a row different lengths. Now both measure 363 at 1920, 230 at 979, 450 at 978 — the column, every time. The same mechanism as `.pair` in D135, met for the third time
D157The five machine picturesReplaced with the client's: 600 x 600 JPEG on white, against cut-outs of 692 x 496, 496 x 452, 368 x 520, 632 x 372 and 467 x 469`machine-aromatizzatore`, `-essiccatore`, `-mixer`, `-nastro` and `-pulitore`. Four were PNGs with transparency and are now JPEGs, so the references in `pages/macchinari-accessori.json` and the `band-split` sample move from `.png` to `.jpg`
D158`font.size.base``clamp(1rem, 0.9235rem + 0.3137vw, 1.3rem)` — fluid 16 → 20.8px, against 17 → 24Measured: 20.8 at 1920, 18.8 at 1280, 16 on a phone. Everything written in em follows it, because the body is where em starts: the badge, the tabs, a value's 2em pictogram, the 2.5em offset of a separator. Chosen against a source that measures 23.5 and 24 twice
D159`.decor--inset-right-top`Restored to what D145 left it: 120.6% of the column's width, `left: -35%`, `translateY(-53.44%)`, and 190% at `top: 30%` once stackedThat figure was measured against the raster for the home's band, and D146 overwrote it to make one class serve two sections. The home is back to its own shape: 756 x 756 at 1920, the lens tip clear of the band's right edge instead of clipped flat against it
D160`.mould:first-of-type` below `break-mid`No top borderAbove the breakpoint the rule lives on the media cells and the first row's cells already went without one (D148); stacked, the rule moved onto the row itself (D153) and the exemption did not move with it, so the table opened with a line under nothing. Measured, six rows: `0 4 4 4 4 4` on the rows at 978 and 390 and on the media cells at 1920, the other collection `0` throughout
D161`.band-row--alt` → `.band-row--wide`, reached by a new `gutters` option6rem between the halves, 1rem by 3rem around them, no wrap while side by side, picture first and text centred once stacked — all of it now a choice any section can makeIt was tied to `surface: alt`, which is a colour. *Miscelatori per cereali* is a white band and wanted the same spacing, so the option moved out of the surface and onto its own name. Two sections carry it: the cream band on Presse and the mixers on Macchinari. Measured on the mixers: row 1366 x 632, gutter 96, padding 16/48
D162The two halves of a wide band rowEqual: `flex-basis: 0`, `flex-grow: 1`, and `max-inline-size: none`587 and 587 at 1920, where they were 554 and 620. Three things had to go for that: `.measure` caps the text at 54ch, which is 554px at the running size, and a half that is capped is not a half; a flex item will not shrink under its own content, so the 600px photograph held its side wider; and the heading's rule is 334px wide, which on a 230px phone column kept the text from narrowing — `min-inline-size: 0` at every width settles the last two
D163`font.size.sm` and `font.size.xs`Brought under the running text: sm 17–22 → 15–19, xs 15–20 → 13–17D158 took `base` down to 16–20.8 and left `sm` above it, which the validator called what it was. Both ends are ordered now — 13 < 15 < 16 on a phone, 17 < 19 < 20.8 at 1920 — and since every size is linear between the same two viewports, ordering the ends orders the whole range. Integrity back to 0 errors, the first clean run since D158
D164The running text on *Macchinari accessori*Seven paragraphs lose their `<br>`They were carrying the line breaks of the 1920px mock-up into a column that is 587px wide, so a line ended in the middle of a sentence and the next began under it: *"…di produzione di gallette / di cereali soffiati…"*. The text now wraps where its column ends
D165The leaf showing through the machineThe five pictures get their white background knocked out and go back to PNG with alphaD161 had blended the picture over the leaf because a JPEG carries an opaque white rectangle; multiply does hide the white, but it also tints everything light in the machine, so the leaf read as lying on it. The background is removed by flooding from the four edges through pixels whose darkest channel is 238 or more, so only the connected background goes and the machine's own whites stay: 58–73% of each picture removed, no holes. `mix-blend-mode` is deleted — 143 styles
D166`.decor--inset-left-bottom`80% of its column's height, up from 65Measured: 557 x 557 behind the mixer on Macchinari, in a column of 587. Two sections carry the class, so the home's product band grew with it — its white leaf goes 398 to 582 in a 613 column. It still reads as the leaf the press stands on, and the cream still shows around it, but the change was not asked for and is stated here: a placement of its own would keep the two apart, the way D159 did for the leaf behind a text column
D167The stacked text column of a wide row3rem under itMeasured 48px at 390 and 0 above the breakpoint. Stacked, the text ended against the next band; now it has the same air under it that the band split puts between its own parts
D168`.band-row--tight`2rem between its lines, as between its columnsMeasured 32 / 32 at 1920 and at 390, against the wide row's 96 / 0
D169*Essiccatori* and *Nastri trasportatori*Formatted like *Miscelatori per cereali*: `pad: 0` on the section and a cream leaf behind the machineBoth already had `gutters: wide` from D165, so the two things missing were the padding and the leaf. Measured: padding 0 top and bottom on all three, leaf 557 x 557 in each
D170The five picturesReplaced with the client's own cut-outsPNGs with alpha, cropped to the machine: 593 x 398, 524 x 454, 402 x 551, 564 x 341, 435 x 470, against the 600 x 600 squares D165 produced by flooding the white. The file names already ended in `.png`, so nothing in the pages or the spec changed — only the bytes, in the capture and in the preview alike
D171`.decor--inset-left-bottom`110% of the column's height, held to its right edge, uprightIt was 80%, inset 24% and tilted 12 degrees. Measured now: 606 behind the mixer, 433 behind the flavourer
D172`.decor--inset-left-bottom` upright90% of the column's height, 23% in from its right edgeMeasured 496 behind the mixer and 355 behind the flavourer, where 110% and `right: 0` gave 606 and 433
D173The upright leaf below `break-mid``left: auto` beside the `right: auto` it already hadWith neither offset stated it falls back to the static position, where the flow would have left it. Measured at 390: 189 in a column of 230 behind the mixer, 93 behind the flavourer
D174The picture of a wide band row below `break-mid``width: auto; height: 400px`, as askedWhere the column is wide enough it is exact: at 978 the mixer measures 292 x 400 at its own ratio, at 600 the cleaner 370 x 400 at its own
D175The home's leaf, stacked`left: 0`, where the five on Macchinari fall back to the flow`.band-row--inset .decor--inset-left-bottom`: the product band is a composition of its own since D111, and its leaf was placed against the raster long before the machines had one. The row's own name is what tells them apart, so neither needs a variant of its own. Measured at 390: the home's leaf at 0 of its column, Macchinari's at −5
D176`.l-switcher--middle` below `break-mid`Its text column ranges its lines on the middle and lays its own children on that axis; the rule under a heading leaves the flow and centres itselfA row whose halves are centred on each other should centre their contents once they stack: a full-width text column ranged left leaves the yellow rule starting at an edge the eye has no reason to look at. Measured at 390: `text-align: center`, `align-items: center`, and the rule 230 x 8 at `left: 115` — the middle of its column
D177The rule added in D176Reverted`.l-switcher--middle` no longer centres its stacked text column, and the rule under a heading stays in the flow. Measured at 390: `text-align: start`, `align-items: normal`, the rule `position: static` at 230 x 8 under its heading, and the heading back to two lines at 230 x 68 where centring had given 157 x 56. 149 → 148 styles, portability notes 12 → 11
D178The rule withdrawn in D177Back, narrowed: `.l-switcher--middle:not(.band-row--tight)`Stacked, a middle row centres its text column and lets the rule under a heading leave the flow — every row except the tight one. Measured at 390 across the seven rows of Macchinari: `center` and `absolute` on six, `start` and `static` on the tight one. At 1920 all seven read `start` and `static`, as before
D179`.section > .section__content.band-row--inset` below `break-mid`1rem between its halves, against the 5rem a section's content carries everywhere elseThe two halves are one picture and one block of words about it; stacked they read as one thing. Measured: 16px at 390, 80 at 1920. The selector names the home's row because `section__content` is shared by four patterns and the figure belongs to this one
D180`.heading-rule`The heading hugs its words (`width: fit-content`, `position: relative`) and the rule is 100% of them, out of the flowIt was a declared 334px capped at the column — a figure that fitted the raster at one width and nothing else. Measured: 292 under *Sistemi di aspirazione fumi* at 1920, 157 at 390, each exactly its heading. `size.rule.heading` has no reader left and is deleted: 95 tokens
D181`.heading-rule::after`4px, `border.underline`The thinnest rule in the system, which is what a line under words has been since D135
D182`.heading-rule + p`75% of its column, down from 90
D183`.leaf-list`A stack of its own: flex, column, 0.5rem between items; each item a 2rem column for its leaf and its words ranged leftMeasured: `flex`, 8px, `32px 1fr`, `left` at 1920 and at 500. The left alignment is the point — D178 centres everything in a stacked middle row, and a list that centres has no left edge for the eye to follow
D184The leaf on *Pulitori / setacciatori*Translucent white, `#ffffff70`On a brand band a cream leaf is a second colour; a white one at 44% is the band itself, lightened. Declared as `color.surface.veil`, a mix of white at 0.44 — 94 tokens, and colour coverage stays 100% because it is a token and not a hex in a rule
D185The four machine bands on Macchinari2rem above and below, at every width, under a name that says soThey were on `pad: 0`, which stopped being true the moment D183 gave them 3em when stacked. The modifier scale makes room instead of stretching a name: the old `2xs` (24) becomes `3xs`, and `2xs` is the new 32, so the figures still climb — 24, 32, 40, 64. Measured at 1920, 500 and 399: 32 on the four bands, 24 on the three brand strips between them
D186`.pair--people`3rem above it, down from 5Measured 48px at every width
D187The three bands`gutters: wide`: halves of equal width, 6rem between them, 1rem by 3rem around themMeasured at 1920: 587 / 587 on all three
D188The three leaves on Servizi`behind-text-left` and `behind-text-right`, mirror images about the verticalMeasured against the source: the leaf behind *Consulenza* had its point down-left, the source puts it down-right. The two bands now answer each other across the page — left bleeds off the left with its point down-right, right bleeds off the right with its point down-left. Both are 708 x 708, and the home keeps `inset-right-top` with its own mirror untouched
D189The three bands on ServiziThe same height, the tallest setting itSections are siblings, so equal heights need a parent that says so: the page's `main` becomes a grid whose last three rows are `1fr`, and `1fr` rows in a grid of auto height all take the height of the tallest. Measured: 614 each at 1920, 740 at 1200, 739 at 978, where they were 373 / 506 / 614 and 348 / 589 / 740
D190Each band on ServiziA grid of one row, so the row fills the section's content box and the two halves centre in the whole of itMeasured at 1920: sections of 582, rows of 438, 502 and 438 — the content box exactly. The `l-switcher--middle` centring was already there; what it lacked was something to centre in
D191The running textEight paragraphs lose their `<br>` — the home's product band, Azienda's people, and all six on ServiziThe same reason as D164: they were the mock-up's line endings carried into a column of a different width. Titles keep theirs, and so do three kinds of content that only look like text — a fair's dates and city, a Green Puff feature label, and a mould's figures, each of which is two or three data on their own lines rather than a sentence that wrapped
D192The stacked text column of a Servizi bandAt least 21rem tall, its lines centred in that heightMeasured at 978 and 390: 336px under *Consulenza*, which asks for less, and 393 / 456 and 441 / 519 for the two that ask for more. Side by side nothing changes — 172, 394, 438 at 1920, `min-height: auto`. The three bands keep a family resemblance on a phone even when the shortest of them is four lines long
D193`+39 (0)11 4249644.` on Servizi`.nowrap` on the `<strong>` that already held itThe one utility class in the system, declared in D95 for exactly this — a registration number, a share capital, a telephone number. Measured at 1920, 978, 390 and 320: the number draws one line box at each, 165 to 127px wide. The colophon's three numbers have carried the class since the first build; the one in the body of a page had been missed
D194Its paragraphIts five hand-set lines restoredD191 took the `<br>` out of eight paragraphs, this one among them. Here the breaks are the composition: the words are written on a white leaf and the leaf was fitted to that shape, so the two are one drawing and the text is not running copy that happens to wrap
D195A stacked picture in a wide row`max-height: 400px` and `object-fit: contain`, with `height` goneThe distortion D174 flagged and D182 only half closed is over. Measured at 390, each ratio against its own: mixer 0.730 / 0.730, dryer 1.154 / 1.154, conveyor 1.654 / 1.654 where it had been 0.575, flavourer 1.490 / 1.490, the trasporto photograph 2.003 / 2.003. Nothing is stretched to reach the figure; what cannot be 400 tall is simply shorter
D196`.card-row__media > img`300px wideFlagged: its column is 288 wide — `layout.sidebar-narrow` — and `max-width: 100%` caps the picture there, so at 1920 it draws 288, not 300. The figure only takes effect once the card stacks, where the column is wider: 300 at 451. If 300 is wanted at every width, `sidebar-narrow` has to grow with it
D197The list of fairsA grid of three columns, each fair taking twoOdd fairs hold the first two, even ones the last two, so the empty column walks from one side of the page to the other. Measured at 1920: a band of 1366 in three tracks of 413, every fair 889 wide, the odd ones at x 0 and the even at x 477
D198`.card-row__media`No `aspect-ratio`: the picture carries the square now, not its boxMeasured at 1280: the picture 300 x 300 inside a column 557 wide, where before the box was a 557 square and the picture filled it. Beside the text the flex still stretches the picture — 288 x 395 at 1920
D199Each pictureA frame of its own ratio, the picture fitted inside: 4 by 5 for the first, 2 by 1 for the secondMeasured at 1920: 413 x 516 and 413 x 206, and 261 x 326 and 261 x 130 at 390. A stand photograph and a square logotype can now sit one under the other and still line up. Two things were needed to make the ratio win — `width: 100%`, because the media column centres its children rather than stretching them and a frame was as wide as its picture (600 against a column of 413), and `min-height: 0`, because a flex item will not go under its own content and the picture held the frame at 392 where the ratio asked for 206
D200The fairs' pictures`fiera-snackex.jpg` alone, one to a fairSix events, six pictures, all the same file in the 4 by 5 frame: 413 x 516 at 1920 and 261 x 326 at 390. Four of the six had two — a stand photograph and the fair's logotype — and two had one
D201The gridFive columns, 80% of the band, centred — at every width, not only stackedMeasured at 1920: 1093 of 1366 in five tracks of 167
D202A fair below `break-mid`Two columns, 1fr and 2fr: the picture narrow, the name and dates wideMeasured at 978: 224 and 448 in a grid of 720
D203The grid below `break-mid`The whole band, with 4rem between the fairs80% of a phone left too little for a picture and a name side by side. Measured: 900 of 900 at 978, 326 of 326 at 390

Site → system

What the site uses today and what the design system keeps.

Health of the site

  • 0 of 9 colours are near-duplicates (ΔE00 < 2), 2 pairs are similar (ΔE00 < 8)
  • 6 of 9 font sizes fall off a minor third scale (1.2, base 26px)
  • 39 of 72 spacing values miss the 4px grid (55 miss 8px); 35 are within 1px of another
  • 11 font-size declarations in px (they ignore the user's default size)

What the system keeps

Colors9 on the site (9 opaque, 1 written by hand)→ 8 primitives + 15 semantic
Font sizes9 (20, 22, 24, 26, 28, 30, 37, 40, 52px)→ 9 steps
Letter spacing4 distinct values→ 2 tokens
Spacing values54 distinct→ 18 steps
Radii2 distinct→ 3
Review findings11→ triaged in Decisions

Colors

Primitives define the palette; components only use the semantic names. Italic notes show which site values each token absorbs.

Foundation

Raw values. Named for what they are, never for where they are used.

Yellow 500--color-base-yellow-500#eaa900site: --yellow, 76 uses
#eaa900
Cream 100--color-base-cream-100#faecc8site: --cream
#faecc8
Green 500--color-base-green-500#80ba27site: --green
#80ba27
Ink 900--color-base-ink-900#2e2d2csite: #2e2d2c (brand value, corrected 2026-10-24), #1d1d1b, #333333
#2e2d2c
White--color-base-neutral-0#ffffffsite: --white
#ffffff
Neutral 200--color-base-neutral-200#d6d6d6site: measured: nav rule, chip rule
#d6d6d6
Neutral 300--color-base-neutral-300#949494site: measured #c2c2c2
#949494
Neutral 600--color-base-neutral-600#757575site: measured #7a7a7a
#757575

Semantic

Meaning. Each one points at a foundation value and is what components refer to.

Surface

Surface--color-surface-default→ neutral-0
#ffffff
Alternate surface--color-surface-alt→ cream-100
#faecc8
Brand surface--color-surface-brand→ yellow-500
#eaa900
Product surface--color-surface-product→ green-500
#80ba27
Inverse surface--color-surface-inverse→ ink-900
#2e2d2c
Veil--color-surface-veilneutral-0 · 44%
#ffffff70

Text

Text--color-text-default→ ink-900
#2e2d2c
Muted text--color-text-muted→ neutral-600
#757575
Muted text on dark--color-text-inverse-muted→ neutral-200
#d6d6d6
Inverse text--color-text-inverse→ neutral-0
#ffffff

Accent

Accent--color-accent-default→ yellow-500
#eaa900
Accent on brand--color-accent-on→ neutral-0
#ffffff

Border

Border--color-border-default→ neutral-200
#d6d6d6
Border on dark--color-border-inverse-strongneutral-0 · 40%
#ffffff66
Control border--color-border-control→ neutral-300
#949494

Contrast

WCAG 2.2, computed from the tokens: 4.5:1 for text, 3:1 for components; decor pairs are allowed only as decoration.

AaSample text at body size
text.default / surface.default13.74:1AAAtext
AaSample text at body size
text.default / surface.alt11.71:1AAAtext
AaSample text at body size
text.default / surface.brand6.66:1AAtext
AaSample text at body size
text.muted / surface.default4.61:1AAtext
AaSample text at body size
text.inverse / surface.brand2.06:1FAILtext
Component border
surface.product / surface.default2.34:1FAILui
Component border
border.control / surface.default3.03:1AAui
Underlines, rules, icons
accent.default / surface.default2.06:1decoration onlydecor
Underlines, rules, icons
accent.on / surface.brand2.06:1decoration onlydecor

Typography

Fluid sizes grow between 390 and 1920px and stay in rem, so they follow browser zoom. Each step is shown in every weight, in sentence case and in capitals; the slider moves the fluid steps the way the clamp would at that viewport width.

Families

AaABCDEFGHIJKLM abcdefghijklm 0123456789
Base family--font-family-bodyRoboto Condensed, Arial Narrow, sans-serif

Weights

Design system

Regular--font-weight-regular400site: measured by stem width

Design system

Bold--font-weight-bold700site: measured by stem width

Scale

1920pxFluid steps follow the slider the way the clamp would; fixed steps do not move.
Size 4XL (28–52)--font-size-4xl28–52px fluidsite: 52.4
min · 28px at 390pxAa
max · 52px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size 3XL (24–45)--font-size-3xl24–45px fluidsite: 44, 46
min · 24px at 390pxAa
max · 45px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size 2XL (22–40)--font-size-2xl22–40px fluidsite: 40, 40.5
min · 22px at 390pxAa
max · 40px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size XL (22–37)--font-size-xl22–37px fluidsite: 37
min · 22px at 390pxAa
max · 37px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size LG (19–30)--font-size-lg19–30px fluidsite: 30
min · 19px at 390pxAa
max · 30px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size MD (18–27)--font-size-md18–27px fluidsite: 26.1, 27.6, 28
min · 18px at 390pxAa
max · 27px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size BASE (16–20.8)--font-size-base16–20.8px fluidsite: 23.5, 24, 24 -> 1rem–1.3rem chosen (D158)
min · 16px at 390pxAa
max · 20.8px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size SM (15–19)--font-size-sm15–19px fluidsite: 21.5 -> 15–19 (D163)
min · 15px at 390pxAa
max · 19px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Size XS (13–17)--font-size-xs13–17px fluidsite: 19.6 -> 13–17 (D163)
min · 13px at 390pxAa
max · 17px at 1920pxAa
Base family · Regular

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Regular · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Base family · Bold · caps

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Leading

A design system turns decisions made once into named choices that every page can reuse, so the next page starts from the brand instead of from a blank screen.

Tight--font-leading-tight1.0site: 1.0, 1.05, 1.09

A design system turns decisions made once into named choices that every page can reuse, so the next page starts from the brand instead of from a blank screen.

Normal--font-leading-normal1.2site: 1.22, 1.34, 1.57, 1.6, 1.84

Tracking

SECTION LABEL

Normal--font-tracking-normal0emsite: 0, 0.02, 0.04

SECTION LABEL

Wide--font-tracking-wide0.1emsite: 0.1

Spacing & layout

Spacing

Space 2XS (4)--space-2xs4px
Space XS (8)--space-xs8px
Space S (12)--space-s12px
Space M (16)--space-m16px
Space L (20)--space-l20px
Space XL (24)--space-xl24px
Space 2XL (32)--space-2xl32px
Space 3XL (40)--space-3xl40px
Space 4XL (48)--space-4xl48px
Space 5XL (56)--space-5xl56px
Space 6XL (64)--space-6xl64px
Space 7XL (72)--space-7xl72px
Space 8XL (80)--space-8xl80px
Space 9XL (96)--space-9xl96px
Space 10XL (112)--space-10xl112px
Space 11XL (128)--space-11xl128px
Space 12XL (144)--space-12xl144pxsite: authored (D112)
Space 13XL (192)--space-13xl192px

Layout widths

Content max width--layout-content1366pxsite: 1584, 1600, 1560 -> 1366 (D44)
Header max width--layout-content-header1366pxsite: 1334, 1300 -> 1366 (D44)
Text max width--layout-content-text1188pxsite: 1188
Narrow max width--layout-content-narrow1016pxsite: 1016, 1000, 964
Page max width--layout-page3500pxsite: authored (D44)
Gutter--layout-guttermax(2rem, 4vw)site: 24 -> max(2rem, 4vw) (D61, D68)
Measure--layout-measure54chsite: 54, 54
Measure narrow--layout-measure-narrow38chsite: 38
Measure wide--layout-measure-wide89chsite: 89
Switcher threshold--layout-threshold900px
Breakpoint wide--layout-break-wide1200pxsite: authored (D74, D104)
Event breakpoint--layout-break-event750px
Breakpoint mid--layout-break-mid978pxsite: derived from threshold and gutter (D107)
Tiny breakpoint--layout-break-tiny400px
Person breakpoint--layout-break-person450px
Breakpoint narrow--layout-break-narrow499pxsite: authored (D73)
Card breakpoint--layout-break-card1461pxsite: derived: 1344 / 0.92
Sidebar--layout-sidebar480pxsite: 452, 467, 496
Sidebar narrow--layout-sidebar-narrow288pxsite: 288, 304 -> 288 (D44)
Sidebar wide--layout-sidebar-wide768pxsite: 752, 766, 768, 789
Grid minimum--layout-grid-min300pxsite: 340
Grid minimum wide--layout-grid-min-wide400pxsite: 460 -> 400 (D44)
Reel item--layout-reel-item260px
Reel item wide--layout-reel-item-wide320px
Logo width--layout-logoclamp(150px, 14vw, 210px)site: 416, 296 -> clamp (D54)
Header height--layout-header150–228px fluidsite: 228 on the home
Header compact--layout-header-compact183pxsite: 183 on the five inner pages
Hero--layout-hero280–601px fluidsite: 601
Hero home--layout-hero-home320–670px fluidsite: 670

Radii, shadows, motion, layers

Radii

Radius M--radius-m15pxsite: 20 -> 15 (D80)
Pill--radius-pill999pxsite: 27, 44
None--radius-none0px

Shadows

Components

Live examples rendered with the project's own element and component styles (spec/styles.json).

Elements

1920pxThe element specimens render at this viewport width: the slider redefines the fluid tokens on them, exactly as the clamp would.
Elementsh1, h2, h3, p, a, strong, small, :focus-visiblePlain HTML gets these styles without classes. h4, h5, h6 are not part of this design and are not shown.
h1

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

h2

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

h3

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

p

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next. With a link in the text, some strong words and small print. Press Tab to see the focus ring on the link.

Text components

.leadThe centred opening paragraph of the home and of Azienda: one step above running text, centred, on the wide measure.tokens: font.size.md, font.leading.normal, layout.measure-wide

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

.labelA short uppercase label that introduces what follows — SCOPRI above the Green Puff badge, SCOPRI LA TECNOLOGIA above the large one.tokens: font.size.sm, font.weight.bold, font.leading.tight

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

.text-bodyRunning text in a column: the default size on the default measure. Rendered here over several lines, which is the only way to judge leading and wrapping.tokens: font.size.base, font.leading.normal, layout.measure

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

.event__subtitleThe fair's own strapline, under its name and over the same rule (D199).tokens: font.size.xl, font.weight.bold, font.leading.tight

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

.event__datesDates and place, one line each, at the same 30px as the role on Azienda.tokens: font.size.lg, font.weight.bold, font.leading.normal

The quick brown fox jumps over the lazy dog, and a design system keeps every line, every step and every colour in step with the next.

Primitives

.l-stackVertical flow: children one under the other, separated by gap. Modifiers are named after the space token they use: --s, (default) m, --l, --xl, --2xl. A group that contains actions uses a stack two steps above the one of its text (text --l → with buttons --2xl; card content --s → with link --l). .l-push pushes a child and what follows to the end. --equal: every child as tall as the tallest (rows of a grid), e.g. a list of profiles.tokens: space.m
Eyebrow
Heading
Lead paragraph
.l-stack--stokens: space.s

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-stack--ltokens: space.l

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-stack--xltokens: space.xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-stack--2xltokens: space.2xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-stack--equal

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-clusterItems side by side that wrap when they run out of room (buttons, tags, links). Default gap space.s; --m space.l; --center, --end, --between align the row.tokens: space.s
OneTwoThreeFour
.l-cluster--mtokens: space.l

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-cluster--2xDouble the default gap (2 × space.s): groups of buttons and other actions.tokens: space.s

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-cluster--center

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-cluster--end

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-cluster--between

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-gridIntrinsic grid: as many columns as fit, each at least --l-grid-min (layout.grid-min). --wide: layout.grid-min-wide. Balanced rows (--5: 5, 3, 2 or 1 per row; --4: 4, 2 or 1; --3: 3, 2 or 1) switch on the grid's own width and stretch the items of a shorter last row. Pick by item count N: a row count c is fine when N mod c is 0, or c − 1 for odd N — 5 → --5; 4, 7, 8 → --4; 3, 6, 9 → --3 (checked by validate.py).tokens: layout.grid-min, space.m
Card
Card
Card
Card
Card
.l-grid--widetokens: layout.grid-min-wide

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-grid--sNarrower gutters between the cells (space.s).tokens: space.s

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-grid--2xlWider gutters between the cells (space.2xl, double the default space.m). Named after the space token, like the stack modifiers; --s is the narrow one.tokens: space.2xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-grid--4

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-grid--3

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-grid--5

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-grid--switchWith --3/--4/--5: the row collapses straight to one column at layout.threshold, with no two-column stage and no orphan last row -- the switcher's all-at-once rule for a grid. Use it when the grid sits beside switchers that stack at that width.tokens: layout.threshold

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-sidebarA narrow side (first child) next to a main side that takes the rest; they stack when the main side would drop under 50%. --right: the sidebar is the last child. --narrow / --wide set the sidebar width. --middle / --bottom align the two sides.tokens: space.2xl, space.xl, layout.sidebar
.l-sidebar--righttokens: layout.sidebar

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-sidebar--narrowtokens: layout.sidebar-narrow

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-sidebar--widetokens: layout.sidebar-wide

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-sidebar--middle

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-sidebar--bottom

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-sidebar--top

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-switcherEqual columns side by side, all stacked at once when the container is narrower than layout.threshold (never a 2+1 orphan). More than 4 children always stack. --middle / --top / --bottom align.tokens: space.2xl, space.xl, layout.threshold
Column
Column
.l-switcher--middle

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-switcher--top

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-switcher--bottom

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-centerA centered column no wider than the reading measure (layout.measure, in ch). --narrow / --wide pick another measure; --text also centers text and children.tokens: layout.measure
Centered column at the reading measure
.l-center--narrowtokens: layout.measure-narrow

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-center--widetokens: layout.measure-wide

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-center--text

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-measureLimit a block to the reading measure without centering it (left-aligned heads).tokens: layout.measure

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-boxEven padding, named after the space token: --s, (default) m, --l, --xl, --2xl, --3xl. Graduated: a box nested in another box (or in a coloured band, 4xl) uses at least one step less than its parent — checked by validate.py. Layout only. Modifiers set --l-box-space; --tall doubles the block padding (top/bottom = 2 × sides) for panels that need vertical air.tokens: space.m
l-box--xl
l-box--xl l-box--tall
.l-box--stokens: space.s

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-box--ltokens: space.l

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-box--xltokens: space.xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-box--2xltokens: space.2xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-box--3xltokens: space.3xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-box--tall

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-coverA block whose .l-cover__principal child sits in the vertical middle. On screens wider than 3:2 its height is max(content, 100svh); on narrower screens (4:3, square, portrait) the content sets the height. The aspect-ratio query is a documented exception to 'no media queries': it depends on the screen's shape, not on a width breakpoint. --short: 80svh instead of 100svh (same aspect-ratio condition).tokens: space.m
Top
Principal (centered)
.l-cover--short

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-frameMedia cropped to a fixed aspect ratio (default 16:9; --4x3, --1x1, --3x4). When stretched by a row (sidebar, switcher), it fills the row height instead.
4:3
.l-frame--4x3

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-frame--1x1

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-frame--3x4

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-reelA horizontal scrolling strip of equal items (layout.reel-item; --wide layout.reel-item-wide), for logos and carousels. Keyboard users scroll it once focused (tabindex="0" in the markup).tokens: space.m, space.s, layout.reel-item
Logo
Logo
Logo
Logo
Logo
Logo
.l-reel--widetokens: layout.reel-item-wide

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-imposterAn element centered over its positioned parent (overlays, badges on media); never larger than the parent minus space.m on each side. The parent needs position: relative (.l-relative).tokens: space.m

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-relative

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-iconAn icon sized to the cap height of the surrounding text; .l-with-icon aligns icon and label on the baseline with a 0.5em gap.

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-with-icon

Part of a larger component or pattern: shown with the patterns (phase 6).

.l-containerMakes an element a size container, so components inside can adapt to the room they get (container queries) instead of the viewport.

Part of a larger component or pattern: shown with the patterns (phase 6).

Actions

.btnThe only call to action in the system: a white rounded box with a hairline border and the leaf at its right end. **No width and no height** (D80): it is the label and the leaf plus its padding — 8px above and below, 16 on the left and 8 on the right, which is less on the side the leaf is on because the leaf carries its own air (D86). Label and leaf sit on the **bottom** of the box, 4px apart: the label keeps the low line the raster shows, and the leaf rises above it instead of pushing it off centre. Radius 15px (D80): the raster measures 20 on the corner curve, and this is a choice against it. Still not a pill. The hover inverts it (D23), and it restates the colour, because the element-level a:hover would otherwise turn the label yellow on yellow.tokens: space.2xs, space.xs, space.m, border.hairline, color.border.control, radius.m, color.surface.default, color.text.default, font.size.sm, font.weight.bold …
.btn .btn__leafThe leaf inside a button is **1.7em wide** (D81, D86), so it grows with the label instead of holding one measured size. The selector carries the button because `.leaf` sets a width of its own and is declared later: same specificity, and source order would have won (D81). It is mirrored: its long axis runs bottom-left to top-right, the opposite of the one in the title band. Measured on the shape's principal axis — 135 degrees in image coordinates, against 45 for the base leaf.tokens: color.accent.default

Part of a larger component or pattern: shown with the patterns (phase 6).

.btn:hover .btn__leafWhen the button inverts, the leaf turns to ink so it stays visible on the yellow (D23). The specimen is the hovered state itself, drawn as it ends up: yellow fill, ink label, ink leaf.tokens: color.text.default
.badgeThe Green Puff badge. It carries a wordmark **image**, not text: the lettering is a wide, heavy face that is not the system's (D26), so it is a product logo and ships as an asset. Its size is stated **against the label above it** (D101): the badge carries `font.size.sm`, the step the label is set in, and every measure is in em of that step, so the wordmark is always two and a half times the width of SCOPRI. In pixels it was the only thing in the band that did not breathe — 257 x 54 from 1920 down to 1280 while the label went 68 to 62.tokens: font.size.sm, radius.pill, color.surface.product
Green Puff
.badge--lgThe Green Puff badge at the head of its own page: **14 x 2.5em** with the wordmark 10em across (D141). Still in em of the badge's own type, so the three figures move together; the measured 18.55 x 4 it carried was the raster's, and this is a decision against it.

Part of a larger component or pattern: shown with the patterns (phase 6).

Lists

.leaf-listThe only list in the site: the four parts of the aromatizzatore, each marked with a leaf instead of a bullet. The leaf is 33px and sits at the top of the first line, not on its centre — measured: the leaf spans 3950-3983, the line's ink 3965-3986. The list is a stack of its own with 0.5rem between the items (D183); each item keeps a **2rem column for its leaf** and ranges its words **left even where the band centres everything** (D178), because a list that centres has no left edge to follow. The leaf keeps its 2rem column at every width (D198).tokens: space.xs, space.s, color.accent.default
  • Un sistema di dosatura di olio;
  • Un sistema di dosatura di aromi/sale;

Data

.featureOne of the six Green Puff features: a pictogram and a label on two or three lines, centred on each other. Built like `.value` since D142 — the grid with its 96px icon column is gone — and differing from it only in colour and in the size of its type.tokens: space.m

Ciclo di lavoro rapido

.feature__iconA feature's pictogram: 2em square (D142), like a value's.

Part of a larger component or pattern: shown with the patterns (phase 6).

.feature__label37px bold with 0.04em of tracking and a 45px line pitch — all three measured, and all three corrected from the first rebuild, which had guessed 34px/0.08em/weight 500. It carries no rule of its own: the yellow line is a separator — see .feature--divided.tokens: font.size.xl, font.weight.bold, font.tracking.normal, font.leading.normal

Part of a larger component or pattern: shown with the patterns (phase 6).

.feature--dividedThe yellow line under a feature is a **separator between stacked features**, not an underline, so the **last row carries none** (D138). It runs **from 2.5em in to the cell's right edge** — `calc(100% - 2.5em)` — 4px thick (D144, D146), with 0.5rem of air above and below the row — the values band keeps the half-width bar, because its cells are wider than their words and this grid's are not.tokens: space.xs, border.underline, color.accent.default, layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.mouldOne format of mould: the plate, the figures, the product, centred on each other. **Three declared columns above 978px — the figures half as wide again as a picture (D154) — two below, and one under `break-tiny`, where even two pictures side by side are too many**. In that last column the figures go back **between** the two pictures (D155): the placement is dropped and the markup's own order — plate, figures, product — is the order on the page, and once there are two the two pictures hold the first row and the figures take the whole of the second — a declared grid, like every other grid on the site since D115, instead of `l-grid--3` and its intrinsic arithmetic. The yellow rule that separates one row from the next runs under the pictures only, which is what the source draws, and the reason the rule lives on the two media cells. Stacked (D153) the rule goes back onto the **whole row**, and the first row goes without it (D160) the same way its media cells do above the breakpoint: with the two pictures side by side and the figures under them, a rule under the pictures alone would cut the row in half instead of closing it.tokens: space.4xl, space.xl, layout.break-mid, border.underline, color.accent.default, layout.break-tiny

Part of a larger component or pattern: shown with the patterns (phase 6).

.mould__mediaA picture in a mould row: it takes the **full height of the row** so that the two rules are on one line whatever the pictures measure, and the picture is centred inside it both ways (D148). The rule is a top border, and the first row has none. It carries the 1.5rem that used to sit on the row (D149), so the air belongs to the picture under the rule and not to the figures beside it. Stacked, the two pictures sit against each other with no gutter between them and 1rem of padding of their own (D152). It takes the **full width of its column** too (D156): `l-center` carries auto side margins, and auto margins on a grid item stop the stretch, so the cell was shrinking to its picture and the rule under it was shorter than the column.tokens: border.underline, color.accent.default, space.xl, layout.break-mid, space.m

Part of a larger component or pattern: shown with the patterns (phase 6).

.mould:first-of-type .mould__mediaA separator belongs between things, so the first row opens without one.

Part of a larger component or pattern: shown with the patterns (phase 6).

.mould__specThe middle column of a mould row: format, pieces per cycle, capacity. The **label of each line is in capitals and its value is not** (D153) — `Ø 90 mm` and `pz/h` are measurements and lose their meaning shouted — so the label is marked as a label in the content and the capitals are a rule here, not a spelling there. Centred in its cell and as tall as the row, less 2.5rem above and 1rem below.tokens: space.3xl, space.m, font.weight.bold, font.leading.normal, font.size.md, space.s
Formato: 80X80 mmGallette/ciclo: 6 (4 - 10 g)
.mould:nth-child(even) .mould__spec**Every other row** fills its figures with the brand yellow (D148): the alternation is decoration and no row means more than another, so it is counted in the stylesheet rather than declared row by row in the page. Below `break-mid` the alternation **stops** (D152): stacked, the figures are a caption under two pictures and every row reads the same.tokens: color.surface.brand, color.text.inverse, space.2xl, space.l, layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.valueOne of the four values on Azienda: an outlined pictogram and a word, on the yellow band.tokens: space.2xl, font.size.2xl, font.weight.bold
Innovazione
.value--dividedThe white line between the rows of values is a **separator**, not an underline, and a separator belongs **between** things: the cells of the **last row carry none** (D133). Two columns, so that is the last two cells; one column below `break-mid`, so there it is only the last one, and the second-to-last gets its line back. The line is an `::after` bar **half the cell wide, set 2.5em in from its left edge** (D142) — 3em of the value's own type, so it starts where the word does, under the word and never under the pictogram — and 4px thick. It hangs 0.6rem below the cell, into the row gap. The padding and the background gradient that used to carry it are gone; 1rem now sits between a pictogram and its word.tokens: space.m, border.underline, color.accent.on, layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.value imgA value's pictogram: **2em square** (D142), so it follows the word beside it, and `contain` keeps the outline drawing whole inside that square.

Part of a larger component or pattern: shown with the patterns (phase 6).

.value__labelThe single word beside a value's pictogram on Azienda — INNOVAZIONE, QUALITÀ, ESPERIENZA, KNOW-HOW. Size, weight and capitals come from `.value`; the label only pulls its line box tight, so a word that wraps does not push the pictogram off centre. It carries no rule of its own: the white line between the rows is `.value--divided` (D29).tokens: font.leading.tight
Know-how
.personA portrait with a name and a role, the text sitting on the portrait's bottom edge — measured: the role's last ink row is 3209, the portrait ends at 3221. Under `break-person` the portrait stands **above** the name rather than beside it (D196), and the two range left together: at 450px a 150px portrait leaves a name less room than it needs.tokens: space.2xl, layout.break-person

Giovanni Lavista

Direttore generale

.person:first-childThe first of the two is pushed to the **right of its cell** (D136) **while the two are side by side** (D137): the cell is wider than a person, so the slack moves to the left and the pair closes towards the middle of the band, the way the source draws it. Once the grid is one column there is no second person to close towards, and the person stays at the left like everything else on the page.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.person imgA portrait: **square**, `max(150px, 35%)` of the row (D135), cropped to fill rather than letterboxed — a head and shoulders survives a crop, and the two portraits in the source are not the same shape.

Part of a larger component or pattern: shown with the patterns (phase 6).

.person__nameA person's name: xl, with the yellow rule tight under it — 0.2rem of air and a 4px line (D135), the thinnest rule in the system, because here it underlines a name rather than separating two things.tokens: font.size.xl, font.weight.bold, font.leading.tight, border.underline, color.accent.default

Part of a larger component or pattern: shown with the patterns (phase 6).

.person__roleThe role under the name, md, 0.2rem under the rule (D135).tokens: font.size.md, font.weight.bold, font.leading.tight

Part of a larger component or pattern: shown with the patterns (phase 6).

.eventOne fair: its pictures and its name, in **two columns of equal width** centred on each other (D197). The pair takes two of the band's three columns and the third is left empty — which is what alternates down the page. Below `break-mid` it is **1fr and 2fr** (D202) — the picture in the narrow column, the fair's name and dates in the wide one — and every fair reads the same way: on one column there is no left and right to alternate between. Under `break-event` the two columns become one (D203), 2rem apart.tokens: space.4xl, layout.break-mid, layout.break-event, space.2xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.event--leftAn odd fair holds the **first two** columns of the three, and its words range left (D197). Stacked it takes the one column there is: a span of two in a grid of one invents the second, and the three fairs came out 163, 262 and 163 wide inside a 326px page.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.event--rightAn even fair holds the **last two** columns (D197), so the empty one walks to the other side of the page. Stacked it takes the one column there is: a span of two in a grid of one invents the second, and the three fairs came out 163, 262 and 163 wide inside a 326px page.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.event--right .event__bodyEvery other fair reads from the right, with its media on the other side. Measured: the odd rows right-align their text at x 1027, the even ones left-align it. Stacked, the mirror is dropped (D202).tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.event--right .event__mediaand its media moves after the text. Stacked, the mirror is dropped (D202).tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.event__mediaThe pictures of a fair: the stand, then the fair's own logo. On one column the picture ranges **left** and fills its column up to 300px (D203, D204): the full width of a phone is more than a photograph of a stand needs.tokens: layout.break-event

Part of a larger component or pattern: shown with the patterns (phase 6).

.event__bodyName, edition and dates. It may shrink: a long fair name must wrap rather than push the row.tokens: space.m

Part of a larger component or pattern: shown with the patterns (phase 6).

.event__headThe fair's name and its strapline, over **one rule** (D199). The rule was on the strapline, which half the fairs do not have, so half of them went without it: it belongs to the pair.tokens: space.m, border.underline, color.accent.default

Part of a larger component or pattern: shown with the patterns (phase 6).

.event__titleThe name of a fair.tokens: font.size.4xl, font.weight.bold, font.leading.tight

Interpack

Processing & packaging

7-13 maggio 2026

Marks

.text-column > .decor, .media-column > .decorA leaf that belongs to one half of a band sits **behind** that half's content (D93). It works because the column is a stacking context with no background of its own: one layer down is below the words and still above the band.

Part of a larger component or pattern: shown with the patterns (phase 6).

.leafThe leaf motif: a lens on the top-left/bottom-right diagonal, redrawn from the title band (D7). It is a mask over currentColor, so one asset serves white on yellow, yellow on white and ink on cream.tokens: size.leaf.mark
.leaf--bulletThe 30px leaf that marks a list item.tokens: size.leaf.bullet

Part of a larger component or pattern: shown with the patterns (phase 6).

.leaf--markThe leaf beside a title in the band. It is stated as a **height** of two ems and no width at all (D87): the width then comes from the square aspect ratio `.leaf` already carries, so the mark scales with the type around it instead of holding the 52px it measured at one viewport. `width: auto` is what undoes the width `.leaf` sets — leaving it out would not have been enough.

Part of a larger component or pattern: shown with the patterns (phase 6).

.leaf--accentThe 132px leaf that accents a section edge.tokens: size.leaf.accent

Part of a larger component or pattern: shown with the patterns (phase 6).

.decorThe same leaf as a large background shape, up to 800px across (D24). The component gives it colour and behaviour; the pattern gives it position and size, because where a decoration sits is a property of the band, not of the shape.
.decor-clusterA **group of leaves that travels as one** (D128). The three marks on each side of the approach band are placed in percentages of this box, not of the section, so the composition they make is the same drawing at 1920 and at 390 — only its size changes. The box itself has a ratio and a width, which is what makes the percentages inside it mean something.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor-cluster--leftThe left group: a pale leaf on its side with a yellow leaf above it and a smaller one below. It stands **one gutter in from the edge of the band** (D129), so it keeps the page's own margin whatever the window is. Below `break-mid` it moves to the top of the band and widens to `max(330px, 40%)` (D130).tokens: layout.gutter, layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor-cluster--rightThe right group: a pale leaf with two yellow leaves gathered at its top. Once the blocks stack (D130) the two groups go to the far ends of the band — the left one 5% from the top, this one 5% from the bottom — and grow to `max(330px, 40%)`, because a group that keeps 20% of a phone is a smudge. `top: auto` is what lets `bottom` take the anchor: with a height already fixed by the ratio, a box that states both is over-constrained and the top wins.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor-cluster--ear-leftThe ear of wheat that holds the left edge of the Green Puff band: a stalk, two yellow leaves and a black one, growing upwards. Centred on the section and just outside the band, so it frames the features without crowding them. It sits **on the band's own edge** and grows to 22% of it once the features stack (D139), where a 9.5% ear would be a thread. Below `break-narrow` it is switched off (D140): on a narrow page an ear that wide is a background, not a mark.tokens: layout.break-mid, layout.break-narrow

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor-cluster--ear-rightThe same ear on the right, **mirrored as a whole** — one `scaleX(-1)` on the group, so the four marks inside it need no mirrored twins of their own. It sits **on the band's own edge** and grows to 22% of it once the features stack (D139), where a 9.5% ear would be a thread. Below `break-narrow` it is switched off (D140): on a narrow page an ear that wide is a background, not a mark.tokens: layout.break-mid, layout.break-narrow

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--ear-stemThe stalk: the one mark in the system that is **not a leaf**, so it drops the leaf mask and takes a pill radius instead.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--ear-1The first leaf of the ear, the smallest.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--ear-2The second leaf, a little larger and a little lower.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--ear-3The last leaf, the largest, and the only black one.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--frame-leftThe big pale leaf on the left of the approach band, **turned on its side** (D127) and pinned to the page's own gutter: the `calc` walks back from the narrow column the text holds to the edge of the band and then in by one gutter, so the leaf sits where the margin starts whatever the window is doing. Placed in percentages of its cluster (D128).

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--frame-rightThe pale leaf on the right, one gutter in from the edge and lower than its twin. Placed in percentages of its cluster (D128).

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--spark-left-topA yellow leaf over the pale one, towards the top. Placed in percentages of its cluster (D128).

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--spark-left-bottomA smaller yellow leaf low on the left, in the gutter. Placed in percentages of its cluster (D128).

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--spark-right-topThe top spark mirrored onto the right gutter. Placed in percentages of its cluster (D128).

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--spark-right-bottomThe smallest leaf of the six, inside the right margin. Placed in percentages of its cluster (D128).

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--inset-left-topThe small accent leaf beside the machine (D96). Stacked, it moves out to `right: 88%` and up to `top: 9%` (D105, D110): the machine goes from a quarter of its half at 978 to all of it at 390, and at 55% the leaf was simply behind the picture. At 88% it clears the machine at 978 and 768 and leans into the gutter at 390, where there is no room beside the picture at all; at 9% it sits above the white leaf below it instead of alongside it.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--inset-left-bottomThe leaf a machine stands on: **90% of its column's height**, square, set 23% in from the column's right edge and upright (D172). Below `break-mid` it moves to the top of the column and gives up a little height. Five sections carry it on Macchinari and one on the home's product band. Stacked it gives up a little height and lets both of its offsets go (D173), so it sits where the flow would have left it.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--quarter-turnA **quarter turn** on a leaf that already has a placement (D171). It is the only thing that separates the machines whose leaf lies across them from those whose leaf stands behind them, so it is one declaration and composes with any placement rather than doubling it.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--inset-left-bottom.decor--quarter-turnA leaf lying across the machine wants more of the column than one standing behind it, and less of a margin (D172): 110% of the height against 90%, 10% in from the right edge against 23%. The compound is the honest place for it — the figures belong to the pair, not to either class alone. Stacked, it takes the whole height of the column and **centres itself on it** (D173): the picture runs the full width there, and a leaf held to one edge would hang off the other.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--centredA leaf **on the middle of its column** rather than against an edge (D184). It restates the quarter turn because a transform replaces the one before it rather than adding to it.

Part of a larger component or pattern: shown with the patterns (phase 6).

.band-row--inset .decor--inset-left-bottomThe white leaf the press stands on, **as it was measured** (D194): 65% of its column's height, 24% in from its right edge, hanging 5% below it and tilted 12 degrees. D166 to D172 moved the class while fitting the five machines on Macchinari to their own band, and the home's composition went with it; the row's own name takes it back, the way D175 already did for its stacked offset.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--inset-right-topThe big white leaf the text is written on: **wider than its half** and mirrored, so it runs past the top and the bottom of the band and the text sits in its belly (D96, D100). Its size comes from the **width** of the half, not its height (D102): what has to fit inside it is the text, and the text is as wide as the column and only as tall as the type makes it. Sized by height it lost 38px of width between 1920 and 1500 while the text kept all of its 627, and the second line of the heading crossed out of the white onto the cream. It is anchored on the centre of its half and offset by a fraction of **itself**, so the whole composition is one shape at every width. Once the halves are stacked it is **190% of its half's height**, `top: 30%` of that half, centred on it horizontally (D105–D107), and the text is centred inside it rather than filling the column. Sized to cover the full width of the words it swallowed the band — a lens is only 77% as wide as its box at its own middle, and less again across the height of a block of text, so covering 899px of text took a box of 1573 and the cream survived only in the corners. A leaf the text is centred **in** is the shape the raster has; a leaf the text is written **on** is a white page. Stacked it moves to `left: 70%` (D179): centred on the column it reached past both of its edges.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--behind-text-leftThe leaf a block of text is written on, **centred on the column** and 85% of its width (D190). Servizi carries three, two cream and one in the veil.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--behind-text-rightThe same leaf for a band whose text sits on the right, **mirrored about the vertical** (D188) so the two bands answer each other across the page, and centred on its column like its twin.

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--inset-right-tallThe same white leaf behind a **tall** text column — four paragraphs rather than two (D159). Sized by the column's **height**, 135% of it and square, 4rem to its left and centred on it, because a figure taken from the width cannot cover a column that is twice as deep as the one it was fitted to. Stacked, 130% of that height, centred. The home's band keeps `inset-right-top` and its own width-based figure, which is the one measured against the raster.tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--inset-right-bottomThe accent leaf under the text, mirrored, starting at the middle of its half (D96). Sized by the **height** of its half, 22%, and starting just past its middle (D104) — at **95%** once the halves are stacked, which puts it clear of the big white leaf's body, off its right shoulder (D106, D108). It keeps D96's rule where the big white leaf above it does not (D102): it is a mark beside the badge, not a field the words have to fit inside, so the dimension it answers to does not have to be the one the text answers to. Stacked it hangs off the right of the column by a third of itself (D179).tokens: layout.break-mid

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--whiteWhite on cream: the shape the machines sit on. A colour, nothing else: the leaf is a mask over `currentColor`, so one shape serves every surface in the system.tokens: color.surface.default
.decor--creamCream on white: the quiet shape behind a text column. A colour, nothing else: the leaf is a mask over `currentColor`, so one shape serves every surface in the system.tokens: color.surface.alt
.decor--veilA leaf in **translucent white** (D184): on a brand band a cream leaf is a second colour, and a white one at 44% is the band itself, lightened.tokens: color.surface.veil

Part of a larger component or pattern: shown with the patterns (phase 6).

.decor--accentA full-strength yellow leaf, used small. A colour, nothing else: the leaf is a mask over `currentColor`, so one shape serves every surface in the system.tokens: color.accent.default
.decor--inkThe dark leaf of the Green Puff column: the only place the ink is used as a shape. A colour, nothing else: the leaf is a mask over `currentColor`, so one shape serves every surface in the system.tokens: color.text.default
.section > .section__contentContent sits above the decor layer. Declared once here rather than on every component. 5rem between its rows (D126, D130), which is what a section's own parts are worth once they stack.tokens: space.8xl

Part of a larger component or pattern: shown with the patterns (phase 6).

.seamThe short yellow tab that marks the seam between two white bands. Four instances, two pages. It sits **astride the join** (D88): half of it on the band above, half on the band below, pulled up and down by half its own height so that the row it lives in takes no vertical space at all. It is raised a layer, or the band that comes after it would paint over its lower half. Its height is a **space** step, 8px (D83): it is a shape with a size, not a border, and `border.underline` — 4px, which it used to carry — is for rules under text. Its 224px are capped at **80% of the column** (D122), so on a narrow page the mark stays a mark and does not run the width of the band.tokens: space.xs, color.accent.default

Site

.mastheadSite header at rest: contacts on the left, logo centred, social on the right, then the navigation under a hairline. The three-column row is composed in the pattern with the core `grid` primitive — the component carries appearance only (rule 12).tokens: color.surface.default, layout.content-header, layout.gutter

Part of a larger component or pattern: shown with the patterns (phase 6).

.masthead__logoOne size, on every page and at every scroll position (D52). The PDF shows the mark at 416px on the home and at 296 on the inner pages, where the capture caught the header already scrolled; a logo that resizes while you read is an effect, not a rule, so the system keeps the smaller of the two measurements — the one the six pages mostly show.tokens: layout.logo

Part of a larger component or pattern: shown with the patterns (phase 6).

.masthead__logo-linkThe link around the logo, on every page: the mark is the way home. It holds an image and never text — `display: block` and the tight leading exist precisely so the image does not sit on a text baseline and drag the header's first row a few pixels down.tokens: font.leading.tight
.masthead__contactE-mail and telephone, the only contact details on every page. The row sits on its bottom edge (D59), so the padding is what lifts the last line clear of the logo's foot (D79).tokens: font.size.xs, font.leading.normal, color.text.default, space.xs

Part of a larger component or pattern: shown with the patterns (phase 6).

.masthead__socialThe three marks, lifted off the logo's foot by the same step as the contacts (D79).tokens: space.xs

Part of a larger component or pattern: shown with the patterns (phase 6).

.masthead__social imgThree square marks, measured 32px with a 15px gap.

Part of a larger component or pattern: shown with the patterns (phase 6).

.masthead.is-pinnedPinned (D53, D62). **The header stays in the flow and scrolls away**; the menu band leaves it and fixes to the top of the window at the moment it gets there — not on the first pixel of scroll. The script measures how far that is and sets `.is-pinned` at exactly that offset, so the band arrives at the top and stays, with nothing to see in between. The padding underneath replaces exactly the height the band took with it, so nothing jumps at the moment the class lands — and since no height is fixed any more (D55), that height is measured by the script and published as `--masthead-pin-h`, rather than restated here as a number that would drift. The hairline moves from above the menu to below it, because at the top of the window a rule above the menu has nothing to separate. The class is set by a script, never by a media query (D12).tokens: border.hairline, color.border.default

Part of a larger component or pattern: shown with the patterns (phase 6).

.site-navItems 72 to 85px apart across the header column — a cluster whose gap is the 72px step; the pattern spreads it to the column's full width. The labels are **xs and bold** (D58): the raster measures them at 21.5px regular, and the system sets 20px bold, which reads as a navigation rather than as running text at the same size. The page being read, and the item under the pointer, are both marked with **the leaf, one em tall, to the right of the label and mirrored on its horizontal axis** (D63, D65, D71): **accent yellow** on the page being read, **cream** under the pointer (D76), so the two are told apart by colour and the hover is the quieter of the two. The underline is gone. The leaf is an `::after` over the same mask every other leaf uses — no extra markup, and the composer keeps setting nothing but `.is-current` and `aria-current`. It sits in the line box of **every** item, transparent until it is wanted, so hovering colours a shape that is already there instead of pushing the label sideways under the pointer. The items are left-aligned with a 32px column gap (D66): the row no longer spreads across the header, it starts where the content starts.tokens: font.size.xs, font.weight.bold, font.leading.tight, color.text.default, space.2xl, space.m, space.xs, color.surface.alt, color.accent.default, font.size.sm …
.masthead__logo-link--compactThe logo inside the menu band. It is the compact header's mark (D74) and nothing at all above the breakpoint, where the first row carries the real one.

Part of a larger component or pattern: shown with the patterns (phase 6).

.masthead.is-mobileThe compact header (D74), below 1200px. The first row is gone — contacts and social marks with it — and the logo it held is replaced by the one in the menu band, on the left. The language switch is pushed to the right and the menu button follows it, `space.4xl` away: 3rem, the bar's own column gap (D70). `.is-mobile` is set by the same script that sets it on the navigation, from the breakpoint the pattern declares — so the number lives in one place and the header needs no media query of its own.

Part of a larger component or pattern: shown with the patterns (phase 6).

.masthead.is-mobile .site-navBelow 500px the language switch has left the bar for the panel (D77), and with it the auto margin that pushed the pair to the right. The navigation takes it over, so the menu button stays where it was — at the end of the row, opposite the logo.tokens: layout.break-narrow

Part of a larger component or pattern: shown with the patterns (phase 6).

.site-nav__lang--barThe switch as it sits in the menu bar. Below 500px the bar is the logo and the menu button and nothing else fits beside them, so this copy goes and the one in the panel appears (D77).tokens: layout.break-narrow

Part of a larger component or pattern: shown with the patterns (phase 6).

.site-nav__lang--panelThe switch at the end of the open menu, under the last item. It is a second copy in the markup, not the same one moved: a stylesheet cannot carry an element from one box to another, and the panel is inside the navigation while the bar's copy is beside it (D77).tokens: space.2xl, layout.break-narrow

Part of a larger component or pattern: shown with the patterns (phase 6).

.site-nav__langIT | EN, in the menu's own type — xs and bold (D60), because it sits on the same line and reads as part of it. The separator is the one muted grey in the system.tokens: font.size.xs, font.weight.bold, color.text.default, color.text.muted
.colophonFooter: three centred lines on the brand yellow, and the one place where the design already puts ink on yellow (6.64:1) instead of white. Three rem of air above it (D116): the page ends before the colophon starts.tokens: color.surface.brand, color.text.default, space.3xl, layout.gutter, font.size.xs, font.leading.normal, space.4xl

Idealmac SRL P.IVA-C.F. 12065780012

Contatti info@idealmac.com - +39 (0)11 424 96 44

.page-titleThe yellow band that names the page: a leaf, the title, a leaf. **No height** (D64): it is as tall as what it holds plus `space.m` above and below (D67), so a title that wraps on a narrow window opens the band instead of overflowing it — and wraps centred (D78), not ragged against the leaf on its left. The raster measures 113px on all six pages; what the padding gives is reported with the decision. It is the only component with a single slot (D25). The two leaves are mirrored — measured: the right one matches the left one flipped horizontally at 0.88, unflipped at 0.55.tokens: space.xl, space.m, color.surface.brand, color.text.inverse

Macchinari accessori

.page-title .leaf:last-childThe leaf that closes the band is the mirror of the one that opens it: measured, the right leaf matches the left one flipped horizontally at 0.88 and unflipped at 0.55.

Part of a larger component or pattern: shown with the patterns (phase 6).

Headings

.heading-ruleA heading with the yellow rule under it. The heading **hugs its words** and the rule is **exactly as wide as them** (D180): it was a declared 334px capped at the column, which fitted the raster at one width and nothing else. The rule is out of the flow, so it takes no height of its own and hangs in the gap the stack already leaves. Thirteen instances across three pages, so it is a component and not a local rule. It is pinned to the **foot** of the heading: an absolutely positioned box with no offsets takes its static position, which after a run of text is the end of the last line — the rule came out beside the words rather than under them. The rule is **4px** thick (D181), the thinnest in the system, which is what a line under a name has been since D135.tokens: border.underline, space.2xs, color.accent.default

Know-how consolidato

.heading-rule + pThe paragraph under a ruled heading stops at **75%** of its column (D126). The heading runs the full width and its rule under it; the text does not, so the block reads as a heading with something written under it and not as a rectangle of type. Both places that pair the two — the home's cards and the approach grid — get it from here.

Part of a larger component or pattern: shown with the patterns (phase 6).

.section--brand .heading-rule::afterOn a yellow band the rule turns white, like every other accent device.tokens: color.accent.on

Part of a larger component or pattern: shown with the patterns (phase 6).

Tabs

.tabThe yellow tab that names a product family. A fixed **20rem** block with the label set 2rem in from the left and nothing declared on the right (D122) — not a label that hugs its text, which is why the width is declared. The source measures 481 wide with the label 86 in; both are chosen against it. **No height** (D115): 0.5rem above and below the line is what decides it, so the tab follows its own type instead of holding a measured 56px.tokens: space.xs, size.rule.tab, space.2xl, color.surface.brand, color.text.inverse, font.size.xl, font.weight.bold, font.leading.tight
Gallette
.tab--autoThe same tab used as a centred section label (IL NOSTRO APPROCCIO, CONTATTI). It **hugs its text** again (D127): `width: unset` undoes the `min(20rem, 100%)` `.tab` declares, which was 30px short of *Il nostro approccio* and broke it over two lines. 3rem of air on each side instead of the 2rem indent a tab carries when it starts a row, no height, and the label centred — `text-align` cannot centre a flex line on its own, so `justify-content` does the centring.tokens: space.4xl
Il nostro approccio
.tab-rowA tab with the rule that runs from it to the edge of the column. The rule sits on the tab's bottom edge — measured, and the reason the row aligns to flex-end. No gap (D122): the rule starts where the tab ends.tokens: border.rule, color.border.default
Snack

Layout

ClassPurposeKey properties
.mainPage ceiling: twice the content width, no padding. Bands are adjacent and touch — measured on all six pages, there is no gap between sections.maxWidth, marginLeft, marginRight
.main:has(.media-column--fit-cover)Servizi, and only Servizi: its three bands are **the same height** (D189). Sections are siblings, so equal heights need a parent that says so — the page's `main` becomes a grid whose last three rows are `1fr`, and `1fr` rows in a grid of auto height all take the height of the tallest. The hook is `:has(.media-column--fit-cover)`, which is the one thing only this page carries; a class on `main` would be cleaner and the composer does not write one. The row list states the page's shape — hero, title, three services — so a fourth service needs a fourth `1fr`. Its children take `width: 100%`: a section carries auto side margins, and auto margins on a grid item stop the stretch — without it the five of them shrank to their content, 554 to 1320 wide instead of the band. Each band is a grid of one row as well (D190), so its row fills the section's content box: the two halves are centred in the whole of it and the photograph is as tall as the band less its padding. The row gives up its own 1rem above and below, so the photograph is the band's content box and nothing less: 470 and not 438. Once the halves stack the three bands go back to their own heights (D191) — equal bands are a figure of the page side by side, and stacked they would only leave one of them half empty — and each row puts 2rem between its picture and its words. Each stacked text column stands at least 21rem tall with its lines centred in that height (D192), so the three bands keep a family resemblance even when the shortest of them is four lines long.display, gridTemplateRows
.sectionThe content column, {layout.content} wide, with the gutter **outside** it: the box is the column plus its two gutters, so the column keeps its full width wherever the window allows it and gives way only when the window is narrower (D61). Position is relative because a section may carry decor (D24). The air above and below is **3em** — 72px, the body's 24px three times over, `space.7xl` (D114). One figure for every white section on the site: a white section no longer states its padding, it inherits it. A coloured surface still overrides, and those overrides are the only ones left.position, maxWidth, marginLeft, marginRight, paddingTop, paddingBottom, paddingLeft, paddingRight
.section--wideA full-bleed coloured band that keeps its content on the same column as a plain section (component rule 9): the padding is whichever is larger, the gutter or half of what the band has over the column — which lands on exactly the column a plain section lands on, at every width (D61). The clip keeps the large decorative leaves inside the band.maxWidth, overflow, paddingLeft, paddingRight
.section--altCream band.background
.section--brandYellow band. Text on it is white at 2.07:1 — a brand choice taken with the number in hand (D11), recorded in DESIGN.md.background, color
.section--pad-3xsThe tightest band of all: on Macchinari accessori a yellow band is only as tall as the photograph inside it, with 24px of air measured above and below.paddingTop, paddingBottom
.section--pad-2xs**2rem** above and below, at every width (D185). It is what the four machine bands on Macchinari asked for when `pad: 0` stopped meaning what its name said: a band whose halves stand on its own edges still needs to be told apart from the one before it.paddingTop, paddingBottom
.section--pad-xsThe tightest band: the alternating bands of Macchinari accessori, where the photograph sets the height and the padding only keeps it off the seam.paddingTop, paddingBottom
.section--pad-sTighter band.paddingTop, paddingBottom
.section--pad-0No padding: the band is exactly as tall as what it holds, as the title band is.paddingTop, paddingBottom
.section:not(.section--alt):not(.section--brand):not(.section--pad-0) + .section:not(.section--alt):not(.section--brand):not(.section--pad-0), .section:not(.section--alt):not(.section--brand):not(.section--pad-0) + .section--pad-0 + .section:not(.section--alt):not(.section--brand):not(.section--pad-0)Two white sections one after the other are **one field, not two** (D114): the second drops its top padding, so the pair is separated by 3em and not by 6. The second selector steps over a `.seam`, which is a section of zero height between two bands and must not count as one of them. A coloured band breaks the run, which is the whole point of a coloured band.paddingTop
.heroFull-bleed photograph under the header, a `frame` with a measured height. The image is positioned against the band rather than flowing inside it: that way the band keeps the page column like every other section, and the photograph still runs edge to edge without the negative margins the page model forbids.position, height, overflow
.hero--homeThe home hero is 69px taller than the inner pages. Measured, not a rounding.height
.masthead__barThe bar that holds the menu and the language switch. **No height**: it is as tall as the menu plus the band's padding (D55), which lands within a pixel or two of the measured 54 and survives a longer menu, a second line, a bigger text size. It is the column; the band around it is what spans the page and what pins (D53).position, display, alignItems, justifyContent, columnGap
.masthead__navbandThe band the menu bar sits in, and the owner of the hairline that separates the menu from the row above (D57): the rule belongs to the band it opens, not to the column inside it — which is also why it still spans the header when the band pins and goes full width. The band exists so that the menu has something to pin **as a band**: a pinned column would leave the page showing through on either side of it (D53).background, paddingTop, paddingBottom, borderTop
.media-columnThe media side of a band. It centres its pictures instead of stretching them: a cut-out machine has a size of its own and must keep it, which a plain stack would not allow. It sits a layer **above** the text half (D98), so a machine that runs past the edge of its own column crosses over the text instead of disappearing under it.display, flexDirection, alignItems, gap, position, zIndex
.media-column--gridThree photographs of one installation, read as one picture (D180): the first runs the **whole width**, the two under it share it **two to one**. A column of three stacked pictures made the band twice as tall as its text and said nothing the grid does not. Each photograph fills its cell and is cropped to it (D181), so the three make one rectangle instead of three of different heights. Under `break-narrow` the two to one goes and the three photographs stand one under the other (D186): at a third of a phone's width the smaller of the pair is a thumbnail.display, gridTemplateColumns, gap
.text-columnThe text half of a band, and the box its own leaves are placed against (D93). The layer is what lets them sit behind the words: it makes the column a stacking context, so a leaf one layer down is still above the band's background and below everything written here.position, zIndex
.l-switcher--middle:not(.band-row--tight)A row whose halves are centred on each other **centres their contents too once they stack** (D176, narrowed in D178): the text column ranges its lines on the middle and lays its own children on that axis, and the yellow rule under a heading leaves the flow to sit on it. Stacked, a text column is the full width of the card and ranging it left would leave the rule starting at an edge the eye has no reason to look at. The **tight** row is excluded by name: it keeps no padding of its own, so its text already starts at the band's edge and has nothing to centre in.
.text-column.text-column--insetThe text half of the home's product band: **half** the row, with 7rem of air above and below (D92, D97). It grows at 2.5 and so does the picture's half, which is what makes the two containers the same width (D97) — the composition is carried by the leaves and by the machine hanging off its column, not by an uneven split. The air on the **left** is the row's gap and not this column's padding: flex adds an item's padding outside the share it grows into, so a padded half is always wider than an unpadded one by exactly that padding (measured: 723 against 611 at 1920). `max-width: none` has to come with it, and the selector has to carry the column's own class: `.measure` is on this column and is declared later, so 54ch would otherwise hold it to 47% of the row however hard it is told to grow — the same trap as the leaf in the button (D81). Once the halves are stacked **both** paddings go and the column becomes `fit-content`, centred in the row (D105–D107): it is then as wide as its widest line, and everything in it — heading, paragraph, label, badge — stretches to that one width and starts on the same left edge, which centring each block on its own did not do: the 7rem were there to centre the text against a picture beside it, and what is above the text now is the picture itself, with the column's own row gap between them. The column is then exactly as tall as its words, which is what the leaf behind it is measured from.flexGrow, maxWidth, paddingTop, paddingBottom
.band-row--insetThe row of a product band whose halves are inset: **7rem** between the machine and the text (D97). Stating it here instead of as padding on the text keeps the two halves the same width, and the air lands where it is meant to be — between them — with the machine free to lean into it. Below **1200px** the gap stops being a fixed 7rem and becomes **7% of the row** (D104): 112px is a tenth of the row at 1920 and a quarter of it at 1000, and a quarter of the row spent on nothing is what squeezed the two halves. At **978px** it stops being a row at all and becomes a **column** (D105, D107) rather than a wrapped row: the switcher would reach the same arrangement by wrapping, at 977, but a column states it — and states **where** (D107), which is why the band turns at 978 and not at a width the gutter arithmetic happened to produce — and the three things that only make sense across a row — the basis that drives the wrap, the centring, the gap between columns — stop applying instead of being worked around.columnGap
.section > .section__content.band-row--insetThe home's product band closes up once its halves stack (D179): **1rem between them**, against the 5rem a section's content carries everywhere else. The two halves of this band are one picture and one block of words about it, and stacked they read as one thing.
.section > .section__content.band-row--wideA band split that **stands inside its band**: 6rem between its halves, **which are equal** (D162), 1rem by 3rem of padding around them, nothing between its rows, and it never wraps while the two are side by side — the switcher's own threshold would break the row before the breakpoint that governs the rest of the page does. Once the switcher is a single column the photograph comes first and stands **up to** 400px tall (D174, D195): a ceiling and not a height, so nothing is stretched to reach it, and the text column centres itself under it, its lines ranged left as everywhere else (D166). A choice, not a colour (D161): any section can ask for it with `gutters: wide`. The selector carries both of the row's other names because `.section > .section__content` declares a row gap of its own and is written later in the sheet, and the halves carry `min-inline-size: 0` because a flex item will not shrink below its content and a 600px photograph would otherwise keep its half wider than the other. The halves also drop their `max-inline-size`: `.measure` caps the text at 54ch, which at the running size is 554px, and a half that is capped is not a half. Both halves carry `min-inline-size: 0` at every width: the heading's yellow rule is 334px wide, and a flex item will not go under its own content, so a column of 230px on a phone was refusing to be narrower than that rule. A column that takes its height from the text puts its picture back in the flow when the halves stack (D188), full width and its own height — `max-width: none` is what lets it fill a half, and nothing caps it once the half is the page. Stacked it gives up its 3rem at the sides as well (D198): the band's own gutter is all the margin a phone has room for.columnGap, padding, rowGap
.section > .section__content.band-row--tightA wide band row with the **switcher's own spacing** (D167): no padding and 2rem between the halves. It keeps everything else `band-row--wide` brings — halves of equal width, no wrap while they are side by side, picture first and text centred once they stack — because `gutters: tight` declares both classes. The spacing is the only thing it takes back. 2rem between its lines as well (D168), and its text column drops the auto margins the wide row gives it: with no padding around the row there is nothing to centre the column **in**, so it starts where the band starts. Its photograph keeps its own proportions at every width (D182): full width of the column and the height that follows, instead of the 400px a wide row gives a stacked picture.padding, columnGap, rowGap
.section > .section__content.band-row--wide > .media-column--grid > imgA gallery decides for its own pictures (D182). The row's rule for a stacked photograph — 400px tall, width to follow — has the same weight as the gallery's, so this one is written after it and says so plainly: inside a grid, each picture fills its cell and is cropped to it, at every width.width, height, objectFit
.section--alt > .section__content.band-row--wideThe cream band on Presse puts **2rem between its lines** (D175), where a white one puts none: it is the only wide row whose two halves are a block of text and a photograph of equal weight, and stacked they need telling apart.rowGap
.media-column--insetThe picture's half of that row: the same 2.5 as the text, so the two halves measure the same (D97).flexGrow
.media-column--fitA media column that takes the height the text gives it instead of setting one (D91). **Only while the two halves are side by side** (D104): at 978px and below the row is a column, the column is alone on its line with nothing in its flow, and a picture that has left the flow leaves it 0 tall — which is how the phone lost the machine and the two leaves behind it. Below that width the picture is **in the flow** again, at its own size, and the column is as tall as it. The picture leaves the flow and fills the column, keeping its proportions — the same device the hero uses (D35) — and hangs **3% of the column past its right edge** (D94, D100). It is anchored by that right edge and takes its width from its own proportions, so the machine keeps its shape and the overhang stays the same fraction of the half at every width. Without it a tall product photograph decides how tall the band is, and the text floats in the middle of whatever is left.alignSelf, minHeight, position
.media-column--fit.media-column--fit-coverA photograph that takes the height of the text beside it (D188): it fills the half and is cropped to it, where the product band's machine is fitted inside without cropping. Both leave the flow so the **text** sets the row's height, and both come back into it once the halves stack.
.card-rowThe two home cards: **two columns above 978px, one below** (D118), declared and not left to auto-fit, so the rule that releases the button meets the same breakpoint exactly. 64px between the columns and 64 down (D117).gridTemplateColumns, columnGap, rowGap
.card-row > .l-sidebarA stacked card is a **grid of two rows**, not a wrapped sidebar (D119): the picture's row is `auto` and the text's is `1fr`, so every pixel the grid adds to the shorter card goes **inside the text** and none of it above it. Wrapped, a flex container shares that space equally between its lines, which pushed the two headings off each other's line by twenty-odd pixels. The two windows where the picture sits beside the text put the sidebar back on flex, where it belongs.display, gridTemplateColumns, gridTemplateRows
.card-row__mediaThe picture beside a card's text. The **picture** carries the square now (D198), not its box: 300px wide, square, and the column takes whatever height that gives it. Beside the text the flex stretches the picture to the card; stacked, nothing does and the square holds.display, alignSelf
.l-stack > .card-row__actionThe button of a card: at the **right end** of its column, and on the **floor** of the card — `l-push`, with nothing above it. Once the grid is a single column there is no neighbour to line up with, so the push is released and the button follows its paragraph (D118). The selector carries `.l-stack` because that is where `l-push` declares its auto margin, and a single class would lose to it.justifyContent
.bandA section that carries decorative leaves: it becomes their positioning context and clips whatever runs past its edge.position, overflow
.band--insetThe home's product band is the one section whose top padding is not the one its padding option gives it (D112): **144px** while its halves are side by side, against the 64 of `.section--pad-s`. The white leaf the text is written on runs past the top of the band, so the words start lower than the band does, and the 64 that is right for a plain cream band leaves the heading crowded against the edge. Once the halves stack the picture is on top and the leaf is behind it, so the band goes back to 96 (D104).paddingTop
.masthead__topThe header's first row: contacts, logo, social marks. Its three parts sit on the **bottom** of the row (D59), so the contact lines and the social marks line up with the foot of the logo however large the logo's clamp makes it. As tall as they are plus its own padding (D55), and with no width of its own: the header states it once, for both rows (D56).display, alignItems, justifyContent, paddingTop, paddingBottom
.pairTwo columns of equal width, **narrow and centred in the band** (D125): the four blocks of the approach hold the middle of the page and leave the margins to the leaves, which is how the source draws them. **55% of the band**, 75% on a phone (D126). Declared and not auto-fit, like every other grid on the site since D115, and a single column below `break-mid`. 4rem between the columns, 5rem between the rows.display, gridTemplateColumns, width, marginLeft, marginRight, columnGap, rowGap
.pair--valuesThe four values on the yellow band take **75%** of it, with 6rem between the columns and **1rem between the rows** (D134): the separator hangs into that gap instead of sitting on the join. Below `break-mid` it takes the whole band (D135): once there is one column left, holding it back from the edges only makes the line shorter for no reason.width, columnGap, rowGap
.pair--peopleThe two people take **as much of the band as they need** (D136): `width: auto` against the auto side margins `.pair` carries means as wide as the two of them, centred. 3rem above them at every width (D186), so the pair sits apart from the paragraph that introduces it.width, marginTop
.pair--featuresThe six Green Puff features take the same grid as the four values on Azienda (D142), with two figures of their own (D143): **`width: auto`**, so against `.pair`'s auto side margins the block is as wide as its six labels and centred, and **`grid-auto-rows: 1fr`**, so all three rows are the height of the tallest — *Struttura e pannellatura completa* sets on three lines and the other five keep its height, which is what puts the separators of the two columns on the same line.width, gridAutoRows, columnGap, rowGap
.nowrapA phrase that must not be broken across lines: a registration number, a share capital, a telephone number, the name of a policy (D95). It is the one utility class in the system, and it exists because the alternative — non-breaking spaces inside the content — hides a typographic rule inside the words.whiteSpace
.order-firstPuts a column first without changing the document order: the patterns alternate which side the media sits on, and an option may only add a class, never reorder the markup.order
.measureReading width in characters of the text's own font (component rule 14).maxWidth
.measure--narrowThe narrow text column.maxWidth
.measure--wide89ch, far past comfortable reading. It holds one or two centred sentences and is kept as measured rather than silently corrected.maxWidth
.product-rowA row of cut-out products under a tab. An explicit grid and not an intrinsic one (D115): the number of columns is declared, because the client declared it — the declared count above 978px, two at or below it, one on a phone (D116). Each picture takes the full width of its cell. While the row is **one row** it sits in a square of its own — `aspect-ratio: 1` with `object-fit: contain` — so a round galletta and a flat one occupy the same box and line up on their centres. Once the row folds (D120) the square goes and so does the stretch: below 978 each picture is drawn at its own size (D123), centred in its cell both ways, so two rows of products read as products and not as a wall of boxes. The gutter is 64 both ways (D117): it was 64 across and 32 down, and two rows of squares need as much air between them as the squares have beside them. The modifier carries two classes, so the two queries have to carry them too or they lose on specificity and nothing moves. The row is inset **10% on each side** (D124): the products sit in the middle of the column and not against the tab's own edges, which is how the source draws them — the picture ends well before the rule above it does.display, gridTemplateColumns, paddingLeft, paddingRight, columnGap, rowGap, alignItems, justifyItems
.product-familiesThe families of one section, one under the other inside the column that holds the first tab (D115). 3em between them, the same air a white section puts above and below itself (D114), so the two families are spaced like sections without being sections.rowGap
.mould-rowsThe rows of the mould table, one against the next (D149): the gap between them is zero, because each row carries its own air under its pictures and the rule is the only thing that separates them.rowGap
.events-gridThe fairs: a grid of **five columns** holding 80% of the band, centred, in which every fair takes four (D201). Odd fairs take the first four and even ones the last four, so one column is empty on the right and then on the left and the list walks down the page. One column below `break-mid`. It puts 4rem between the fairs once stacked, and takes the whole band only under `break-narrow` (D204), where 80% of 326 is not enough for a photograph.display, gridTemplateColumns, width, margin, columnGap

Site chrome (handled by the platform)

PartTokens and rules
consentowner: platform consent plugin (not a component); surface: {color.surface.default}; text: {color.text.default}; accept: btn; reject: btn; border: {color.border.control}; radius: {radius.pill}; focus: {color.accent.default}; note: The captured pages carry no consent banner; these are the tokens it must use when the client chooses a plugin.

Patterns

Section patterns with their options and repeatable lists, shown with sample content.

MastheadmastheadSite header at rest: contacts, the centred logo and the social marks on one row, the menu and the language switch under a hairline. Below 1200px the header is a different shape (D74): the first row goes, the logo moves into the menu band, and the language switch and the menu button sit together on the right. On scroll (.is-scrolled, D12/D53) the header scrolls away with the page and only the menu band stays at the top of the window; the logo does not change size (D52). The class is set by a script, never by a media query.pages: all (site.json)lists: social
info@idealmac.com
+39 (0)11 424 96 44
ColophoncolophonThree centred lines on the brand yellow: company, contacts, policies.pages: all (site.json)

Idealmac SRL P.IVA-C.F. 12065780012

Contatti info@idealmac.com - +39 (0)11 424 96 44

Link utili: Privacy Policy

HeroheroThe full-bleed photograph that opens every page. 601px tall, 670 on the home (option home).pages: index, azienda, presse-per-gallette, macchinari-accessori, servizi, fiere-ed-eventioptions: size: inner / home
Gallette di riso e cereali soffiati
Page titlepage-titleThe yellow band under the hero: a leaf, the page's one sentence, a mirrored leaf. 113px on all six pages.pages: index, azienda, presse-per-gallette, macchinari-accessori, servizi, fiere-ed-eventi

Idealmac: tecnologie per l'industria alimentare

SeamseamThe short yellow tab that marks the seam between two white bands. It carries no content: it is the one pattern that is pure punctuation.pages: index, presse-per-gallette
IntrointroCentred opening paragraphs on the wide measure, with an optional action aligned to the right of the column. Two pages open this way: the home, which ends with a button, and Azienda, which does not (D126).pages: index, aziendaoptions: pad: default / 3xs / xs / slists: paragraphs

Idealmac è in grado di supportare i propri clienti durante tutte le fasi del processo produttivo alimentare.

Band splitband-splitThe workhorse of the site: a text column and a piece of media side by side, on any of the three surfaces. Options place the media on either side, choose the surface and the padding, and say whether the heading keeps its rule; either half can carry any number of decorative leaves. The text column holds a heading, paragraphs, an optional leaf list, and an optional action — a button. **Eleven** of the site's sections are this one pattern. The home's product band was the twelfth until D111 lifted it out: it was the only user of `split: text` and `height: text`, and those two options left with it. `gutters: wide` gives a row 6rem between its halves and room around them (D161) — a choice any section can make, not something the cream surface carries.pages: presse-per-gallette, macchinari-accessori, servizioptions: surface: default / alt / brand; gutters: default / wide / tight; pad: default / 2xs / 3xs / xs / s; media: last / first; rule: on / off; gallery: off / on; fit: off / textlists: leavesText, paragraphs, list, leavesMedia, media

Miscelatori per cereali

I miscelatori sono utilizzati in tutte le linee di produzione di gallette di cereali soffiati.

Miscelatore per cereali
Product bandproduct-bandThe home's one product band, and the only section of the site built this way (D111). It was a `band-split` carrying two options nothing else used — `split: text` and `height: text` — plus the four leaf slots, nine styles and seven media queries that belong to it alone; eleven other `band-split` sections used none of it. Here the composition is the pattern and there is nothing to choose: the cream surface, the short padding, the picture first, the text half inset in a white leaf wider than its column, the picture half as tall as the text beside it. Four leaves: two behind the words, two beside the machine. The action is the Green Puff badge, sized against its own label (D101), and never a button. Below `layout.break-wide` the row loosens; below `layout.break-mid` the halves stack and the composition is restated rather than inherited (D104-D110).pages: indexlists: leavesText, paragraphs, leavesMedia, media

Presse per
gallette
e snack non fritti

Progettiamo e realizziamo innovative presse ad elevata potenza e basso consumo energetico.

Scopri

Green Puff
Pressa Green Puff per gallette
Card rowcard-rowTwo blocks side by side, each a picture beside a heading with its rule, a paragraph and a button. They look like cards and are not: no box, no border, no padding (D27). The two are the same height, the taller text sets it and both pictures fill it (D113); the button sits at the right end of its column, on the floor of the card, so the two buttons end on the same line (D116) — `l-push` and nothing else, no padding above it.pages: index · single useoptions: pad: default / 3xs / xs / slists: cards
Product familyproduct-familyA section of product families: one heading, then for each family the yellow tab with its rule, a row of cut-out photographs and a button to the page that sells them. The families live in **one container** (D115), so the second tab lines up with the first and the whole block is one white section. `columns` is content and not an option, because it belongs to the family and not to the section: `"3"` or `"4"`.pages: indexlists: families

Tecnologie avanzate per la lavorazione
di un' ampia gamma di prodotti

Feature gridfeature-gridScopri la tecnologia Green Puff, **full bleed** (D140) so the two ears reach the edge of the page the way the source draws them: a label and the green badge, then six features two by two, each a pictogram beside a label with a yellow separator under it — and none under the last row (D138). The decoration is an **ear of wheat** on each edge, declared as content the way the approach grid declares its leaves: a stalk, two yellow leaves and a black one, in a group that scales as one drawing and is mirrored on the right.pages: presse-per-gallette · single useoptions: pad: default / 3xs / xs / slists: leavesLeft, leavesRight, features

Scopri la tecnologia

Green Puff

Ciclo di
lavoro rapido

Mould tablemould-tableThe moulds: the yellow tab, then one row per format — the plate, the figures, the product — centred on each other, with the yellow rule running under the pictures only. Every other row fills its middle column with the brand yellow, which is decoration and not emphasis, and is counted in the stylesheet (D148).pages: presse-per-gallette · single useoptions: pad: default / 3xs / xs / slists: rows
Stampi
Stampo tondo
Formato: Ø 90 mm

Gallette/ciclo: 6 (4 - 10 g)
Capacità: fino a 2700 pz/h

Gallette tonde
Approach gridapproach-gridThe company's approach: a centred tab, then four blocks of a heading with its rule and a short paragraph, two by two in a column narrower than the band. The leaves are content, not markup (D125), declared the way the product band declares its own, and they come in **two groups** (D128) — `leavesLeft` and `leavesRight` — each in a box of its own so the arrangement holds at every width.pages: azienda · single useoptions: pad: default / 3xs / xs / slists: leavesLeft, leavesRight, items
Il nostro approccio

Know-how
consolidato

Conosciamo le dinamiche produttive perché provengono dall'esperienza diretta nel settore alimentare.

Values bandvalues-bandThe values, on the brand yellow: a centred heading and four pictogram-and-word pairs, two by two, separated by the white rule (D29).pages: azienda · single useoptions: pad: default / 3xs / xs / slists: items

I valori

Innovazione
PeoplepeopleWho the company is: a centred tab, a short centred text, and the two people who answer, each a portrait with a name and a role.pages: azienda · single useoptions: pad: default / 3xs / xs / slists: paragraphs, people
Contatti

Idealmac è guidata da un team che unisce competenze tecniche e conoscenza del processo produttivo.

Giovanni Lavista

Direttore generale

Events listevents-listThe fairs, three columns wide and two columns to a fair (D197): odd fairs on the left two, even on the right two, each a pair of equal columns — the pictures and the name — centred on each other, with the words ranged towards the page's edge. The name and its line sit over one rule (D199).pages: fiere-ed-eventi · single useoptions: pad: default / 3xs / xs / slists: events

Interpack

Processing & packaging

7-13 maggio 2026
Dusseldorf-Germania

Pages rebuilt from the patterns

Each page is composed only from spec/patterns.json, spec/styles.json and spec/tokens.json, with the original copy (pages/*.json). Header, footer and cookie banner are left to the platform.

PageSectionsOpenScreenshots
Azienda — Idealmachero → page-title → intro → approach-grid → values-band → peoplerebuilt pageoriginal · rebuilt (1280px)
Fiere ed eventi — Idealmachero → page-title → events-listrebuilt pageoriginal · rebuilt (1280px)
Idealmac — Tecnologie per l'industria alimentarehero → page-title → intro → seam → product-band → seam → card-row → product-familyrebuilt pageoriginal · rebuilt (1280px)
Macchinari accessori — Idealmachero → page-title → band-split → band-split → band-split → band-split → band-split → band-split → band-splitrebuilt pageoriginal · rebuilt (1280px)
Presse per gallette e snack non fritti — Idealmachero → page-title → feature-grid → seam → band-split → seam → mould-tablerebuilt pageoriginal · rebuilt (1280px)
Servizi — Idealmachero → page-title → band-split → band-split → band-splitrebuilt pageoriginal · rebuilt (1280px)

Validation

Integrity, coverage of the site's values, contrast, layout and a page-by-page comparison with the original.

Overall: FAIL — full report in analysis/report.md.

Integrity0 errors, 0 warnings
Colors covered (exact or merged, by uses)100%
Font sizes within ±4px (by uses)100%
Spacing within ±4px (by uses)96%
Radii within ±4px (by uses)29%
Contrast pairs passing7/9
Layout checks with issues0/18
Portability notes13

Site values not kept as they were

Values farther than ΔE 8 or ±4px from any token: merged by a decision, replaced by the flow model, or written inside a component (decorative overlays).

KindSite valueUsesNearest tokenDifference
Spacing86px3space.8xl-6px
Spacing90px2space.9xl+6px
Spacing103px1space.9xl-7px
Spacing107px1space.10xl+5px
Spacing117px1space.10xl-5px
Spacing138px1space.12xl+6px
Spacing170px1space.13xl+22px
Radius20px5radius.m-5px

Layout

PageViewportHeightOverflowMisaligned sections
index390655400
index1280531300
index2400487700
azienda390448200
azienda1280430200
azienda2400341400
presse-per-gallette390814700
presse-per-gallette1280583900
presse-per-gallette2400563400
macchinari-accessori390699200
macchinari-accessori1280569700
macchinari-accessori2400613300
servizi390352400
servizi1280292700
servizi2400333800
fiere-ed-eventi390591900
fiere-ed-eventi1280601400
fiere-ed-eventi2400618900

Original vs rebuilt (1280px)

indexoriginal 4079px (with header and footer) · rebuilt 5313px
Original
Rebuilt from the spec
aziendaoriginal 3139px (with header and footer) · rebuilt 4302px
Original
Rebuilt from the spec
presse-per-galletteoriginal 5328px (with header and footer) · rebuilt 5839px
Original
Rebuilt from the spec
macchinari-accessorioriginal 5012px (with header and footer) · rebuilt 5697px
Original
Rebuilt from the spec
servizioriginal 2717px (with header and footer) · rebuilt 2927px
Original
Rebuilt from the spec
fiere-ed-eventioriginal 5789px (with header and footer) · rebuilt 6014px
Original
Rebuilt from the spec

Portability notes for the platform skill

WhereNote
*, ::before, ::after@media (prefers-reduced-motion): check support in the target's media-query UI
*, ::before, ::afteranimation: needs the @keyframes shipped separately
a@media (prefers-reduced-motion): check support in the target's media-query UI
:focus-visible:focus-visible: element-level global style; check the target accepts pseudo-class selectors
.main:has(.media-column--fit-cover):has(): a relational selector; GenerateBlocks has no UI for it, ship it as CSS
.l-switcher--middle:not(.band-row--tight)pseudo-element (::before/::after): supported as a nested selector; check the content property
.site-navpseudo-element (::before/::after): supported as a nested selector; check the content property
.heading-rulepseudo-element (::before/::after): supported as a nested selector; check the content property
.btn@media (prefers-reduced-motion): check support in the target's media-query UI
.tab-rowpseudo-element (::before/::after): supported as a nested selector; check the content property
.leaf-listpseudo-element (::before/::after): supported as a nested selector; check the content property
.feature--dividedpseudo-element (::before/::after): supported as a nested selector; check the content property
.value--dividedpseudo-element (::before/::after): supported as a nested selector; check the content property