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()
|