
How CEOs are rethinking growth in a slower market
Leaders are reallocating capital toward resilience.
Application standards
Use this chapter when you are building an Alix web page. It defines the layouts, spacing and responsive behaviour implemented by the components. Start with the 50% centre line, choose a section layout, then apply the page gutter and section spacing shown here. Thin gold lines mark the measurements drawn over each specimen.
The 50% line is the website's main alignment. In the hero, the X in the wordmark lands on that line and the two media panels meet there. Reuse the same split in the sections below so text, media and colour fields share one vertical edge. Use an off-centre division only for the two-thirds layout or the fixed title rail.



Measurements are shown from the md breakpoint (768px). At phone width the grid has not split yet, so there is nothing to measure.
HomepageHeader calculates the wordmark width so the X lands at 50% (left + width × 0.8417 = 50%). The two media panels and the block below meet on the same line.The page has one width constraint: --page-max-width at 1728px. Below it, the page follows the viewport. Above it, the whole page centres with equal margins. Apply the cap once, at the page root; never apply it to individual sections.
Viewport below 1728px
The canvas follows the viewport width.
Viewport at 1728px
The canvas reaches its cap.
Viewport above 1728px
The canvas holds 1728px and centres. The outer margins grow evenly.
--page-max-width (1728px), set once on the page root. Individual sections never carry it, and full-bleed sections still reach the canvas edges.Every section uses one of two outer-spacing modes. An editorial section uses SiteContainer for the page gutter and adds its own vertical padding. A full-bleed section spans the canvas and adds no outer spacing. The component then owns its internal space: Surface-based blocks use p-10, PostRowBlock uses py-10, and Hero media fills its grid tracks.
SiteContainerResponsive page padding: px-6 md:px-10 lg:px-16.Use on editorial content. It does not set the 1728px page cap.site shell · not in the registry, copy the classesSectionWrapperSection semantics and an anchor target. No spacing.Leave it unpadded so full-bleed blocks can meet edge to edge.@alix/sectionWrapperSurfaceInternal tile padding (p-10 · 40px) and surface colours.Adds no margin or outer padding.@alix/surfaceUse one of the six layouts shown below. Halves suit text with media; quarters suit card rows; thirds suit three equal cards; the 25/25/50 split adds two supporting tiles; two-thirds creates a main and an aside; the rail keeps a fixed title or filter column beside fluid content. Each row names the implementation and its breakpoint behaviour.
Text beside media, or two equal text tiles (Layout=50/50).
TextAndMedia · TextAndText
1 col → md 2
Card rows and post feeds.
PostRowBlock columns={4}
1 col → md 2 → lg 4
Three-card rows when the content suits three equal items.
PostRowBlock columns={3}
1 col → md 2 → lg 3
Two supporting tiles beside a half-width media tile (Layout=25/25/50).
TextAndMedia textTileVariant="split"
1 col → md the full split
A primary content area beside a narrower aside.
no block · raw Grid + col-span (W8)
1 col → md 2 equal → lg 2:1 (the asymmetry appears at lg)
A 256px title or filter rail beside fluid content.
PeopleGrid
stacked below lg → rail w-64 · 256px from lg

Measurements are shown from the md breakpoint (768px). At phone width the grid has not split yet, so there is nothing to measure.
<TextAndMedia
textTileVariant="titleAndText"
textTile={{
bgColor: "default",
sectionTitle: {
title: "Turnaround, led from the front.",
description: "Senior operators work with your team, find the cash…",
align: "start",
},
buttonGroup: {},
}}
media={{ type: "image", src: cms.image, alt: "" }}
ratio="16/9"
/>TextAndMedia implements halves with <Grid columns={2} gap="none">. The tiles meet on the centre line; Surface provides the p-10 internal padding.
Leaders are reallocating capital toward resilience.


Resilience as a capability, not a cost centre.

