zenquality.css 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*
  2. * ZenQuality — client handover stylesheet
  3. * Used to render LIVRAISON.md / HANDOVER.md as a branded HTML/PDF.
  4. * Source brand tokens: zenquality.fr (CSS custom properties extracted from
  5. * the live site) — Inter (body) + Playfair Display (headings), green palette.
  6. */
  7. @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:wght@400;600;700&display=swap');
  8. :root {
  9. --green-dark: #1A3A25;
  10. --green-forest: #2D5A3D;
  11. --green-moss: #4A7C59;
  12. --green-sage: #87A878;
  13. --black-deep: #0A0A0A;
  14. --black-soft: #1A1A1A;
  15. --gray-dark: #2A2A2A;
  16. --gray-mid: #666666;
  17. --gray-light: #B0B0B0;
  18. --white-cream: #F5F0EB;
  19. --white-pure: #FFFFFF;
  20. --status-ok: #2D5A3D;
  21. --status-warn: #b58900;
  22. --status-fail: #a83232;
  23. }
  24. @page {
  25. size: A4;
  26. margin: 22mm 18mm 22mm 18mm;
  27. @top-right {
  28. content: string(doctitle);
  29. font-family: 'Inter', sans-serif;
  30. font-size: 8.5pt;
  31. color: var(--green-moss);
  32. }
  33. @bottom-right {
  34. content: counter(page) " / " counter(pages);
  35. font-family: 'Inter', sans-serif;
  36. font-size: 8.5pt;
  37. color: var(--gray-mid);
  38. }
  39. @bottom-left {
  40. content: "ZenQuality — zenquality.fr";
  41. font-family: 'Inter', sans-serif;
  42. font-size: 8.5pt;
  43. color: var(--gray-mid);
  44. }
  45. }
  46. @page :first {
  47. margin: 0;
  48. @top-right { content: ""; }
  49. @bottom-right { content: ""; }
  50. @bottom-left { content: ""; }
  51. }
  52. * { box-sizing: border-box; }
  53. html, body {
  54. margin: 0;
  55. padding: 0;
  56. font-family: 'Inter', system-ui, -apple-system, sans-serif;
  57. font-size: 10.5pt;
  58. line-height: 1.6;
  59. color: var(--black-deep);
  60. background: var(--white-pure);
  61. }
  62. /* ============ COVER PAGE ============ */
  63. .cover {
  64. page-break-after: always;
  65. height: 297mm;
  66. width: 210mm;
  67. padding: 35mm 22mm 22mm 22mm;
  68. background:
  69. radial-gradient(ellipse at top right, rgba(135, 168, 120, 0.18) 0%, transparent 55%),
  70. radial-gradient(ellipse at bottom left, rgba(45, 90, 61, 0.06) 0%, transparent 55%),
  71. var(--white-pure);
  72. color: var(--black-deep);
  73. position: relative;
  74. display: flex;
  75. flex-direction: column;
  76. justify-content: space-between;
  77. page: cover;
  78. }
  79. .cover-header {
  80. display: flex;
  81. align-items: flex-start;
  82. justify-content: space-between;
  83. }
  84. .cover-logo {
  85. width: 55mm;
  86. height: auto;
  87. max-height: 30mm;
  88. object-fit: contain;
  89. }
  90. .cover-tagline {
  91. font-family: 'Playfair Display', Georgia, serif;
  92. font-size: 10pt;
  93. font-style: italic;
  94. color: var(--green-forest);
  95. text-align: right;
  96. max-width: 70mm;
  97. margin-top: 6mm;
  98. }
  99. .cover-body {
  100. flex: 1;
  101. display: flex;
  102. flex-direction: column;
  103. justify-content: center;
  104. margin: -10mm 0 0 0;
  105. }
  106. .cover-eyebrow {
  107. font-family: 'Inter', sans-serif;
  108. font-size: 9pt;
  109. font-weight: 600;
  110. text-transform: uppercase;
  111. letter-spacing: 0.18em;
  112. color: var(--green-forest);
  113. margin-bottom: 6mm;
  114. }
  115. .cover-title {
  116. font-family: 'Playfair Display', Georgia, serif;
  117. font-size: 34pt;
  118. font-weight: 700;
  119. color: var(--black-deep);
  120. line-height: 1.1;
  121. margin: 0 0 6mm 0;
  122. letter-spacing: -0.015em;
  123. }
  124. .cover-subtitle {
  125. font-family: 'Playfair Display', Georgia, serif;
  126. font-size: 16pt;
  127. font-weight: 400;
  128. font-style: italic;
  129. color: var(--green-forest);
  130. margin: 0 0 18mm 0;
  131. max-width: 140mm;
  132. }
  133. .cover-meta {
  134. font-family: 'Inter', sans-serif;
  135. font-size: 10.5pt;
  136. color: var(--black-deep);
  137. line-height: 1.9;
  138. border-left: 2px solid var(--green-forest);
  139. padding-left: 5mm;
  140. }
  141. .cover-meta strong {
  142. color: var(--green-forest);
  143. font-weight: 600;
  144. display: inline-block;
  145. min-width: 25mm;
  146. }
  147. .cover-meta a {
  148. color: var(--black-deep);
  149. text-decoration: underline;
  150. text-decoration-color: rgba(45, 90, 61, 0.6);
  151. }
  152. .cover-footer {
  153. font-family: 'Inter', sans-serif;
  154. font-size: 9pt;
  155. color: var(--green-forest);
  156. border-top: 1px solid rgba(45, 90, 61, 0.4);
  157. padding-top: 5mm;
  158. display: flex;
  159. justify-content: space-between;
  160. }
  161. .cover-footer a {
  162. color: var(--black-deep);
  163. text-decoration: none;
  164. font-weight: 500;
  165. }
  166. .cover-footer a:hover { color: var(--green-forest); }
  167. /* ============ DOCUMENT BODY ============ */
  168. .content {
  169. string-set: doctitle attr(data-title);
  170. }
  171. h1 {
  172. font-family: 'Playfair Display', Georgia, serif;
  173. font-size: 22pt;
  174. font-weight: 700;
  175. color: var(--green-dark);
  176. margin: 0 0 6mm 0;
  177. page-break-after: avoid;
  178. string-set: doctitle content();
  179. }
  180. h2 {
  181. font-family: 'Playfair Display', Georgia, serif;
  182. font-size: 17pt;
  183. font-weight: 600;
  184. color: var(--green-forest);
  185. margin: 12mm 0 4mm 0;
  186. padding-bottom: 2.5mm;
  187. border-bottom: 2px solid var(--green-sage);
  188. page-break-before: always;
  189. page-break-after: avoid;
  190. }
  191. .content > h2:first-of-type,
  192. h2.no-break,
  193. h2.continue {
  194. page-break-before: auto;
  195. }
  196. h3 {
  197. font-family: 'Playfair Display', Georgia, serif;
  198. font-size: 13.5pt;
  199. font-weight: 600;
  200. color: var(--green-forest);
  201. margin: 8mm 0 3mm 0;
  202. page-break-after: avoid;
  203. }
  204. h4 {
  205. font-family: 'Inter', sans-serif;
  206. font-size: 10pt;
  207. font-weight: 600;
  208. color: var(--green-moss);
  209. margin: 6mm 0 2mm 0;
  210. text-transform: uppercase;
  211. letter-spacing: 0.06em;
  212. page-break-after: avoid;
  213. }
  214. p { margin: 0 0 3mm 0; }
  215. p, li { orphans: 3; widows: 3; }
  216. ul, ol { margin: 0 0 3mm 0; padding-left: 6mm; }
  217. ul li, ol li { margin: 0 0 1.5mm 0; }
  218. ul li::marker { color: var(--green-moss); }
  219. ol li::marker { color: var(--green-moss); font-weight: 600; }
  220. /* ============ PAGE-BREAK HARDENING ============ */
  221. /* Keep each list item intact across pages — prevents the bullet/marker
  222. from staying on the previous page while the text reflows to the next
  223. (historical cause of "trailing word + leading bullet" superposition). */
  224. li {
  225. page-break-inside: avoid;
  226. break-inside: avoid;
  227. }
  228. /* Tie the first block after a heading to the heading itself so a page
  229. break never splits "heading + intro" or "heading + first list item"
  230. across two pages. */
  231. h1 + p, h1 + ul, h1 + ol,
  232. h2 + p, h2 + ul, h2 + ol,
  233. h3 + p, h3 + ul, h3 + ol,
  234. h4 + p, h4 + ul, h4 + ol {
  235. page-break-before: avoid;
  236. break-before: avoid;
  237. }
  238. strong { color: var(--green-dark); font-weight: 600; }
  239. em { color: var(--green-forest); font-style: italic; }
  240. blockquote {
  241. border-left: 3px solid var(--green-moss);
  242. padding: 3mm 5mm;
  243. margin: 4mm 0;
  244. background: var(--white-cream);
  245. color: var(--gray-dark);
  246. font-style: italic;
  247. page-break-inside: avoid;
  248. }
  249. blockquote p:last-child { margin-bottom: 0; }
  250. a { color: var(--green-forest); text-decoration: underline; text-decoration-thickness: 0.5pt; text-underline-offset: 1.5pt; }
  251. a:hover { color: var(--green-dark); }
  252. code {
  253. font-family: 'JetBrains Mono', 'Fira Code', Menlo, monospace;
  254. font-size: 9pt;
  255. background: var(--white-cream);
  256. padding: 0.5mm 1.5mm;
  257. border-radius: 1mm;
  258. color: var(--green-dark);
  259. }
  260. pre {
  261. background: var(--white-cream);
  262. padding: 4mm 5mm;
  263. border-radius: 1.5mm;
  264. border-left: 3px solid var(--green-moss);
  265. font-size: 8.5pt;
  266. line-height: 1.45;
  267. white-space: pre-wrap;
  268. word-wrap: break-word;
  269. page-break-inside: avoid;
  270. margin: 4mm 0;
  271. }
  272. pre code { background: none; padding: 0; color: var(--black-deep); font-size: inherit; }
  273. /* ============ TABLES ============ */
  274. table {
  275. width: 100%;
  276. border-collapse: collapse;
  277. margin: 4mm 0;
  278. font-size: 9.5pt;
  279. page-break-inside: avoid;
  280. }
  281. th {
  282. font-family: 'Inter', sans-serif;
  283. background: var(--green-forest);
  284. color: var(--white-pure);
  285. text-align: left;
  286. padding: 2.5mm 3mm;
  287. font-weight: 600;
  288. font-size: 9pt;
  289. text-transform: uppercase;
  290. letter-spacing: 0.04em;
  291. border-bottom: 0;
  292. }
  293. td {
  294. padding: 2.5mm 3mm;
  295. border-bottom: 1px solid var(--green-sage);
  296. vertical-align: top;
  297. }
  298. tr:nth-child(even) td { background: rgba(245, 240, 235, 0.55); }
  299. /* Numeric / status cols of score tables auto-detected via header text */
  300. table th:nth-child(2),
  301. table th:nth-child(3),
  302. table th:nth-child(4),
  303. table td:nth-child(2),
  304. table td:nth-child(3),
  305. table td:nth-child(4) {
  306. text-align: right;
  307. font-variant-numeric: tabular-nums;
  308. }
  309. table th:last-child,
  310. table td:last-child {
  311. text-align: center;
  312. }
  313. /* ============ CHECKLISTS ============ */
  314. ul.checklist,
  315. ul.task-list {
  316. list-style: none;
  317. padding-left: 0;
  318. }
  319. ul.checklist li,
  320. ul.task-list li {
  321. padding-left: 8mm;
  322. position: relative;
  323. margin-bottom: 2.5mm;
  324. }
  325. ul.checklist li::before,
  326. ul.task-list li::before,
  327. li input[type="checkbox"] + *,
  328. li.task-list-item::before {
  329. content: "☐";
  330. position: absolute;
  331. left: 0;
  332. color: var(--green-moss);
  333. font-size: 12pt;
  334. line-height: 1;
  335. }
  336. input[type="checkbox"] {
  337. display: none;
  338. }
  339. input[type="checkbox"]:checked + label::before {
  340. content: "☑";
  341. color: var(--green-forest);
  342. }
  343. /* ============ CALLOUTS ============ */
  344. .callout {
  345. padding: 4mm 6mm;
  346. margin: 4mm 0;
  347. border-radius: 2mm;
  348. page-break-inside: avoid;
  349. font-size: 10pt;
  350. }
  351. .callout.info {
  352. background: var(--white-cream);
  353. border-left: 4px solid var(--green-moss);
  354. }
  355. .callout.warn {
  356. background: #fdf6e3;
  357. border-left: 4px solid var(--status-warn);
  358. }
  359. .callout.success {
  360. background: rgba(135, 168, 120, 0.14);
  361. border-left: 4px solid var(--green-forest);
  362. }
  363. .callout-title {
  364. font-family: 'Inter', sans-serif;
  365. font-weight: 600;
  366. font-size: 10pt;
  367. color: var(--green-dark);
  368. margin-bottom: 2mm;
  369. text-transform: uppercase;
  370. letter-spacing: 0.04em;
  371. }
  372. /* ============ SECTION DIVIDERS ============ */
  373. hr {
  374. border: none;
  375. border-top: 1px solid var(--green-sage);
  376. margin: 8mm 0;
  377. }
  378. /* ============ STATUS PILLS (used by text replacement) ============ */
  379. .status-ok { color: var(--status-ok); font-weight: 600; }
  380. .status-warn { color: var(--status-warn); font-weight: 600; }
  381. .status-fail { color: var(--status-fail); font-weight: 600; }
  382. /* ============ LINK BEHAVIOR IN PRINT ============ */
  383. @media print {
  384. a[href^="http"]::after {
  385. content: " (" attr(href) ")";
  386. font-size: 7.5pt;
  387. color: var(--gray-mid);
  388. font-style: italic;
  389. font-weight: 400;
  390. }
  391. a[href^="#"]::after,
  392. a[href^="mailto:"]::after,
  393. a[href^="tel:"]::after,
  394. a.bare-url::after,
  395. .cover a::after,
  396. table a::after { content: ""; }
  397. /* Belt-and-braces: prevent the ::after URL pseudo-element from breaking
  398. across pages or columns and overlapping the next block (root cause of
  399. historical "text superposition" bugs on long URLs). */
  400. a[href^="http"]::after {
  401. white-space: nowrap;
  402. page-break-before: avoid;
  403. page-break-inside: avoid;
  404. break-before: avoid;
  405. break-inside: avoid;
  406. }
  407. }