diff --git a/app/Controllers/Opd.php b/app/Controllers/Opd.php
index 70ddeca..68deb81 100644
--- a/app/Controllers/Opd.php
+++ b/app/Controllers/Opd.php
@@ -3594,7 +3594,11 @@ class Opd extends BaseController
}
}
- $formatBlock = static function (string $label, string $value, bool $lineBreakAfterLabel = false): string {
+ // mPDF-safe vertical spacer. Using a fixed-height block in mm is more reliable
+ // than margins inside absolute-positioned containers.
+ $blockGapHtml = '
';
+
+ $formatBlock = static function (string $label, string $value, bool $lineBreakAfterLabel = false) use ($blockGapHtml): string {
$value = trim($value);
if ($value === '') {
return '';
@@ -3607,21 +3611,23 @@ class Opd extends BaseController
if ($lineBreakAfterLabel) {
// List-style sections (Complaint, Diagnosis …):
// heading on its own line, content block below with a small left indent.
- // margin-bottom:18px gives clear visual separation between consecutive sections.
- return ''
+ // explicit spacer block is appended for consistent separation in mPDF.
+ return '
'
. $headingHtml
. '
'
. $value
- . '
';
+ . '
'
+ . $blockGapHtml;
}
// Inline sections (Vitals, Investigation, Next Visit):
- // heading + value on the same line; same 18px gap after block.
- return ''
+ // heading + value on the same line; explicit spacer appended after block.
+ return '
'
. $headingHtml
. ' '
. $value
- . '
';
+ . '
'
+ . $blockGapHtml;
};
$escape = static fn (string $value): string => htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
@@ -3854,12 +3860,12 @@ class Opd extends BaseController
$medicalHtml = trim((string) ($tokens['medical'] ?? ''));
$tokens['Rx'] = $medicalHtml !== ''
- ? ''
+ ? $blockGapHtml . '' . $blockGapHtml
: '';
$tokens['rx'] = $tokens['Rx'];
// {{medical}} used directly in templates: wrap with the same top/bottom margin.
$tokens['medical'] = $medicalHtml !== ''
- ? '' . $medicalHtml . '
'
+ ? $blockGapHtml . '' . $medicalHtml . '
' . $blockGapHtml
: '';
$tokens['VitalsBlock'] = (string) ($tokens['vital_content'] ?? '');