# סיווג שורות — `_classify_line()`

כל שורה של content מה-MD עוברת דרך `_classify_line()` שמחזירה
`(kind, clean_text)`. הקטגוריה מכתיבה איזה סגנון Word יוחל.

## טבלת הקטגוריות

| kind | regex | clean_text | נמפה ל-style |
|------|--------|-----------|--------------|
| `label_heading` | `^\s*\*\*([^\n*]+?):\*\*\s*$` | `"$1"` | `Heading 2` |
| `label_heading` (plain) | `^\s*([^\n:]{2,40}):\s*$` | `"$1"` | `Heading 2` |
| `inline_label` | `^\s*\*\*([^\n*]+?):\*\*\s+(.+)$` | `"$1\x00$2"` | `Normal` + bold label + value |
| `numbered` | `^\s*(\d+)[.)]\s+(.+)$` | `"$2"` | `List Paragraph` |
| `bullet` | `^\s*[\-\u2022\*\u25CF\u25E6]\s+(.+)$` | `"$1"` | `Normal` (marker stripped) |
| `heb_letter` | `^\s*\([א-ת]\)\s+` | **full line** (marker kept) | `List Paragraph` + `_strip_numpr()` |
| `plain` | fallback | line | `Normal` |

## סדר הבדיקות (חשוב!)

```
1. STANDALONE_LABEL_RE      (**X:**)
2. INLINE_LABEL_RE          (**X:** value)
3. NUMBERED_LINE_RE         (1. X)
4. BULLET_LINE_RE           (- X) + re-check inside:
     4a. STANDALONE inside → label_heading
     4b. INLINE inside → inline_label
5. HEB_LETTER_LINE_RE       ((א) X)
6. PLAIN_LABEL_RE           (X:)  — last because it's broad
7. plain
```

## דוגמאות מהשטח

### input: `- **נקודות פתוחות:**`
- `BULLET_LINE_RE` תופס → `inner = "**נקודות פתוחות:**"`
- `STANDALONE_LABEL_RE` על ה-inner → `label_heading`, text = `"נקודות פתוחות"`
- יוצא כ-Heading 2.

### input: `- **נקודות פתוחות:** האם המקדם...`
- `BULLET_LINE_RE` תופס → inner = `"**נקודות פתוחות:** האם..."`
- `INLINE_LABEL_RE` על ה-inner → `inline_label`
- יוצא כ-Normal עם label "נקודות פתוחות:" bold + value רגיל.

### input: `1. **שאלה עקרונית:** האם נספח...`
- `NUMBERED_LINE_RE` תופס → `"**שאלה עקרונית:** האם נספח..."`
- יוצא כ-List Paragraph. ה-`**...**` בתוכו יעובד על ידי
  `_add_runs_with_inline_bold()` (bold inline run).

### input: `(א) נספח הבינוי של תכנית...`
- `HEB_LETTER_LINE_RE` תופס
- יוצא כ-List Paragraph עם `_strip_numpr()` — כי המחבר כבר כתב "(א)".

### input: `העורר טוען כי:`
- לא תואם regex ספציפי
- `PLAIN_LABEL_RE` תופס (23 תווים, מסתיים ב-`:`)
- יוצא כ-Heading 2.

### input: `פסקה ארוכה: עם עוד תוכן ופסיק, וסוגיה מורכבת.`
- `PLAIN_LABEL_RE` לא תופס (יותר מ-40 תווים לפני `:`)
- נשאר `plain` → Normal.

## למה הגבלת `PLAIN_LABEL_RE` ל-`{2,40}`

בלי הגבלה, כל פסקה עם `:` במקום כלשהו הייתה הופכת ל-Heading 2. דוגמה
שצריך למנוע:
```
טענה חשובה כאן: היא שהוועדה שגתה בכל אופן.
```
אין כאן כוונה לכותרת — `:` הוא חלק ממשפט. ההגבלה ל-40 תווים מסננת את
רוב המקרים האלה כי רוב headings אמיתיים הם קצרים.

40 תווים זה ניחוש — אפשר לכוון אם מגלים false positives/negatives.

## inline bold — `_add_runs_with_inline_bold()`

אחרי סיווג, הטקסט עדיין יכול להכיל `**word**` באמצע. הפונקציה מחלקת
את המחרוזת ל-runs מתחלפים:

```
"העורר טוען **שהתוצאה** שגויה"
→ [
    Run("העורר טוען ", bold=None),
    Run("שהתוצאה", bold=True),
    Run(" שגויה", bold=None),
  ]
```

כל run מסומן RTL בנפרד. יוצא ב-Word עם הדגש המקומי בלבד על המילה
`שהתוצאה`.

## השלמת התמונה

```
md content
    ↓ splitlines()
for line in lines:
    ↓ _classify_line(line)
    → (kind, clean_text)
    ↓ _emit_content_line(doc, line)
    → paragraph with chosen style
    ↓ _add_runs_with_inline_bold(paragraph, clean_text)
    → runs with inline **bold** rendered
    ↓ _mark_run_rtl / _mark_paragraph_rtl
    → Hebrew renders in David (cs slot)
```

## הוספת קטגוריה חדשה

אם יש דפוס שלא מזוהה ורצוי למפות אותו:

1. הוסף regex constant (למעלה בקובץ, אחרי הקיימים).
2. הוסף branch ב-`_classify_line()` לפי הסדר הנכון (ספציפי לפני כללי).
3. הוסף branch ב-`_emit_content_line()` עם הסגנון המתאים.
4. הוסף test case ב-references/line-classification.md (כאן).
5. הרץ על תיק מייצג (למשל 8070-25) וראה שהתוצאה נכונה.
