CBDF Specification: Styles Section
Version 1.0 (Phase II)Document: 03-Styles-Section • Date: 2026-03-25
1. Overview
The Styles section defines all visual formatting used in the document. It sits between the first FS (end of Meta) and the second FS (start of Text). It begins with a 4-byte LE length prefix.
Structure (after the FS marker):
[Length: 4 bytes LE] [Layout byte] [Background style] GS [sub-tables...]
The 4-byte length prefix counts the section content bytes only (everything after the length field itself). This is consistent with Document Structure spec Section 4A.
The section is organized into sub-tables separated by GS (0x1D). Each sub-table defines a category of styles (text, container, border, etc.). Empty sub-tables are represented as GS immediately followed by the next GS or FS.
If the meta section contains a "default style set" flag (value >= 1), the styles section may be empty or contain only delta overrides.
2. Layout Byte (1 byte)
The first byte of the Styles section selects one of 256 predefined page layouts. Each layout defines the arrangement of top-level panels.
Bit layout:
| Bits | Field | Description |
|---|---|---|
| 0-3 | Panel existence flags | Bit 0: Header, Bit 1: Footer, Bit 2: Left aside, Bit 3: Right aside |
| 4-5 | Column count | 00=1, 01=2, 10=3, 11=4 columns |
| 6-7 | Row count | 00=1, 01=2, 10=3, 11=4 rows |
The Main panel is ALWAYS implied (never needs a flag).
Common Layout Reference Table
| Hex | Binary | Panels | Cols | Rows | Description |
|---|---|---|---|---|---|
0x00 | 0000 0000 | Main | 1 | 1 | Single content area |
0x01 | 0000 0001 | Header+Main | 1 | 1 | Header bar + body |
0x03 | 0000 0011 | Hdr+Ftr+Main | 1 | 1 | Header + footer |
0x07 | 0000 0111 | Hdr+Ftr+Left+Main | 1 | 1 | With left sidebar |
0x0F | 0000 1111 | All panels+Main | 1 | 1 | Full layout |
0x11 | 0001 0001 | Header+Main | 2 | 1 | Header + 2 cols |
0x1F | 0001 1111 | All panels+Main | 2 | 1 | Full + 2 cols |
0x2F | 0010 1111 | All panels+Main | 3 | 1 | Full + 3 cols |
0x3F | 0011 1111 | All panels+Main | 4 | 1 | Full + 4 cols |
0x4F | 0100 1111 | All panels+Main | 1 | 2 | Full + 2 rows |
0xFF | 1111 1111 | All panels+Main | 4 | 4 | Maximum layout |
Decoding example for 0x3F (0011 1111):
- Bits 0-3 =
1111: Header(1) + Footer(1) + Left(1) + Right(1) - Bits 4-5 =
11: 4 columns - Bits 6-7 =
00: 1 row - Result: All panels, 4 columns, 1 row.
Click diagram to open full size in new tab
3. Sub-Table Header Byte
A Note About "Tiering"
In this spec, "tiering" means that a style record can have different sizes depending on how many properties you need.
Think of it like ordering a burger: small, medium, or large. You don't pay for the large if you only need the small.
Example with Text Styles:
- Base tier (8 bytes): Font, size, bold/italic flags, text color, background color. This covers 90% of use cases.
- Extended tier (12 bytes): Everything in base PLUS text shadow, letter spacing, line height. For documents that need more control.
- Rare tier (16 bytes): Everything in extended PLUS font effects (flames, glow, etc.), text direction (RTL), word spacing. Only for heavily styled documents.
Key Rule
ALL text styles in a document use the SAME tier. If even one style needs a shadow, then ALL text styles in that document are extended tier (12 bytes each). This is signaled by the 2-bit tier field in the sub-table header byte.
This saves bytes because most simple emails only need base tier styles. A plain email with 3 text styles uses 3 x 8 = 24 bytes for text styling. If we forced the rare tier for everyone, it would be 3 x 16 = 48 bytes -- double the size for properties nobody used.
The trade-off: if you have 10 simple styles and 1 style that needs a shadow, all 11 become extended tier. You "waste" 4 bytes on each of the 10 simple ones. But this is still better than per-record variable sizing, which makes parsing much harder.
Click diagram to open full size in new tab
Each sub-table (after the layout byte and background style) begins with a 1-byte header:
| Bits | Field | Description |
|---|---|---|
| 0-1 | Tier | 00=Base, 01=Base+Extended, 10=Base+Extended+Rare, 11=Reserved |
| 2-7 | Count | 0-63 records in this sub-table |
This is ONE byte, appearing ONCE per sub-table. ALL records in that sub-table use the SAME tier size. The parser reads the header, knows the record size and count, and parses all records sequentially.
Not all sub-tables use tiering. Sub-tables with fixed-size records (shadow, composite, nav bar) only use the count field (bits 2-7) with tier bits = 00.
4. Sub-Table Order
Sub-tables appear in this fixed order, separated by GS (0x1D):
| Position | Sub-table | Tiered? | Ref Name |
|---|---|---|---|
| 1 | Container Background Styles | Yes | BG |
| 2 | Container Border Styles | No | BORDER |
| 3 | Container Spacing Styles | No | SPACING |
| 4 | Container Shadow Styles | No | SHADOW |
| 5 | Container Composite Styles | No | COMPOSITE |
| 6 | Text Styles | Yes | TEXT |
| 7 | Font Effects | No | EFFECT |
| 8 | Nav Bar Styles | No | NAV |
| 9 | Table Styles | No | TABLE |
| 10 | Image Definitions | No | IMAGE |
| 11 | Frame/iFrame Definitions | No | FRAME |
| 12 | Reserved (Form Styles) | - | (Phase III) |
Empty sub-table: [GS] immediately (header byte with count=0, or just GS).
The page-level background style appears BEFORE the first GS and after the layout byte. It is a single record (not a sub-table) using the Container Background Style format.
Click diagram to open full size in new tab
5. Page-Level Background Style
Immediately after the layout byte, before the first GS, sits a single background style record for the entire page (Layer 0). This uses the Container Background Style format (see Section 6A).
If the first byte after the layout byte is GS, the page has no background style (transparent/default).
6. Style Record Formats
6A. Container Background Style
All tiers are FIXED SIZE to maintain sub-table indexability. Gradient color stops have a fixed count per tier (0, 2, or 4 stops).
Base tier (6 bytes) -- no gradient:
| Byte | Field | Description |
|---|---|---|
| 0-1 | Background color | R5G6B5 or transparency code |
| 2-3 | Background image ID | 0=none; references built-in image table |
| 4 | Color opacity | 0-255 maps to 0-100%. Controls BG color over BG image. |
| 5 | Image flags | Bit 0: Repeat X, Bit 1: Repeat Y, Bit 2: Fixed, Bit 3: Cover, Bit 4: Contain |
Extended tier (12 bytes) -- 2 gradient stops:
| Byte | Field | Description |
|---|---|---|
| 0-5 | (Same as base tier) | |
| 6 | Gradient type + angle | Types: 0=none, 1=linear, 2=radial, 3=conic. Angle: 0-15 (22.5° steps) |
| 7 | Reserved | Must be 0 |
| 8-9 | Gradient color stop 1 | R5G6B5 |
| 10-11 | Gradient color stop 2 | R5G6B5 |
Rare tier (20 bytes) -- 4 gradient stops + animation:
| Byte | Field | Description |
|---|---|---|
| 0-11 | (Same as extended tier) | |
| 12-13 | Gradient color stop 3 | R5G6B5 |
| 14-15 | Gradient color stop 4 | R5G6B5 |
| 16 | Animation type + speed | Types: 0=none, 1=scroll, 2=pulse, 3=fade, 4=parallax. Speed: 0-15 |
| 17 | Event flags | Bit 0: On hover change, Bit 1: On click change |
| 18 | Hover style ID | References another BG style |
| 19 | User-settable flag | Bit 0: User's browser may override this style |
Gradient Stop Limits
Base tier = 0 stops, Extended = 2, Rare = 4. If a design needs more than 4 gradient stops, use overlapping containers with different gradient backgrounds.
6B. Container Border Style (9 bytes, fixed)
| Byte | Field | Description |
|---|---|---|
| 0-1 | Border color | R5G6B5 |
| 2-3 | Outside-of-border color | R5G6B5 or transparency |
| 4-5 | Border thickness per side | Bits 0-3: Top, 4-7: Right, 8-11: Bottom, 12-15: Left (0-15 px each) |
| 6-8 | Corner radius | 6 bits each (0-50%): UL, UR, LR, LL |
6C. Container Spacing Style (4 bytes, fixed)
All values are percentages of the parent container.
| Byte | Field | Description |
|---|---|---|
| 0-1 | Margin per side | Bits 0-3: Top, 4-7: Right, 8-11: Bottom, 12-15: Left (0-15%) |
| 2-3 | Padding per side | Bits 0-3: Top, 4-7: Right, 8-11: Bottom, 12-15: Left (0-15%) |
The "Egg" (content area) size = container - margin - border - padding. If top/bottom margin = 0, it inherits the left margin value.
6D. Container Shadow Style (4 bytes, fixed)
| Byte | Field | Description |
|---|---|---|
| 0-1 | Shadow color | R5G6B5 |
| 2-3 | Shadow geometry | Bits 0-5: X offset, 6-11: Y offset (signed 6-bit), 12-15: Blur (0-15 px) |
6E. Container Composite Style (5 bytes, fixed)
Cross-references into the other container sub-tables:
| Byte | Field | Description |
|---|---|---|
| 0 | Background style ID | Index into BG sub-table |
| 1 | Border style ID | Index into BORDER sub-table |
| 2 | Spacing style ID | Index into SPACING sub-table |
| 3 | Shadow style ID | Index into SHADOW sub-table |
| 4 | Overflow + Layer ID | Bits 0-1: Overflow (0=visible, 1=hidden, 2=scroll, 3=auto), Bits 2-7: Layer ID (0-63) |
This design allows sharing: multiple panels can reference the same border style, same spacing, etc. without duplication.
6F. Text Style
Base tier (8 bytes):
| Byte | Field | Description |
|---|---|---|
| 0-1 | Font ID | Bits 0-11: Font family index (0-4095), Bits 12-15: Sub-variant hints |
| 2 | Font size | 1-255 points; 0 = inherit/default |
| 3 | Flags | Bit 0: Bold, 1: Italic, 2: Underline, 3: Strikethrough, 4: Subscript, 5: Superscript, 6-7: Alignment |
| 4-5 | Text foreground color | R5G6B5 or transparency code |
| 6-7 | Text background color | R5G6B5 or transparency code |
Extended tier adds 4 bytes (total 12):
| Byte | Field | Description |
|---|---|---|
| 8-9 | Text shadow | Bits 0-5: X offset, 6-11: Y offset (signed 6-bit), 12-15: Blur (0-15 px) |
| 10 | Letter spacing | Signed int8, -128 to +127, in 0.1em units |
| 11 | Line height | 0=auto; 1-255 = value/10 (0.1 to 25.5) |
Rare tier adds 4 bytes (total 16):
| Byte | Field | Description |
|---|---|---|
| 12 | Font effect + intensity | Bits 0-3: Effect ID (0-15), Bits 4-7: Intensity (0-15) |
| 13 | Transform + direction + word spacing | Bits 0-1: Transform, 2-3: Direction, 4-7: Word spacing |
| 14-15 | Effect color | R5G6B5 (used by glow/shadow/gradient effects) |
6G. Font Effect (4 bytes, fixed)
For effects that need more parameters than the 4+4 bits in the text style rare tier. Referenced by effect ID 15 ("Custom") in the text style.
| Byte | Field | Description |
|---|---|---|
| 0 | Effect type | Same IDs as text style effect (0-15) |
| 1 | Parameter A | Effect-specific (e.g., blur radius, density) |
| 2 | Parameter B | Effect-specific (e.g., animation speed, angle) |
| 3 | Animation flags | Bits 0-3: Speed, 4-5: Loop mode, 6-7: Reserved |
6H. Nav Bar Style (12 bytes, fixed)
| Byte | Field | Description |
|---|---|---|
| 0 | Orientation + item count | Bit 0: Orientation (0=horiz, 1=vert), Bits 1-7: Max items (0-127) |
| 1-2 | Background color | R5G6B5 |
| 3-4 | Item background color | R5G6B5 |
| 5-6 | Item hover color | R5G6B5 |
| 7 | Item text style ID | Index into TEXT sub-table |
| 8 | Divider + spacing | Bits 0-1: Divider style, Bits 2-7: Item spacing (0-63 px) |
| 9 | Active item text style ID | For "current page" indicator |
| 10 | Collapse breakpoint | 0=never; 1-255 = viewport width / 4 (4-1020px in 4px steps) |
| 11 | Icon/text mode | Bits 0-1: Mode (0=text, 1=icon, 2=icon+text, 3=auto) |
6I. Table Style (6 bytes, fixed)
| Byte | Field | Description |
|---|---|---|
| 0 | Table flags | Bit 0: Border collapse, 1: Header row, 2: Stripe odd rows, 3-4: Width mode |
| 1 | Border spacing | 0-255 px (if not collapsed) |
| 2-3 | Stripe color | R5G6B5 (alternating row color if bit 2 set) |
| 4 | Header row text style ID | |
| 5 | Body cell text style ID |
6J. Image Definition (8 bytes, fixed)
Defines how an image is displayed. Does NOT contain image data (that's in the Resources section).
| Byte | Field | Description |
|---|---|---|
| 0 | Image source type | 0=Resource, 1=Built-in, 2=AI-generated |
| 1 | Resource ID | For type 0: resource ID; type 1: built-in ID; type 2: 0 |
| 2-3 | Width | 16 bits, in pixels; 0=auto |
| 4-5 | Height | 16 bits, in pixels; 0=auto |
| 6 | Fit mode + alignment | Bits 0-2: Fit, 3-4: H-align, 5-6: V-align |
| 7 | Border style ID | Index into BORDER sub-table; 0=no border |
When the Resources section is skipped (abortable download), the renderer uses Width and Height to display a placeholder box.
6K. Frame/iFrame Definition (8 bytes, fixed)
| Byte | Field | Description |
|---|---|---|
| 0 | Source type | 0=External URL, 1=Inline CBDF sub-document |
| 1 | Resource ID | For type 1; or 0 if URL provided inline |
| 2-3 | Width | 16 bits, in pixels |
| 4-5 | Height | 16 bits, in pixels |
| 6 | Border style ID | Index into BORDER sub-table |
| 7 | Sandbox flags | Bit 0: Allow scripts, 1: Allow links, 2: Allow forms, 3: Allow popups |
7. Complete Styles Section Layout
[Length: 4 bytes LE]
[Layout byte: 1 byte]
[Page background: BG record (variable if extended/rare tier)]
GS [Header: 1B] RS [BG record 0] RS [BG record 1] ... -- BG styles
GS [Header: 1B] RS [Border 0] RS [Border 1] ... -- Border styles
GS [Header: 1B] RS [Spacing 0] RS [Spacing 1] ... -- Spacing styles
GS [Header: 1B] RS [Shadow 0] RS [Shadow 1] ... -- Shadow styles
GS [Header: 1B] RS [Composite 0] RS [Composite 1] ... -- Composite styles
GS [Header: 1B] RS [Text 0] RS [Text 1] ... -- Text styles
GS [Header: 1B] RS [Effect 0] RS [Effect 1] ... -- Font effects
GS [Header: 1B] RS [Nav 0] RS [Nav 1] ... -- Nav bar styles
GS [Header: 1B] RS [Table 0] RS [Table 1] ... -- Table styles
GS [Header: 1B] RS [Image 0] RS [Image 1] ... -- Image defs
GS [Header: 1B] RS [Frame 0] RS [Frame 1] ... -- Frame defs
GS -- Reserved (forms)
Minimum styles section (no styles, just structure):
[0x00 0x00 0x00 0x02] [0x00] [GS][GS][GS][GS][GS][GS][GS][GS][GS][GS][GS][GS]
(4-byte length=2, layout byte=0x00 (main only, no bg), 12 empty GS markers)
8. Record Size Summary
All style record types have FIXED sizes within each tier. There are no variable-length records. This guarantees that the parser can index into any sub-table by offset: record_offset = header_size + (index * record_size).
| Style Type | Base | Extended | Rare |
|---|---|---|---|
| Container Background | 6 B | 12 B | 20 B |
| Container Border | 9 B | - | - |
| Container Spacing | 4 B | - | - |
| Container Shadow | 4 B | - | - |
| Container Composite | 5 B | - | - |
| Text Style | 8 B | 12 B | 16 B |
| Font Effect | 4 B | - | - |
| Nav Bar | 12 B | - | - |
| Table | 6 B | - | - |
| Image Definition | 8 B | - | - |
| Frame Definition | 8 B | - | - |
- means that style type does not use tiering (only one fixed size).