Measurements are shown from the md breakpoint (768px). At phone width the grid has not split yet, so there is nothing to measure.
<PostRowBlock
columns={4}
contentCards={posts.map((p) => ({
variant: "news",
alignment: "vertical",
media: { type: "image", src: p.cover, alt: "" },
tagline: p.category,
title: p.title,
excerpt: p.summary,
href: p.href,
}))}
/>PostRowBlock implements a quartered card row using gap="none" and hairline dividers between cards. It renders two columns from md and four from lg.Measurements are shown from the md breakpoint (768px). At phone width the grid has not split yet, so there is nothing to measure.
<TextAndText
contentLeft={{
bgColor: "primary",
sectionTitle: {
title: "The plan becomes weekly actions.",
description: "Senior teams assign an owner to each action…",
align: "start",
},
buttonGroup: {},
}}
contentRight={{
bgColor: "greyGradient",
sectionTitle: {
variant: "largeText",
description: "Every action has an owner.",
align: "start",
},
buttonGroup: {},
}}
/>TextAndText uses the same 50/50 grid. Each Surface keeps its own padding, so the two colour fields need no gap between them.Write the phone layout first. At md (768px), most sections move from one column to two and the page gutter increases. At lg (1024px), card rows reach three or four columns and the gutter increases again. Grid accepts one to four equal columns and applies those changes for you.
| CSS variable | rem · px | Prefix | Effect on page layout |
|---|---|---|---|
| --breakpoint-sm | 40rem · 640px | sm: | Use only for small-control adjustments. Page layout starts changing at md. |
| --breakpoint-md | 48rem · 768px | md: | Primary page breakpoint. Grids move to two columns; display type, page gutter and section padding step up. |
| --breakpoint-lg | 64rem · 1024px | lg: | Secondary page breakpoint. Card rows reach their full column count and the page gutter reaches 64px. |
| --breakpoint-xl | 80rem · 1280px | xl: | Available from Tailwind. Used only by a small number of components. |
| --breakpoint-2xl | 96rem · 1536px | 2xl: | Available from Tailwind. No current page layout depends on it. |
--breakpoint-smsm:Use only for small-control adjustments. Page layout starts changing at md.
--breakpoint-mdmd:Primary page breakpoint. Grids move to two columns; display type, page gutter and section padding step up.
--breakpoint-lglg:Secondary page breakpoint. Card rows reach their full column count and the page gutter reaches 64px.
--breakpoint-xlxl:Available from Tailwind. Used only by a small number of components.
--breakpoint-2xl2xl:Available from Tailwind. No current page layout depends on it.
Grid columns={4} renders one column by default, two from md, and four from lg. Start with the base layout, then add complexity at wider breakpoints with md:grid-cols-2 and lg:grid-cols-4. Do not write a desktop layout and override it for smaller screens.SiteContainer provides the horizontal page gutter: 24px at base, 40px at md and 64px at lg. Use it around editorial content. Do not wrap full-bleed sections in it. Apply the 1728px maximum width to the whole page, not to individual sections.
SiteContainer padding: px-6 md:px-10 lg:px-16 (24 → 40 → 64). Full-bleed sections skip this wrapper. Each block then applies its own internal spacing.px-6 md:px-10 lg:px-1624 · 40 · 64pxHorizontal padding supplied by SiteContainer. Apply it to editorial content, not full-bleed sections.py-20 md:py-2880 · 112pxVertical padding set on each editorial section.p-1040pxInternal padding supplied by Surface-based tiles. Other blocks own their internal spacing.mx-auto w-full max-w-page1728pxApply once to the page root. The page fills the viewport up to 1728px, then centres.Editorial sections and CMS blocks use different spacing rules. Give an editorial section py-20 md:py-28 and, when it follows another editorial section, a border-t. Render CMS blocks next to one another with no added outer gap or padding. Each block owns its internal spacing: Surface-based blocks use p-10 and PostRowBlock uses py-10. SectionTitle controls the gap between its own title and content.

