| """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 |
|
|
|
|
| |
|
|
| @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" |
|
|
|
|
| |
|
|
| @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" |
|
|
|
|
| |
|
|
| @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%" |
|
|
|
|
| |
|
|
| @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%" |
|
|
|
|
| |
|
|
| @dataclass(frozen=True) |
| class Bullets: |
| """Bullet characters used throughout the handbook.""" |
|
|
| primary: str = "\u27A2" |
| benefit: str = "\u2022" |
| career: str = "disc" |
|
|
|
|
| |
|
|
| BLOCK_TYPES = ( |
| "heading_1", |
| "heading_2", |
| "paragraph", |
| "bullet_list", |
| "note", |
| "table", |
| "enrollment_steps", |
| "school_profile", |
| "university_summary", |
| "toc", |
| "cover", |
| "full_page_image", |
| ) |
|
|
|
|
| |
|
|
| @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] = {} |
| |
| for fname in Colors.__dataclass_fields__: |
| v[f"--hb-{fname.replace('_', '-')}"] = getattr(self.colors, fname) |
| |
| 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 |
| |
| 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 |
| |
| v["--hb-bullet-char"] = f'"{self.bullets.primary}"' |
| return v |
|
|
|
|
| |
| THEME = HandbookTheme() |
|
|