File size: 6,043 Bytes
ec94fc1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
"""Centralized handbook visual theme β€” single source of truth.

All colour values, font sizes, spacing, and rendering tokens live here.
Templates, CSS generation, and renderers reference this module instead
of hardcoding visual rules.

Spec source: ISP Handbook Enhancement Guidelines + sample PDF.
"""

from __future__ import annotations

from dataclasses import dataclass, field


# ── Colour palette ──────────────────────────────────────────────

@dataclass(frozen=True)
class Colors:
    """Every colour used in the handbook, named by purpose."""

    heading_blue: str = "#1C75BC"
    heading_green: str = "#1A9970"
    body_text: str = "#000000"
    toc_text: str = "#111111"
    note_red: str = "#C00000"
    link_blue: str = "#1C75BC"
    benefits_header_bg: str = "#00F600"
    benefits_header_fg: str = "#FFFFFF"
    benefit_item_bg: str = "#00FCFC"
    benefit_item_fg: str = "#000000"
    school_info_green: str = "#1A9970"
    table_border: str = "#333333"
    table_header_bg: str = "#E6E6E6"
    table_header_fg: str = "#333333"
    toc_dots: str = "#777777"
    muted: str = "#666666"
    note_bg: str = "#F7F8FA"
    note_border: str = "#BBBBBB"
    page_bg: str = "#FFFFFF"


# ── Typography ──────────────────────────────────────────────────

@dataclass(frozen=True)
class Typography:
    """Font families, sizes, weights, and line-heights."""

    font_family: str = "'Century Gothic', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif"
    font_size_body: str = "10pt"
    font_size_h1: str = "12pt"
    font_size_h2: str = "12pt"
    font_size_h3: str = "10pt"
    font_size_toc_heading: str = "12pt"
    font_size_toc_item: str = "10pt"
    font_size_table: str = "9.5px"
    font_size_programs_table: str = "8.5px"
    font_size_career_list: str = "8.5px"
    font_size_note: str = "9.5px"
    font_size_benefits_header: str = "10.5px"
    font_size_benefit_item: str = "10px"
    font_size_school_name: str = "12pt"
    font_size_summary_label: str = "10.5px"
    font_size_summary_value: str = "9.5px"
    font_size_qualify: str = "10px"
    line_height_body: str = "1.4"
    line_height_heading: str = "1.2"
    line_height_table: str = "1.25"


# ── Spacing / margins ──────────────────────────────────────────

@dataclass(frozen=True)
class Spacing:
    """Page geometry and element margins. All margins: 2.54cm."""

    page_margin_top: str = "2.54cm"
    page_margin_right: str = "2.54cm"
    page_margin_bottom: str = "2.54cm"
    page_margin_left: str = "2.54cm"
    paragraph_margin: str = "2px 0 8px"
    heading_margin_h1: str = "12px 0 6px"
    heading_margin_h2: str = "10px 0 4px"
    list_margin: str = "2px 0 8px 18px"
    note_padding: str = "6px 8px"
    note_margin: str = "6px 0 8px"
    table_margin: str = "6px 0 10px"
    table_cell_padding: str = "5px 6px"
    benefits_margin: str = "4px 0 4px"
    school_top_summary_width: str = "58%"
    school_top_campus_width: str = "42%"


# ── Table column widths ────────────────────────────────────────

@dataclass(frozen=True)
class ProgramTableColumns:
    """Fixed widths for the 5-column programs table."""

    program: str = "22%"
    designation: str = "14%"
    entrance_exam: str = "12%"
    career_pathways: str = "34%"
    funding: str = "18%"


# ── Bullet characters ──────────────────────────────────────────

@dataclass(frozen=True)
class Bullets:
    """Bullet characters used throughout the handbook."""

    primary: str = "\u27A2"        # ➒
    benefit: str = "\u2022"        # β€’
    career: str = "disc"           # CSS list-style-type for career lists


# ── Render-block type registry ──────────────────────────────────

BLOCK_TYPES = (
    "heading_1",
    "heading_2",
    "paragraph",
    "bullet_list",
    "note",
    "table",
    "enrollment_steps",
    "school_profile",
    "university_summary",
    "toc",
    "cover",
    "full_page_image",
)


# ── Composed theme object ──────────────────────────────────────

@dataclass(frozen=True)
class HandbookTheme:
    """Complete handbook theme β€” inject into renderers and templates."""

    colors: Colors = field(default_factory=Colors)
    typography: Typography = field(default_factory=Typography)
    spacing: Spacing = field(default_factory=Spacing)
    program_columns: ProgramTableColumns = field(default_factory=ProgramTableColumns)
    bullets: Bullets = field(default_factory=Bullets)

    def css_vars(self) -> dict[str, str]:
        """Flatten theme to CSS custom properties (--hb-*)."""
        v: dict[str, str] = {}
        # Colors
        for fname in Colors.__dataclass_fields__:
            v[f"--hb-{fname.replace('_', '-')}"] = getattr(self.colors, fname)
        # Typography
        v["--hb-font-family"] = self.typography.font_family
        v["--hb-font-size-body"] = self.typography.font_size_body
        v["--hb-font-size-h1"] = self.typography.font_size_h1
        v["--hb-font-size-h2"] = self.typography.font_size_h2
        v["--hb-line-height-body"] = self.typography.line_height_body
        # Spacing
        v["--hb-page-margin-top"] = self.spacing.page_margin_top
        v["--hb-page-margin-right"] = self.spacing.page_margin_right
        v["--hb-page-margin-bottom"] = self.spacing.page_margin_bottom
        v["--hb-page-margin-left"] = self.spacing.page_margin_left
        # Bullet
        v["--hb-bullet-char"] = f'"{self.bullets.primary}"'
        return v


# Module-level singleton
THEME = HandbookTheme()