/* * ZenQuality — client handover stylesheet * Used to render LIVRAISON.md / HANDOVER.md as a branded HTML/PDF. * Source brand tokens: zenquality.fr (CSS custom properties extracted from * the live site) — Inter (body) + Playfair Display (headings), green palette. */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:wght@400;600;700&display=swap'); :root { --green-dark: #1A3A25; --green-forest: #2D5A3D; --green-moss: #4A7C59; --green-sage: #87A878; --black-deep: #0A0A0A; --black-soft: #1A1A1A; --gray-dark: #2A2A2A; --gray-mid: #666666; --gray-light: #B0B0B0; --white-cream: #F5F0EB; --white-pure: #FFFFFF; --status-ok: #2D5A3D; --status-warn: #b58900; --status-fail: #a83232; } @page { size: A4; margin: 22mm 18mm 22mm 18mm; @top-right { content: string(doctitle); font-family: 'Inter', sans-serif; font-size: 8.5pt; color: var(--green-moss); } @bottom-right { content: counter(page) " / " counter(pages); font-family: 'Inter', sans-serif; font-size: 8.5pt; color: var(--gray-mid); } @bottom-left { content: "ZenQuality — zenquality.fr"; font-family: 'Inter', sans-serif; font-size: 8.5pt; color: var(--gray-mid); } } @page :first { margin: 0; @top-right { content: ""; } @bottom-right { content: ""; } @bottom-left { content: ""; } } * { box-sizing: border-box; } html, body { margin: 0; padding: 0; font-family: 'Inter', system-ui, -apple-system, sans-serif; font-size: 10.5pt; line-height: 1.6; color: var(--black-deep); background: var(--white-pure); } /* ============ COVER PAGE ============ */ .cover { page-break-after: always; height: 297mm; width: 210mm; padding: 35mm 22mm 22mm 22mm; background: radial-gradient(ellipse at top right, rgba(135, 168, 120, 0.18) 0%, transparent 55%), radial-gradient(ellipse at bottom left, rgba(45, 90, 61, 0.06) 0%, transparent 55%), var(--white-pure); color: var(--black-deep); position: relative; display: flex; flex-direction: column; justify-content: space-between; page: cover; } .cover-header { display: flex; align-items: flex-start; justify-content: space-between; } .cover-logo { width: 55mm; height: auto; max-height: 30mm; object-fit: contain; } .cover-tagline { font-family: 'Playfair Display', Georgia, serif; font-size: 10pt; font-style: italic; color: var(--green-forest); text-align: right; max-width: 70mm; margin-top: 6mm; } .cover-body { flex: 1; display: flex; flex-direction: column; justify-content: center; margin: -10mm 0 0 0; } .cover-eyebrow { font-family: 'Inter', sans-serif; font-size: 9pt; font-weight: 600; text-transform: uppercase; letter-spacing: 0.18em; color: var(--green-forest); margin-bottom: 6mm; } .cover-title { font-family: 'Playfair Display', Georgia, serif; font-size: 34pt; font-weight: 700; color: var(--black-deep); line-height: 1.1; margin: 0 0 6mm 0; letter-spacing: -0.015em; } .cover-subtitle { font-family: 'Playfair Display', Georgia, serif; font-size: 16pt; font-weight: 400; font-style: italic; color: var(--green-forest); margin: 0 0 18mm 0; max-width: 140mm; } .cover-meta { font-family: 'Inter', sans-serif; font-size: 10.5pt; color: var(--black-deep); line-height: 1.9; border-left: 2px solid var(--green-forest); padding-left: 5mm; } .cover-meta strong { color: var(--green-forest); font-weight: 600; display: inline-block; min-width: 25mm; } .cover-meta a { color: var(--black-deep); text-decoration: underline; text-decoration-color: rgba(45, 90, 61, 0.6); } .cover-footer { font-family: 'Inter', sans-serif; font-size: 9pt; color: var(--green-forest); border-top: 1px solid rgba(45, 90, 61, 0.4); padding-top: 5mm; display: flex; justify-content: space-between; } .cover-footer a { color: var(--black-deep); text-decoration: none; font-weight: 500; } .cover-footer a:hover { color: var(--green-forest); } /* ============ DOCUMENT BODY ============ */ .content { string-set: doctitle attr(data-title); } h1 { font-family: 'Playfair Display', Georgia, serif; font-size: 22pt; font-weight: 700; color: var(--green-dark); margin: 0 0 6mm 0; page-break-after: avoid; string-set: doctitle content(); } h2 { font-family: 'Playfair Display', Georgia, serif; font-size: 17pt; font-weight: 600; color: var(--green-forest); margin: 12mm 0 4mm 0; padding-bottom: 2.5mm; border-bottom: 2px solid var(--green-sage); page-break-before: always; page-break-after: avoid; } .content > h2:first-of-type, h2.no-break, h2.continue { page-break-before: auto; } h3 { font-family: 'Playfair Display', Georgia, serif; font-size: 13.5pt; font-weight: 600; color: var(--green-forest); margin: 8mm 0 3mm 0; page-break-after: avoid; } h4 { font-family: 'Inter', sans-serif; font-size: 10pt; font-weight: 600; color: var(--green-moss); margin: 6mm 0 2mm 0; text-transform: uppercase; letter-spacing: 0.06em; page-break-after: avoid; } p { margin: 0 0 3mm 0; } p, li { orphans: 3; widows: 3; } ul, ol { margin: 0 0 3mm 0; padding-left: 6mm; } ul li, ol li { margin: 0 0 1.5mm 0; } ul li::marker { color: var(--green-moss); } ol li::marker { color: var(--green-moss); font-weight: 600; } /* ============ PAGE-BREAK HARDENING ============ */ /* Keep each list item intact across pages — prevents the bullet/marker from staying on the previous page while the text reflows to the next (historical cause of "trailing word + leading bullet" superposition). */ li { page-break-inside: avoid; break-inside: avoid; } /* Tie the first block after a heading to the heading itself so a page break never splits "heading + intro" or "heading + first list item" across two pages. */ h1 + p, h1 + ul, h1 + ol, h2 + p, h2 + ul, h2 + ol, h3 + p, h3 + ul, h3 + ol, h4 + p, h4 + ul, h4 + ol { page-break-before: avoid; break-before: avoid; } strong { color: var(--green-dark); font-weight: 600; } em { color: var(--green-forest); font-style: italic; } blockquote { border-left: 3px solid var(--green-moss); padding: 3mm 5mm; margin: 4mm 0; background: var(--white-cream); color: var(--gray-dark); font-style: italic; page-break-inside: avoid; } blockquote p:last-child { margin-bottom: 0; } a { color: var(--green-forest); text-decoration: underline; text-decoration-thickness: 0.5pt; text-underline-offset: 1.5pt; } a:hover { color: var(--green-dark); } code { font-family: 'JetBrains Mono', 'Fira Code', Menlo, monospace; font-size: 9pt; background: var(--white-cream); padding: 0.5mm 1.5mm; border-radius: 1mm; color: var(--green-dark); } pre { background: var(--white-cream); padding: 4mm 5mm; border-radius: 1.5mm; border-left: 3px solid var(--green-moss); font-size: 8.5pt; line-height: 1.45; white-space: pre-wrap; word-wrap: break-word; page-break-inside: avoid; margin: 4mm 0; } pre code { background: none; padding: 0; color: var(--black-deep); font-size: inherit; } /* ============ TABLES ============ */ table { width: 100%; border-collapse: collapse; margin: 4mm 0; font-size: 9.5pt; page-break-inside: avoid; } th { font-family: 'Inter', sans-serif; background: var(--green-forest); color: var(--white-pure); text-align: left; padding: 2.5mm 3mm; font-weight: 600; font-size: 9pt; text-transform: uppercase; letter-spacing: 0.04em; border-bottom: 0; } td { padding: 2.5mm 3mm; border-bottom: 1px solid var(--green-sage); vertical-align: top; } tr:nth-child(even) td { background: rgba(245, 240, 235, 0.55); } /* Numeric / status cols of score tables auto-detected via header text */ table th:nth-child(2), table th:nth-child(3), table th:nth-child(4), table td:nth-child(2), table td:nth-child(3), table td:nth-child(4) { text-align: right; font-variant-numeric: tabular-nums; } table th:last-child, table td:last-child { text-align: center; } /* ============ CHECKLISTS ============ */ ul.checklist, ul.task-list { list-style: none; padding-left: 0; } ul.checklist li, ul.task-list li { padding-left: 8mm; position: relative; margin-bottom: 2.5mm; } ul.checklist li::before, ul.task-list li::before, li.task-list-item::before { content: "☐"; position: absolute; left: 0; color: var(--green-moss); font-size: 12pt; line-height: 1; } /* Pandoc GFM emits
, ) that follow it untouched.
Earlier rule `li input[type="checkbox"] + *` mistakenly absolutely-
positioned the first element sibling after the checkbox, yanking links
and code spans out of flow and overlapping adjacent content. */
li > input[type="checkbox"] {
appearance: none;
-webkit-appearance: none;
display: inline-block;
width: 3mm;
height: 3mm;
margin: 0 1.5mm 0 0;
border: 0.4mm solid var(--green-moss);
border-radius: 0.5mm;
vertical-align: middle;
background: transparent;
}
li > input[type="checkbox"]:checked {
background: var(--green-forest);
border-color: var(--green-forest);
}
/* ============ CALLOUTS ============ */
.callout {
padding: 4mm 6mm;
margin: 4mm 0;
border-radius: 2mm;
page-break-inside: avoid;
font-size: 10pt;
}
.callout.info {
background: var(--white-cream);
border-left: 4px solid var(--green-moss);
}
.callout.warn {
background: #fdf6e3;
border-left: 4px solid var(--status-warn);
}
.callout.success {
background: rgba(135, 168, 120, 0.14);
border-left: 4px solid var(--green-forest);
}
.callout-title {
font-family: 'Inter', sans-serif;
font-weight: 600;
font-size: 10pt;
color: var(--green-dark);
margin-bottom: 2mm;
text-transform: uppercase;
letter-spacing: 0.04em;
}
/* ============ SECTION DIVIDERS ============ */
hr {
border: none;
border-top: 1px solid var(--green-sage);
margin: 8mm 0;
}
/* ============ STATUS PILLS (used by text replacement) ============ */
.status-ok { color: var(--status-ok); font-weight: 600; }
.status-warn { color: var(--status-warn); font-weight: 600; }
.status-fail { color: var(--status-fail); font-weight: 600; }
/* ============ LINK BEHAVIOR IN PRINT ============ */
@media print {
a[href^="http"]::after {
content: " (" attr(href) ")";
font-size: 7.5pt;
color: var(--gray-mid);
font-style: italic;
font-weight: 400;
}
a[href^="#"]::after,
a[href^="mailto:"]::after,
a[href^="tel:"]::after,
a.bare-url::after,
.cover a::after,
table a::after { content: ""; }
/* Belt-and-braces: prevent the ::after URL pseudo-element from breaking
across pages or columns and overlapping the next block (root cause of
historical "text superposition" bugs on long URLs). */
a[href^="http"]::after {
white-space: nowrap;
page-break-before: avoid;
page-break-inside: avoid;
break-before: avoid;
break-inside: avoid;
}
}