py-20 md:py-28). CMS blocks meet with no added gap. Surface-based blocks use p-10; PostRowBlock owns py-10.Use Grid for equal columns and gaps from the spacing scale. Use Container to limit the line length of prose inside a section. Use raw Tailwind utilities only for layouts Grid does not support, such as two-thirds. Apply max-w-page once, at the page root.
columns sets the final equal-column count. gap selects a value from the spacing scale. Two columns suit split sections; four suit card rows. The component supports up to four columns.
import { Grid } from "@/components/ui/grid";
// columns step up by breakpoint; gap defaults to "xl" (40px)
// columns={2} → 1 → md:2 (split sections)
// columns={4} → 1 → md:2 → lg:4 (card rows)
// columns={3} → 1 → md:2 → lg:3 (three-card rows)
<Grid columns={4} gap="lg">
<Card /> <Card /> <Card /> <Card />
</Grid>| gap token | px | class |
|---|---|---|
| gap="none" | 0 | gap-0 |
| gap="xxs" | 4 | gap-1 |
| gap="xs" | 8 | gap-2 |
| gap="sm" | 12 | gap-3 |
| gap="md" | 16 | gap-4 |
| gap="lg" | 24 | gap-6 |
| gap="xl" | 40 | gap-10 |
Container limits the width of its children for readable prose. It does not change the width of the surrounding section. Choose a width from the --container-* scale.
import { Container } from "@/components/ui/container";
<Container width="lg">
<article>Long-form copy, capped for readability.</article>
</Container>container-sm 384 · container-md 448 · container-lg 512 · container-xl 576 · container-2xl 672 (px)
If a layout needs unequal tracks, use raw Tailwind utilities. Keep the same mobile-first rule: one column at base, then md: and lg:. Use column spans for a wider main and narrower aside.
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2">Main, two of three columns</div>
<div>Aside, the remaining column</div>
</div><Grid columns={2} gap="none"> internally. Do not add another layout wrapper around them.Use a flex layout for the fixed title rail. Below lg, stack the rail above the content. From lg, set the rail to w-64 (256px) and let the content take the remaining width.
<div className="flex flex-col gap-8 lg:flex-row lg:items-start">
<Stack gap="lg" className="lg:w-64 lg:shrink-0">…rail…</Stack>
<div className="flex-1">…content…</div>
</div>Apply the page cap at the root. Add the slot-based Hero, then editorial sections with their own gutter and vertical padding. Render CMS blocks separately with no added outer spacing. The navbar and footer exist in Figma but do not yet ship in the registry. SiteContainer is also pending, so use its gutter classes directly.
import { HomepageHeader, HomepageHeaderSlide } from "@/components/homeHeader";
import { SectionTitle } from "@/components/sectionTitle";
import { TextAndMedia } from "@/components/textAndMediaBlock";
import { TextAndText } from "@/components/textAndText";
import PostRowBlock from "@/components/postRowBlock";
export default function Page() {
return (
// canvas: full-bleed to --page-max-width, then centres
<main className="mx-auto w-full max-w-page">
{/* 0 · Navbar: designed, not yet in the registry (roadmap) */}
{/* 1 · Hero: slot-based section, media is yours (next/image, video) */}
<HomepageHeader>
<HomepageHeaderSlide
left={<img src={cms.hero.left} alt="" className="size-full object-cover" />}
right={<video src={cms.hero.loop} autoPlay muted loop playsInline
className="size-full object-cover" />}
/>
</HomepageHeader>
{/* 2 · Editorial section: vertical padding + page gutter */}
<section className="border-t border-border py-20 md:py-28">
<div className="px-6 md:px-10 lg:px-16">
<SectionTitle headingSize="lg" headingTag="h2" align="start" title="Latest thinking" />
</div>
</section>
{/* 3 · Full-bleed CMS blocks: adjacent, with no added outer spacing */}
<PostRowBlock columns={4} contentCards={cms.posts} />
<TextAndMedia {...cms.textAndMedia} />
<TextAndText {...cms.textAndText} />
{/* 4 · Footer: designed, not yet in the registry (roadmap) */}
</main>
);
}These studies show how the approved divisions can combine across a page. Use them to check the balance and sequence of a composition, not as fixed page templates. Every study uses only the layouts from W4.
Choose by contract, not folder alone. Components, elements and slot-based patterns use ReactNode slots when engineers need composition. CMS-shaped patterns and most sections take serialisable data for direct CMS mapping. Hero is the deliberate exception: it is a section by scale but uses media slots. The component directory documents the contract for each item.
Most page errors come from applying a valid rule at the wrong layer. Keep 50/50 layouts centred, use SiteContainer only for editorial content, apply the 1728px cap only to the page, and build from the phone layout up.