From 9eeb6575d0f423bff050dc740bbc1c6a55de1300 Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Mon, 31 Aug 2026 17:32:32 +0100 Subject: [PATCH 1/2] feat(templates): give CvSkill the level as the document words it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A rated skill could say how much — a number in [0, 1] a preset draws as dots or a meter — or it could say it in words by not being a skill at all and living in a RowsSection instead. It could not say both, which is why CharcoalGold sets its languages as rows: that design writes "Native" and "B2 – Upper Intermediate" out, and a number could not carry them back. A design that shows a rating and names it in the same line had nowhere to go. CvSkill now carries `note`, a plain string blank when absent, reachable through CvSkill.of(name, level, note). The two channels stay separate because a number cannot carry a wording and a wording cannot be measured into a meter; a preset draws whichever it has room for, or both. The two-argument constructor and both existing factories are kept explicitly, so existing calls compile and link unchanged and every skill built through them still carries no note. --- CHANGELOG.md | 13 ++++ .../templates/cv/data/CvSkillNoteTest.java | 63 +++++++++++++++++++ .../document/templates/cv/data/CvSkill.java | 38 ++++++++++- 3 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/data/CvSkillNoteTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index f2e77d060..1e16148fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ follow semantic versioning; release dates are ISO 8601. ### Public API +- **`CvSkill` carries the level as the document words it.** A rated skill could say how + much — a number in `[0, 1]` a preset draws as dots or a meter — or it could say it in + words by not being a skill at all and living in a `RowsSection` instead. It could not + say both, which is why `CharcoalGold` sets its languages as rows: that design writes + "Native" and "B2 – Upper Intermediate" out, and a number could not carry them back. A + design that shows a rating *and* names it had nowhere to go. `CvSkill` now carries + `note` — a plain string, blank when absent, like the fields beside it — reachable + through `CvSkill.of(name, level, note)`. The two channels stay separate because a + number cannot carry a wording and a wording cannot be measured into a meter; a preset + draws whichever it has room for, or both. The two-argument constructor and both + existing factories are kept explicitly, so existing calls compile and link unchanged + and every skill built through them still carries no note. + - **The structured invoice model carries what a second sheet needs.** It landed with one consumer, `ConsultingInvoice`, and a model shaped around one document is a model nobody has tested. Fitting a second published invoice to it found six things it could diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/data/CvSkillNoteTest.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/data/CvSkillNoteTest.java new file mode 100644 index 000000000..a76b79a1c --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/data/CvSkillNoteTest.java @@ -0,0 +1,63 @@ +package com.demcha.compose.document.templates.cv.data; + +import org.junit.jupiter.api.Test; + +import java.util.OptionalDouble; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Pins the written-out level on {@link CvSkill}: what it normalises, and that + * every way of building a skill that predates it still compiles and still + * produces a skill without one. + */ +class CvSkillNoteTest { + + @Test + void aSkillCarriesTheLevelAsTheDocumentWordsIt() { + CvSkill skill = new CvSkill("Spanish", OptionalDouble.of(0.6), + "Professional Working"); + assertThat(skill.note()).isEqualTo("Professional Working"); + assertThat(skill.level()).hasValue(0.6); + } + + @Test + void theFactoryTakesBothChannels() { + CvSkill skill = CvSkill.of("French", 0.4, "Basic"); + assertThat(skill.note()).isEqualTo("Basic"); + assertThat(skill.level()).hasValue(0.4); + } + + @Test + void anAbsentNoteIsBlankRatherThanNull() { + assertThat(new CvSkill("Java", OptionalDouble.empty(), null).note()).isEmpty(); + assertThat(new CvSkill("Java", OptionalDouble.empty(), " ").note()).isEmpty(); + } + + @Test + void aNoteIsTrimmed() { + assertThat(new CvSkill("Java", OptionalDouble.empty(), " Native ").note()) + .isEqualTo("Native"); + } + + @Test + void theTwoArgumentConstructorStillBuildsASkillWithoutANote() { + CvSkill skill = new CvSkill("Java", OptionalDouble.of(0.9)); + assertThat(skill.note()).isEmpty(); + assertThat(skill.level()).hasValue(0.9); + } + + @Test + void theNameOnlyAndLevelFactoriesStillBuildSkillsWithoutANote() { + assertThat(CvSkill.of("Java").note()).isEmpty(); + assertThat(CvSkill.of("Java").level()).isEmpty(); + assertThat(CvSkill.of("Java", 0.5).note()).isEmpty(); + assertThat(CvSkill.of("Java", 0.5).level()).hasValue(0.5); + } + + @Test + void aSkillGroupBuiltFromNamesCarriesNoNotes() { + SkillGroup group = SkillGroup.of("Languages", "Java", "Kotlin"); + assertThat(group.entries()).allSatisfy(skill -> assertThat(skill.note()).isEmpty()); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/data/CvSkill.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/data/CvSkill.java index 6ab5e3b28..1f1590061 100644 --- a/templates/src/main/java/com/demcha/compose/document/templates/cv/data/CvSkill.java +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/data/CvSkill.java @@ -15,11 +15,18 @@ * empty level, so name-only renderers are completely unaffected by the * level channel.

* + *

The note is the level written out — "Native", "B2 – Upper + * Intermediate", "3 years" — for the designs that show a rating and name it + * in the same line. It is a separate channel from {@link #level} because a + * number cannot carry a wording and a wording cannot be measured into a + * meter; a preset draws whichever of the two it has room for, or both.

+ * * @param name non-blank skill label * @param level optional proficiency in {@code [0, 1]}; empty when * unspecified + * @param note the level as the document words it; blank when unspecified */ -public record CvSkill(String name, OptionalDouble level) { +public record CvSkill(String name, OptionalDouble level, String note) { /** * Validates that both fields are non-null, trims {@code name} and @@ -29,6 +36,7 @@ public record CvSkill(String name, OptionalDouble level) { public CvSkill { Objects.requireNonNull(name, "name"); Objects.requireNonNull(level, "level"); + note = note == null ? "" : note.trim(); name = name.trim(); if (name.isBlank()) { throw new IllegalArgumentException("name must not be blank"); @@ -42,6 +50,17 @@ public record CvSkill(String name, OptionalDouble level) { } } + /** + * Backward-compatible constructor for callers that predate the written-out + * level. + * + * @param name non-blank skill label + * @param level optional proficiency in {@code [0, 1]} + */ + public CvSkill(String name, OptionalDouble level) { + this(name, level, ""); + } + /** * Skill with no proficiency level. * @@ -49,7 +68,7 @@ public record CvSkill(String name, OptionalDouble level) { * @return a {@code CvSkill} carrying an empty level */ public static CvSkill of(String name) { - return new CvSkill(name, OptionalDouble.empty()); + return new CvSkill(name, OptionalDouble.empty(), ""); } /** @@ -61,6 +80,19 @@ public static CvSkill of(String name) { */ public static CvSkill of(String name, double level) { return new CvSkill(name, - OptionalDouble.of(Math.max(0.0, Math.min(1.0, level)))); + OptionalDouble.of(Math.max(0.0, Math.min(1.0, level))), ""); + } + + /** + * Skill with a proficiency level and the wording that names it. + * + * @param name non-blank skill label + * @param level proficiency, clamped into {@code [0, 1]} + * @param note the level as the document words it + * @return a {@code CvSkill} carrying both channels + */ + public static CvSkill of(String name, double level, String note) { + return new CvSkill(name, + OptionalDouble.of(Math.max(0.0, Math.min(1.0, level))), note); } } From 065423f2efa86528834709b2455725b4bd29d72c Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Mon, 31 Aug 2026 17:53:15 +0100 Subject: [PATCH 2/2] feat(templates): add the Slate Orange masthead-and-rail CV preset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A one-page sheet built as a full-bleed slate band over a two-column body: an orange monogram tile beside the name, the role line and a tracked specialism strip, with the contact lines across an orange hairline; then a narrow column of marked competencies, trophied achievements, rated languages and closing facts, beside a wide column carrying the profile, the roles held on a rail, and a credentials footer. It ports a published standalone template onto the existing CvDocument, and is the first preset to use CvSkill.note: its language rows show a rating and name it on the same line, which is the pair the model could not carry before. The four fills that reach a paper edge — the slate band, the orange tile and the two column dividers — are page backgrounds rather than section fills, because a fill on a section is bounded by its content. Every horizontal pair inside a body column is a table with fixed widths: a row cannot nest in a row cell and both columns are cells, and where a cell needs several stacked lines it holds a single-column table of its own. Seven berths reach their sections by title, including a specialism berth whose body is drawn and whose title is not. As on the presets before it a link is drawn as its own label with the address behind it, the one deliberate departure from the ported sheet at 2,100 of 2,173,720 pixels, and a role or a degree becomes a link when its entry carries one. Guarded by a smoke test, an exact layout snapshot and a pixel-parity gate; the examples showcase gains `cv-slate-orange-v2`. --- CHANGELOG.md | 26 + assets/readme/examples/cv-slate-orange-v2.pdf | Bin 0 -> 51757 bytes .../demcha/examples/GenerateAllExamples.java | 2 + .../examples/support/ShowcaseMetadata.java | 1 + .../support/SlateOrangeSampleData.java | 207 ++ .../templates/cv/v2/SlateOrangeExample.java | 51 + .../cv/presets/SlateOrangeFixtures.java | 206 ++ .../SlateOrangeLayoutSnapshotTest.java | 32 + .../cv/presets/SlateOrangeSmokeTest.java | 277 +++ .../presets/SlateOrangeVisualParityTest.java | 41 + .../cv-v2/slate_orange_layout.json | 2147 +++++++++++++++++ .../cv-v2-layered/slate_orange-page-0.png | Bin 0 -> 155530 bytes .../templates/cv/presets/SlateOrange.java | 245 ++ .../cv/presets/SlateOrangeAside.java | 267 ++ .../cv/presets/SlateOrangeIcons.java | 114 + .../templates/cv/presets/SlateOrangeMain.java | 398 +++ .../cv/presets/SlateOrangeMasthead.java | 304 +++ .../cv/presets/SlateOrangeStyles.java | 342 +++ .../cv/presets/SlateOrangeWidgets.java | 162 ++ .../cv/slate-orange/icons/achievement.svg | 1 + .../cv/slate-orange/icons/availability.svg | 1 + .../cv/slate-orange/icons/calendar.svg | 1 + .../cv/slate-orange/icons/communication.svg | 1 + .../templates/cv/slate-orange/icons/crm.svg | 1 + .../slate-orange/icons/customer-service.svg | 1 + .../templates/cv/slate-orange/icons/email.svg | 1 + .../cv/slate-orange/icons/linkedin.svg | 1 + .../cv/slate-orange/icons/location.svg | 1 + .../cv/slate-orange/icons/office-suite.svg | 1 + .../cv/slate-orange/icons/operations.svg | 1 + .../templates/cv/slate-orange/icons/phone.svg | 1 + .../cv/slate-orange/icons/problem-solving.svg | 1 + .../cv/slate-orange/icons/relocation.svg | 1 + .../cv/slate-orange/icons/remote-work.svg | 1 + .../cv/slate-orange/icons/reporting.svg | 1 + .../templates/cv/slate-orange/icons/sales.svg | 1 + .../cv/slate-orange/icons/time-management.svg | 1 + 37 files changed, 4840 insertions(+) create mode 100644 assets/readme/examples/cv-slate-orange-v2.pdf create mode 100644 examples/src/main/java/com/demcha/examples/support/SlateOrangeSampleData.java create mode 100644 examples/src/main/java/com/demcha/examples/templates/cv/v2/SlateOrangeExample.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeFixtures.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeLayoutSnapshotTest.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeSmokeTest.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeVisualParityTest.java create mode 100644 qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/slate_orange_layout.json create mode 100644 qa/src/test/resources/visual-baselines/cv-v2-layered/slate_orange-page-0.png create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrange.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeAside.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeIcons.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMain.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMasthead.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeStyles.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeWidgets.java create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/achievement.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/availability.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/calendar.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/communication.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/crm.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/customer-service.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/email.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/linkedin.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/location.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/office-suite.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/operations.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/phone.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/problem-solving.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/relocation.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/remote-work.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/reporting.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/sales.svg create mode 100644 templates/src/main/resources/templates/cv/slate-orange/icons/time-management.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e16148fc..32a558537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,32 @@ follow semantic versioning; release dates are ISO 8601. ### Templates +- **A masthead-and-rail CV preset: `SlateOrange`.** A one-page sheet built as a + full-bleed slate band over a two-column body: an orange monogram tile beside the name, + the role line and a tracked specialism strip, with the contact lines across an orange + hairline; then a narrow column of marked competencies, trophied achievements, rated + languages and closing facts, beside a wide column carrying the profile, the roles held + on a rail, and a credentials footer of education and certifications. Ships as + `cv.presets.SlateOrange` on the existing `CvDocument` model, porting the rendered + layout of a published standalone template; it is the first preset to use + `CvSkill.note`, which its language rows need to show a rating and name it on the same + line. The four fills that reach a paper edge — the slate band, the orange tile and the + two column dividers — are page backgrounds rather than section fills, because a fill + on a section is bounded by its content. Every horizontal pair inside a body column is + a table with fixed widths: a row cannot nest in a row cell and both columns are cells, + so mark and label, language and rating, role and dates, and the two credential columns + are all tables, and where a cell needs several stacked lines it holds a single-column + table of its own. Seven berths reach their sections by title, including a specialism + berth whose body is drawn and whose title is not. As on the presets before it, a link + is drawn as its own label with the address behind it — the one deliberate departure + from the ported sheet, measured at 2 100 of 2 173 720 pixels — and a role or a degree + becomes a link when its entry carries one. Guarded by a smoke test (including the + unknown-mark data error, an achievement with no mark falling back to the trophy, a + language with and without its wording, the monogram and the strip, the link targets, + an identity with no links, a document with nothing but an identity, and the refusal of + a CV taller than the sheet), an exact layout snapshot and a pixel-parity gate; the + examples showcase gains `cv-slate-orange-v2`. + - **A clinical CV preset in five bands: `TealPulse`.** A one-page sheet whose mark is a heart crossed by a flat pulse, beside a letter-spaced name over a contact strip divided by short rules; then a two-column body carrying the competencies as dotted diff --git a/assets/readme/examples/cv-slate-orange-v2.pdf b/assets/readme/examples/cv-slate-orange-v2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d3656f57cae7318bc30181e8173daf9436caa2f9 GIT binary patch literal 51757 zcmb5Vb8u$i*Dcr`+qToO^~Sbs+qP}n$s40%+qThh(y^`S-#0Vg+^V^C>)wA(ovO3f z+Pl_zo~nIz)h1UE5u;shzot1rZZFBjdk#F-sd4 zQzs$@F&je{QxQ{RdlS?D;GA8YObu<}VLWoCeK+HDxRbW~dnw<%LwHWF(afXezn?CJJnvcpdHcMu> zHW$CYHpBftZx{%_{8EkW3lS%%p49+OcvP#-am9K7Q)T^>y?Y-tv@Ytma^!3k- z`AS_fAL6~X@-^sh7$sZNPE!eaasG;a?aR`W#7cgrC`tsPcQoml(ZBb~di^3oaWwM1 za?@o@AIo~bo)Nzv*!Y%j9#;K%Q!(>z_^Eg0zi;xt_If`K7WKbR!gs#BYFAHstFOQA zUWL0J%KX0*$|K73Hpq`8ML%EW_DcY}@8P`{8zFw!^4+b{){($oYGn}eHvL@w@B}F+ z;;=csP=%hk*@rUnAphe0vJX3iH{~OD=a0s!o>ZL!@)j$jh)cEcSvZ8s$&*^sx%}Ts zPowmYMSwkb9fl?F9hbLGVCr$zM}KSIJb|5hhwhGy>Tacj@1k-S6%`InNq88skWtMG zZm`2L=23=D+~YDpAy?rf|Eoe@??E@>;pD)IVPfBj?+Os%(=);0=zD#5f8{Fp>iY;e zg7Umvrrq#z(mD9`r+hau!GdH?q>C)?4{xkAHZv|9{!&@cS<1_MI7(J&=7Vk)sBg~U zw*|>}E8_RL6vIWNqEWYsjJ1@E=BiAEKVz0TNwu!i6>GNyG}>D=vIw*gPTw8*s0yZv zn3s?r(4Zm=fmY>Y1J-owq)p*o+kFjc=`KlPThT}iRWmP32*oZ;;CsYnwY$es-*z};9O~t#%8N#8-=}0Bqj(0;K3EEg z)4-5e44_eANIWFTA6YZfwJ2Qnk&2cOCQ-(5RwQd^Dpf5s{?Heug@i8@hC4K$nn*Hun`#v|P8G1}8l7gftg<`Rq6VAz zc0OoVEB*Nct76q+#s{dI>g`#56ka8wlhIPODVIMF0#MN7l`F3ma59SLS|DM%ldK>h z=yWw7%U~5>PMI`0C4d>!SJD^m)F-1MXaf0xM-Z-ZG-F!b@VTtAE|x%a?vl=O_P_7M z;hPqurHNJ@LZ+Z$6X9ABONF#rKGw#x@ni5xGFg&U3N>X6n{dKTIUQ-Z3jGD@e$p5KY3P<*#*$BoUU~DK`>~ut6_QVGA{UY1l6yP$SeG>hZ3$TO zN?#pRv8b2INL{`n^~xOE4@>FsL63!A0IaPM{Oo;*X;Nq@dsDJh?FV@*Gc64(K(G(| zK+0aEbXnr_1zVMWtWL;{6;3V#-R75S_Jpi_(%#>rUtz&@YQe^W?S4s|OR@YD_47fD zS4BPMGaK0|ePoy0e~P;6!;LScH@HJ*w6Jk_AL9G2tPD1UW zdzErl$%WK_%oSCubxxtwH?KUDg}W%|gS#ErnyPTa+L0I|q>dKD%@ob&EI2!fb0T4> zTpY9+#JmCEhOu)wlH9O^pBFToZO6ajhMeO{lIdQ|YMY2W4yVa$bj$D{V zWR&JKEv0q8tM+eAFN#>K#tmjYu9rw>$~8p5eDbZOe8@as{+idzTQ*YKtTL4BcaeUz z{nrDb|Mw`VPz4`bF|ReVX5O#Fh?#ca&Pb_3fnb5K&c1<_EA!vEDABBJ74yQq@|7}| z&8)`Q94d7zUR2BTo@y?uX#?qz^x{xZ42>Cw zZ%?`<%8z(vuUm2dlMbc!LdQrE`@`=mi&^uSFrWpAt*(SjD0?4}o|q>KL4?y{+#>YB zsx0$XM2dP;K)XhbDqYc1i9$;j@)kZ!EXM%(g_bfauxXl7HvLXO%IGY`zL=cC@G?w~ zEHX%3N+*S_6~Dcl+dv7Aj37H?-lUa64t?g~@=zV=a+8D^BAhAq%RiZhoZK*3 z$O>+uDT7(8&m4LnOLy@Q__LH)Kx9cP9oU2^dIV(yI+0rtBm)MsWEfyEOl2$R$}YK4 zKHwS1OW`B#m6|3!Uc*YCI;M7BrLqAZk?;mA9Dpy@E88ZCCZn+QJ*%)T`x~DE18NKx zZnzFx&ykK8%cK!>SI83(%wABd2j+_7vAs;N(UAn;Zc6Ht%o&9S73MA>7e~e>(xQ78 zYyvCAXn$^k{juCH*<5TVgGK-gZp}F|x4Zs5XgCMOXpuA)fjT`UoWzb{Sw8h3o`wzo zIEN4A76LxQ%q$XJykQ^n1SYa^kUSZ6j8=oK8NEp8`3K2xc+HSe+1|0+TnBqT>BVIm zpv$#7K%Div4+UzX2Sa{8`?nsTPN$8{#diByE#FVLs?7Ftv5dipqOU^?>$`_lQxkK< zn($Neyma3^E#qG3$Js*NyYHh=o$^;hDADZR=;^H5CK#?O%_Ifq}+e0A*2J!rvKYXYwRaIlx>v!HUhT)bKTS z376WG{2hkTF3kRZqB|$#rs_tawrL!#QI=Sjlp+U9VEPf2M``K~pNb0u0|DwrvCx%esssROnM7+~-SlXbXj(2H(Cnrb zl}ZJVv|q}ORB$0~zea2PFi&4p^Sb~8+omL~jrp9_9;z}^orpdO4fl8S5Q$nM*EDT% z;k{sN6A|h?(XXeZb1O<$WJ@e9s(xn;yj(Yi}jIHC<^W8WdDLUxfb03MzP*>L|Lr=See zJtO%%+LuhBpe;g16gRmblY#z-q&hUK)=70}ul8e~j=4BQ6+?m2U7=yfUKgkvT-pyf zh9OGF1`T$IGjRGf$noTo%u<0wY$WLJsVr=0Y1lpYOiH#6uomxgfi{$}nIHJP0{c)f z$t{>ga25g%nc%9wr|_9l^&e>s;x!mb zmS}}L5Rp+}h&sS5=H$v~Ef(tqCykUD8(}iJBFflfrS)Se2X2NM z(e5Qhmfjs2vF~6L<;6`F)X_OFK#Fj(9wsDM&18ZdPL^|>gf1mG)K{qIB!$(3g(?O5 zgjfana(;HCpzB~W?+d_a^e>Y+4gSW^?}_tX-$hDU|0jC0Tgo~do91dnH6lckv= zd6p0JizT*oP6`AbB3I5b(&)Ud$_#V&LICgwIaWT_z}{R?2Q4;ohp1ALSaPO{r;N|& z4m@OQ;RMb7f9>~B1Kq!mMuG$#+W(jkR=va*xGvvzifuUIz0Xo#YH$vbO=*xT=!@~FoWf0C1O(vXT8s+tiAyh7YW0#y0wjI7nJ$X52MAM*KK6{bYCwxiG z03QyWjR~i2I8+c}-SufL0X??~jSblthaEf+q-)>fmTVjb%~H4?BUbS9P#_NpJKQ5k z(AL3xfXz5{&XYz0%@Ix=Rg(k|x6w939zvVUk1D;?GC$QM|viTW0c z+*yV4*pd@>H0jwlaEm>HK%6k(E~3hx@pphrqIZCrAGU#=x?-sXt zD{L{Xi>}VgCQl9o4zUkGzF7BThD}~n??MDKq1TD+#*z=!&J%#4=^+XsQ!zzGq{Y3w zan$r*{wc=B`fG$>Z*{555b}jPMKf$B_OKx~HI80f1E)07I2Hu`;VpShTM?MU5ZK13 z#04q3?ZN5>f@G9}pQH5+Rv-?kM$bWL)p$jzY*VT+Yk%8oGb123qc|d(rT9p? zSF^ujiWhm_nMawE=0Nxe708VCFul(v*hRRpb_X~Na(jta(Aeq>y@G9;T|CccwE!n9 zKJdLX4Vwn*S7v&#Jd};Oi}9dpR{PT(qbQckw|6HPxd!{vpn~=s1%MJ0mA_V<=yC zlCDr6b=O-ND&@xSJDm)R1=;7YP8A}Jgqr#vTDOnqfQ{L%5xkX@rj@+l;m6j?w&5M3 z8h~fN;rYF}^RAYqUe5?CPDU){oAqi&?p=BfQ=4jE@_j#BSc>4KGk)b57yfaw;SM~m zujY?9jUvJ6D6(5Lh>*p3VARl$(ooGs=#em}jh6YVA%P;U#`i7!x>zKbz&&|_1|tDp zV)DhH3jtMZkxqujJ$-^x*BTUD>2sjbY&I&IrZHATap%@iqgvhhg9LG*nkE&Pb5L6I zeuzoM7X(vnQ@DjP(d2^AZXa2Te7s^{uDfd1a-SIesh1i5W`IJ7EeUXct_C;6Rk^a( z(_6&aAY*0Gv?P`bQGiW$b>3lMtW2Nt6c_TM(@;+>X@R)cm>*5#&OrqQqj@w|Xous_ zc`;@5!y;ga4NRi{k+uxS8wh0vJWePsU7{ zT_y^7b}6)C;B^d`?k{(^mVKCZG#?-RxxG16AFgRl&}eR;9?%U2zf&tsb{l+4WN12o zb&BCLP%WqHU+AOnwwcLmMuj@ZmSG66P}bZVlRyo2g{z>i6snoa+&7;-`GUr(XSA9_ zOBI5#CWBzH(uF~ewRR1@oVa6#4&69;3TD~dqSUlw55lA+#P=XkN^zLANp_e=%PwL`L5tyq=YJGdcfIlKWIjOazA-d_5nRNzf4 z%r}oQqaJh{=RVXc23su7cA~rt@l^$OEUI#<{JGeY^ zv_}le-CdyGYoPGYy}NlTET@e!!Aco)vG+sfbBX!%HCenx6~73lzJ zUV5}PFC=c_l0{$NQyMMZjwuQ&%m?T|A&ZhnPeIN(4B|j~Qqwr&+g>?mT`OkL8IO#j ze&AGSR3-X~82=#b-~}Ap;3i)2VW%*T9Q@RbfUtL_k&AcT&w7Cp0o0W~Q??OgvS9d8 zp#X~^od(SaPXzqg3lTG3$pGk9V29^A@BWX|CVTH-&~NiM25Gs9e$BZ4JV7R^bzU9r}7@oiSU%LO;BNkNk#hY#G=l2ut3CyQXK`6Lk!wa2}js zYJ4oCVE-hyxx=-x$suV~1S@n3{M_ zBaHGALnC3K3$5HWl$jnccWu!r`5bK?&3FTh=+r=O+wZm-KM1a>{6Ih>tNFVoOzS$- zmr%pvI#%C!K|f5ISLT^;7CUZj;Pza0ty0!^JlmF!HF(|K%aTG0M7nxgGjX)l-W>^Q z0=6i)qvzCIokVC}YaYgE6vdg$GHYXAW7e^thsq*W&|`UNzs>!s3!E#fuifm^} zX{j!BWvMRjzxTJSEVoM~wo9DerKaS>3QJ09)kV4e%2M^;8EJX}RF=PJwq|&OP51Ys z1BuQOm(dHx>4$f(P`%=a9C6H!R{Q<1$ew<1fds{4)8w^mZFt4#!u$n2S<6X50hTN{ zZcT{Jk>N;t4>I84xC?mJQ=69AP@F8$B#8B66I7M|{Ju!wWu?--m_d}Jr2j}gj5hdO z%l-{j3sOkxR6hzz5bl}ed?JSfJA8cOdb--*<$b$mzp+%_<`5S6r4^2 zx6n0R7q?5t?EUaSlFv6*6x}>MS#zVi;tX$7+#W+y8VhY0t*Dw)p`P`SLpk89lu7R@ z$FD&O2JsEv`Z>kQ1}Q7O;*oYd^qI#!nau z8PKB~_yL?%KM#L;{5DtpLtSc21KxISWg6CPkV?{WPI zKh#^tM00NgA}v@szrxRVkf;_G{*vbFas!is|Kq%wMIe|ylx=S`+2>rArAv4h9>4zc z@V4m=wn>kpc^Gm?eebqB{h=>L$gD6bmo9o7wKJX=C1=g3?zfXZTNcZm>FZ8=ILj4q za`%_$MGMeI1AK4a{Mxz!-3W}Cc2GyW;SpqKw?A}IDLoxlHHmtlLMmXz5fPf`Xx_D4 zF42z!KLIW1nPp@~gQ^-@-3xA?SLPj(Dz)M0{jtvW#?;sc zGJK~3av2yod6jf@A9ax2@>YA^&nnx)qswqln@Ef3%i+-Z149mP5;6npwGMK|Tq8~Z znrW@jRD2p_{!5=nO!C@IbSM(1)}<}Qf~X)!Lk^@~v$+w~4;@NKf5gscs|ZyoPId(1 zbcRBTxZgB&y65L67!kao9Af}ZEgrK-vWu;?#Y~{ZfF)@J1LHLVEL>?KJfRRY3SL0q zlG-{|vYVzTE50ptDd7GD4UEi7nTt3TK>k~DLeUMs-8~S(b*VwV4>?^GYbWNU9?!I+ ze>(6f8FmT_F$Vb=xvYOnt&!yVcwQ47Ocy}2Q|xlVcUvHgTkGj59z=7(*16#`yDmG> z;%h`rIRl+q)0sUHc-H--Q0?+}w3V}2b3$MAWa8JE*z?-90UsK@@$Q|amU?iw_>!B1 zHe7WvWJr@{wiBlSYaAfUt#YzPG(H6WwIyB${vb1WaQRAr3$k_V(VR~Iv%?4fG2k=c z7QBQRzfBGM2dm;6Yr$X|%_sn3_!o?wF!0_hiRCLqfCEf*3l2j(fT}^|aMNv)F(%dY zP{SF5{?l^ZUZCpcGB_Amv;)5|vO6GhB!S%7zslQnX-qLk2yy#qS}%sdUiNdt&#~&c zfotSaZ{`?V{Da7Wj=haNChZfVS|0rlzs>5XVCVToWqvIp^pae{vW5dgxLC9x+P1Si z0=)i!doUymI3+A5h;N9C=me{xq5aN z#u$J(n8Y(=Ry35yK)+|?N&g&cf#2hMqakLpM4660ihGt*SKXoRYB_I3MV2RAb;n(3 z{W$R{h0q%JO>~V%@L+Rr0N^@P#s%>f98A0Mw7Z7!&^R#va_(^M!Xz)6%gI~x`xBl1 zT&nioAAL=fjPH;%RH5~VsbZrzd3aEE1awz35qBxZU zX|H5byj1qO*aYbw(|K=_Yfiuf4~KRj$gq1&fM0#1*r<)orw}YW!P(nT@OWNGN_$dmWBg?7|$9^6x%F!~D%%q+m2SD3i*~Y0U)S>Ng@34fN1V zB*K)&5);Snd7t_^-08*U1fHKUqXP*-uxT^7cUsf(5A6iIx{+ z0;NVLa8oNEpJT+^1;16poV5^;T?_IM!`%eYHf5=THwo9;qi%S!x@2{?|HkTLPFQu@vk?@c~C4E7hf7@j{K8eRr zwA6HQr3q*&Z*76DZcg9HwmO|3TEMj!sKW>w`8vC5R`|kEe>}nAa=*qb)4BqO@uXx8 z^^y9Vd0T_=S)!>;sgEcx4~c+1gSd*+-JM@7&Hf_)-G*lOcF)E4_?c{)YWaHyIYKjP zlRpafOM;2p0dXrgkys7SSm9WS=E+M`j}v*X5){XNlb8qM zrFuI-*c)?X1fT0pTa(yNW=GKALOjx3QB%?0L3!~XPi=RIY8=LNbJY2WLTG26O1F&d zwOyo$wbSbd;}6IA^kg{Yqa=AjOSttxk)Q2roCVtOA%I1fq;~O^HFk(WHS_!AQL)IR zbhDkuyi65A|CIAlWQ_Ac4%Y`^F@(f@&bY-Wq$;+c5@h0Bxo= z;Eu4x;bmWq>vt=TYhGPbna(E9?TPijzth28t&Y|a+$wxISsSG=W9R}sWHVeJH-GX3 zk0P|5wmQMv>L^rk0PbO9z?Jlk#0o4quJgNkhzqVcQVU^5HT+Pd`rOFK4Blda1qK8t z=y^oy4hZ+v;^1mb{M}2Q(hSM;JIaF3mDV01Ku)lshU+?{AY%o+9d1_?`rBf)5SI3`Ufbij zwhDTfs3_sIZ0=LR4+iJrg>v<7nH4_895yafBt ziq+Z91sXnZX_vH-L2(-6v1`4;$~r$hL1gM=z5T8g9$dZ^0|RVDH+ZyWZRC&4&`=M9 zBvwg&xgJp44o%S`h;l*&H8xOtd`w0E`3B^aUrS}4?agA{Yd`<0{Q?y!7+Faa#-=6R zDPyqjb<5g2OE1j>F_pQ)q(9^?p*uV|ylzP&9Fp<=NZ1{2lQi?2glF3}9fW|vrEDvK zctfz<(NX5{#h{I}C-_$Z}<$X1DOy6F+wSM~q3vpev(+yShqlnx7FsHIyj(UE# zRxjq z;Gb?KQ0C%30G)%qT{p-*M9%iol-2dM(RkY=PatAB_Q9CEFec*mC&#P}hNi)$W&8Ws zZRNT4tWp~62gG=ewhGE})>58Hk3<5h-GDg}h=AFYWM7&huay{Ui~1pWoYccU9r20C z8>jQ_L{O~zKqn_SzAJhLj>6z@7m=ytKIeIt{4Uq4F zP7QtWDai*__*7-*i@ex6={Wz=)sOI6-~odtm1lV2c#m{~m!VDw<~Yon@`;<6!v8#k zI2+r|IK*^;?zy-+7c5UlwS|iMQJh8evz!QUa>=X*I$Tw94UG4XAcUYkXN)8|47{Mn zI1FI>UujTBJJ>nQOPVO-?QNz031Klu=*oz301Tnd&{Y$PD};1FpV;MDDp}Vd&%k>P zjNf+tqX3zP9B3Ck3M(U&`_Jh?k;7{QjzXPCld5`4uLH8zXkL6_H$GE&;J2_mU~ijJ zdb2#D)K7$moUxgo&za9Me!E;k{KWt0wOX<{Jn6WIss-PAU=mvI?J8x7HF;xIA7aLO z1eFZ+#E88CYxZYK>iFE?qf+Hr1@vc^+9r)x*oQlCFRH$JHp?th9q}%SF(?u3C|Bvr zNGLP-VfCgYXf@~yN%%S__K95SjdqOi0>AvcHv(SllfWQHCHdp?t!D$3x63I6w@)C4#CD3n>KiYZ{dpd@RsJ z#|)})531s4b^^{J)W0N_S6he?YWqK=Om)pRfVx1CxC8>AA(2lVVu%Wu9}#ei?npqw zH-E#Vj($62sc)Lfc8*g5GMyC24%h3g0C7$MWG}Fvvfvkf`FaUVz&Spa5hAmcm+;-j zvv6%Bu`@)bJXBx%m6rfQ3__8vo0*`s9FtH)0zAPd4t0o3^c0G^IyXgC`eMreSBwxx zB78IT>Sv>x7Bm$ZAc+!4@VZT-jJ^_2`b$Vv$ZEQ=-x&T+$dZ7#gr>$gsuG69bI6j& zQFs~df7y?$B$Kcf#E1C74*T~m{M#h(`2(h>IEVHLIND(|)uA`8-xh`0mV%8P3a8hW zaGeqtlb7^OY?2}phBSqksK_8yV*JObf&@XoCD)<%xzue;R0EM+QUg>MlZn^G(+0+> zM^60#k*T=J)gR;C#*RBRYcL*Ts!lJJ;3KT5)vPB2*mHq0qH4QtI$+fqwx4^B-3ndB zchf0#P>9!~AwW4A#Rkf)l?xtk3%F21hEgAnz01Ibm=(MMj!09_xpa)JQtF_*nzW;qfB9x3NUG^=Z#mjU$&{ zt2RToqWLQsVjQyfd9v5Z_3V@AF-HXA-HW3@>ml=>kv_~xaR&h4ZU^>4vf!< z*_M%Nx$yzFSK15j9lo~saV;Ogd4Xfe#FQ&brpAWBx2ojbsdePYW81Ft?Sr;#zhn2k z)u}SKKbvcLX78IuZrQQ)0jo^wnd2#M7d$6QDi#m8YnwCCiEYSnvK8~uBmS)2B|N`P zvViZaM{r_v!wGj@VjbQhU273w%%z(*$m>uai{F;Lioy zy#Rx+y7c>kmhnIP-`O$Wg-h&#gVH;N+G-5(vvC3il82#f-!|Y$m>$u!=RR66l;PLO82Wsx!e`!lfO<`Ef`cK=B zHUe^kN11iH(PG|H2PUnDTc%2l-p%;A|h&h=~rxe zPa@&-5rrhZ_+Xdg#6P7b=S{3ky-&6O-G~3jl+z_bYTpBRy*GsI2Ie9oW;UsV68pnZ z-*(BQ$$3Wm9Oi#yPOO<)>w0f$(*Hw|;Zi#mq3QoQ|1sqmGO-IDr?{_<`gTc&POMY7 zWpLXK4S2GpYAxwK|6Swd=~5A7;)6zJd~U#g6ASulu=hq=d~C0Gs@?wNSq;sB}Ed1x|zhUb%OL|$hh|707q(~uyJD?gblu#W&?x(LW z)>Te(B+99?|NRFE8mK&dt8^9edl~U|Q*zkwLkS(v&}`IN*%APD9V`FnprxVZUPDJY zG-+Z_MKA4-a?-R=5fSUisP_W6)PbvSz=Ca*jLmv!k~HwIb^ZH#x<+qH31WTa#tz1_ zgOsOEUG;Z{qXeFd)!8t&^jDGUWeml~q#Mm6?XoYEnu+e@FtJiv2m>;le6_9m z#PT1|7GTjDiuRF!+Pk>*`urYjvOkHHofqvNNIk6AhvBW=bi|oljYq>K^wC=K`=mmC zV?V%-lg}QiDpbn{#Bl54C&}>Y-C2Y<8X?KKi^!VTP(bZZa?~Q1#(0lp4>V#kob8Z+ zdrZ%o!W#KAje17!Odtja1+fIE9?98FM2x4Qha?yVa9u0K+<9Y6KueG5+@i-^F4cK{ z?rKO`91;U%6i^xpSYSV_I6xmjA~)I=pd}F6b#BXLk3{1^#x3wa>=M$0>>3SXbPh%< zHgJeCiJ>q{CxG(`%bingr-@tt zZIY<=G{oNnhnBJpJw4`50Yjq*$e|9U2L*|L9J{Ark&x>?$R$!KBrfG5#cQz9y8%&5 zbXgN~d{#~yT0*8_B!24Ug{!NlLE6P2 zF~*wz&^om4Wy2rj&c=uCl`KSw0~&c2l(R$h3mpL@qY5@Y$ca0%wC6`)I3cX0RJ!;c z$KjNovI*iTK!a(rX`LvMqy?_)fD-1C#PBcWRdA=$SJ>mm&L92&_$>syq ztia1n+Pi(!-fO|AW@F2JO!2ym{l{NI9knLlTlk(WS)$TmIJhVLH`O5VH8>?|g&d=w zpVfP=na)Kj732G;CM5Mv>Fz2wVVLDVOxY=&9-WTGeXIcwqdx}^h~KskTa76zWH99E zJYpd^W+``C{^Ip|>mH1Oer<6YL`o8Bk7h${{Xz;QQLmS(gb!RK0`c@kh&O>ls28(- zN^l>X*q!SL^x}|io#&%qxAcy6x@&aTw9A4Co3mNs=@OaT!{!ce=~sZhdl0(vAcyh} zKx5NllwG7U?ucFf5#y65-gpPv?$LulgJPyOdJdS=UIV*Rsk$42kqrtY+RM0Mx;D3w z0LxLOCH*~mb-ug#tTIz=IQE{%W8Fs@-L)xZ?8Pehguyn06=ujRX+7%u4X37tvEqDk z^P6{n2qvIwJ#;js|B-R0zfvPO&X>@3X5{zKC|^s|o_gAZA9PlW++BnfAzjU?3XZsX z{JAC0Rm4oFqsZa;Op-=4{ztm9B#_gEt-hI7G1^-hbWo*k`hu`a2e0e*1{gdcXT`>F`eI5jsJtgMf3@$?&Ce-&mDq30b3acdv1~Ddzq!nsX=?+J7E?2Da?Q$yW^1fttVP*XRzxi zl7+bRd`>kkP9jBbO;R0Be!30&>O70%DW~ivG7(-Kzd^eJ`&U^4{bUP&76QAHeJuEw zlyCw&H?QwtY`r-_=Y8P$th!z8Rgkp-N%zKsryXdpPrlwIYj}Yoh6`(Tv=rOa=X<;o z#_BdbyCwG5#4>pQ+r#}d7yic01Ft75KC$+sa&(Rrb zc9N~gOeMXKI`;7_3bb_O?ym}3gO>?LwcO(}tubG#S=o>>3Ax>4>`w5@dllS!(n`72 zQ!BkVBrNXaHdfYxO9Iapj_2O>4_Nm?-7Hw?9Od{Je-)8mpVLxM0B3K4rEx)Hn*EpnzCN$NdacS2imfJIj zoLgvZnmLQXw8_}-sqVcKhKz2#1m4gJ8gyl3`xyVt6(nno?^NNP48 zJZ!I*g-;hJ)jkKe-#-6_ENaqhziqGM#(@Prk5Z}wh<{9$KHfI75$HeZp!blax8HJn zF^2VD26tIA&Tihy>l>pUCOGhbRix<>gu4`oDEFO$x^Zd#DGlEvm?P+hA?EMu9+21A zbdMNuoUj$vqE4cYfG52?Lvj&w4%V!Y_OPRK6_%)McHXhX)v;5zKchRU2}nl& z08}`W|KQ)dEhpZuv^CpFlhkAA)g37~RVTuwjJ4UW>-mL~Dy~kRUr~c?oemQG^#oS2 z!rf3F7*fAw7wPic>OHXUlw@~4S{Bl*IJ9lLx(B^_=^bOgaKY7I*%zR5DLr&M=`nU8 zaKoA!@cn_A_>fd*i~BaF$P@24tFmsu%?wxUHeWt(HJ5^NXW<{k-#MIXuJV2g^Y!WI z=CTy8^o`j0z{BScAA7e@EX$AI!Q*;^CduPjB?oV{+L4^!_Dl(_Ixl*5So}AihwseG z{?L6+Et_L|zMv0BqB&W=*TL&=raaR0@nW3sSiSqB+ZA>!Yc0@wee_LTWRtUod?XX1 zit(9_dW1sL`26%kv4zKvPLUq@OQC{qC|Ms1>aqP-$~(z54sz%7pkYW}I|~71JUN0L zq}=_8@uBA9b|%lkHK?cFBw?kOY|~&dSjTStLA#tF++jNWdZD@EQqW@FxHc>9G7J~U zWv}+o+DQvB-7@muBu+dWAu%mG%)`cEl)If;H zT>Z?CAfC}C2^KwaIszof~>XnZilYRqu7xe_e%U_j~H#t(uWf)lF=d76Ef8F=SRCnGg)<6WVHeb;8)I%0ei1LT5-#vS5&FzxLst6Knl@ieyRCsP>x z?emjxYuf!Xo0Z4Xl`_k{XFET`BLh5mS1<47cHCuZhBLpRe!H6u%Z_#OX~j(*4PfT& zHicAU^i9rqqN)?!U+y>$IdOY9-B^5kUy|P&Z0I`6r6)I7hPJltf{;5!Ys`CD_j}Fs0ed=^s+Vc@%erI5 zB4($zJaMbN4bqOBYwR+hQu=XVxlK=B(ABvQwPJV5zN{l{^mj=I*9ffaB@W?!2L}P} zA2rrXp+}lW?hKmrFdS;5yM}8S6UwotAMUP@d*XaJ8odNTae6S~fLnEOKA z9#>fhT}u$@lhX*1Z2i^7iKWxnEjdw z`}2&D?>$IrMB~;>at7Kq19s3_J-`S?y%Oddc!p5Phjr}>r2o_tptM}9~~5caqoU>>FxvRw40;>OY2j@ zOEvPz(;ACU%8PWKr`_U0f+5w5s&Uv3m`)wI8S%%(DuJ~7t5ej>*ABKp3ICKF;6+7z z(2g-pH{%vLss!%@T=j3oHTy5WPRWV&?>r(N!qP$?1}tEivll4ZKb&7AgdLGro!d-bacy5%GW{#X6PnBD* z8hF()Z{BQ<6>Og~fp4<+8P9S2ggN{N%C|WZj>fiKza{hsj-CzM?ds(4e3OSUliC`4 z2OLXzukDFJ6cJUHcsGuobykOFHtXF_v%I6fwj#^J?Mvs&v3c^2)FDsV~ssx;G>JBP^3G@T*X zAIcKL)%d#gtb{?pB5B%ACBHkS^7REqy>HlvTZU#x6wTG&u1mOLV7`AEk*h@pN@us1 zRndMCiZtt>?7NS48GCvJ$AgO33}o~2nB>I@HBWGy^5_M&eJlxDG#hkBxOEC$+#`HH zEgji^@uKek9k4##nY|dyE9nD3IX>QULNRUWGl8)M^Md6|e(U65;3joSc}oy9el&wF ze7~-zgeeb6X0hoU(+sscukHJ2LTG!bh0=9n9vR3HA23(L8?Ovu0=^P_p9qWDsYwu4 zn+PKb(!U^PZF?8+d`*Ab)818jQJ~Iz+r4%)p z;}%_n+K2LX&+AM4wpE>9rdh{6_dY57>N*FpTgrv}v76(A} z+_WcsO^#HMm*U~icj5SXj*58U&WPI2`fA-k_@0IlbccYz| z^Z&on{;%Wt-&knZP1?2!VMGeOzDH}{(xbJ?x%lsl!4q6ieKJ+2ea4 zvn2$2=O}kqr^0yK!m`oNxupyG0n<8DC*rWprmO%r|IlojD6f9c zDX5?2W?(r{%+SjvXLp>fgQ)IdG#|dW3vfQjzAn1!=+J%#<;{p3rJZaGOMB($UViGn z3KY-SOxwV8S?qcwrtOcKv`8`RV8o1Qf|5dXFGC@ynEgti8c@XU3^4fjgr$a7STYkN{|U2+hT?A` zKzk!$6rT?tF^phu(~aHLZ8}BJIKP#9ZyY!nabG7RWWLMv+pSI-CSRY=w;S|-W)#=| z#3*Lw|1G0r?SlUq^~@KVeo6wO!)-|xB9bg-G*6iN^uquVS&1o)7}ido&~j`V>GV#8*H`QUO6Z&J!;g2PKQCIs`ba6K?tJwef4ZTL_hK)*Melv@B`rrx~T< z+{qI2%4Qv6se}}BNgt8&>*NV`u(7lMH;s`z9dW>b5OnPWg>MEgY%G~#4FUKK z>adE>)(Ib1pWI((AC<^?c&T3VcYFX$D4*WaxwC`#cZRTM+K6YzYrXcnQCsPWJywcc zrw@&{#LmDw2Wh%oXnpS_mH$KPVwSbx!>xU1=%fLcUg9O&)<+co_SGb@cX`P9ua^Yt z9(rMokuzTJ*Daibw-?4)-vLsYXBE;;9j+ipB>6XwjNWWI!YzWUM}{HTgU?&6z&cQF zAKv3Q%MjzL(q6bdw%oV6tdi$AYt@g7g-bpk7s<4cZy)(Av(1fHJ---0`FTrla|lW{ z;3dvhg(@;@NXiuetk~qR<{v*q(ga|x64dZsK&HU3M?bznsUfr=RKnpDKTs>gdQ|;! z4#Z!`KS4GC)V7HAw1ll;t8jJ4g<-3_`lB52Sw1eCLz!#aSd$x!Jt@l1zCg_5b0Zt+?R-&znTX^%-9@C zh^-;8g;v%m1tJ`(8Y>~K1`^`-h(d-(Z{>0eaI~rz-{cu{=8zpwbYxeN7Pvxt&S65s zDMEX!;5x$`PCMCRFjr-No?`04?jq_)X!y<0iT*ZOib+O;9@uM-FCCsCl@{c6r7 zQSIm4^b;fB$;w1z_hTSL^TnIXEiquzvni5)BwsIHWOr`JImMGF=7$SD{^Uo(Z&7yL z3wFehEN<@SLD`j} zQ?D*EYF1&P&`Hi1G+!Hfa{>vb5x;G6yY2} zOOT}q^(8zCNcJG9>J-z4&c}o?4>3!) zC4?}8LNR@Yg)u|SSWRRxh0(@_h0{SA_A`?876n$I5){Y^X(**9a7{!dMW%jy&^GgA z>ZPLZHxP=Gz@^aERN@Htd6GB3;_wz$0Wc7pi(S3hDm@}oKQM@zY;iJIe6`eQnLw)AwXWgykedber zPECFB@g2_}*Yw^6hs9jIJ0*(zo>pY2pw>!Hyl-0%>@b&IDhu`Y_Px_{->NT08ox^l z@EuQ1eA@oD@-I^km5#D}KC<)EWT+^f&giMMEs8UH|F+c?AM@mQF%azK*%3xc(I37( zIc(lbN;|h0o!KcZd30pf?p{}VLG|#2=oNbXk%kT_oRe(&ZzLHBw|)h{^g81r#-edI zNMhEwlvD^M@G~4D!3^Q!4-i2u!4w?G1uO^gFpx9Ah8RRhCLa%-24iE$Lw{%#<1;EF zsXr0|nqU?hSn)AO|NOw14w7LS%q1?^;$RvmD7W>g1DfgMP$wfuQqv znrWm{x@0GvubzKmX`4-xE-NX`Fqw@@D0C5S$_Sv<4h~T$2)Mvo)S&`ub`dAm$%yRZ zro%KtjP222Mpi?N4+ z7*Yq=*(bY)r$8e)q$Ss;_ia`Ie`QQOG0qwg++y~T)G)8Ye?1nbjaW<%d?R}=Lzw)F z$gup&c**hKOfrr1_4SPj&>0Bp(;1C5!`MQT{b9pL;fguKR%XLTP7HTP3L-+y@9Thd z8OB42Mq*3E0K#b{LU4s7tPPkRVgnQzy!;@hZ4f{K9_|57|1D?C|0&FDEdPZp|IeI_ zv7rNLjIWH3^u>rK1$veG0g|U33LzedDGvq?9T(5_C^A5avF#30Pr?JJp8>f4TTa;i zGbc=J|4p~LjImH25P%8Mix(C|p$8E~RJajo2Tc|h9lrnm#oSiye zKa}-jgoY5v6_v(Qc?iNm9bmSNf#@{;*$q<-Pf#&hsFlEPJ^PjHGp))fxPG4eDA~m5 zlNk|1n>lX7Ka(EEV!|z9QC{3!5`95s={Ye2Bl%nJ01Xv9iZ{bhEZ$NMLz7BQu(y4h`>@0dJG|!?@im{N?@QU` z6nW2a)7d*XBR-7gzg6qM%$pgR|Ep@98Al6XfB~I@h=7S;ItcszPOb~e5dbc3*xgdi zB%>$&i!(;(SmVH76K64MQP`c6ymY^N%#7=w-2IJOlY+w7487rwdNd5?ySHiTyt8I0 zRBp~y==D&IFqPWvSbSLn8ZOPV`d69xF~iL>($#k;yW)CZ65yXJ&a&kT;9{T_lxGMC z@m~tX`Y$S&k@dfUA-kLzM+#s-0GU(MwiDlU9X|TzN1RN|fW%~0aX)j-%VTx|bF<8Y z>?{h2(V#uj=C0^Q=D1eNDpq9wDmWqWwzpMSV`8yoe0#yd-q23W@L(d$gwm|B%uIK& zpVpfVwsfH^p{|<#WsSnT(fX{T@A7+f_?p0Yw2zt>V*X3#WMO4u{`c-l|9_7~j0EiLKi%ekfUi|+c-m<%yYrv)Jbf35~mK1A2KSFP?>3eaw=D5){K#if- z-{!UNKa54F*DfLfKST1IQ(y`!L_Q9aCcher9Tqjbt;XjP!tLqvyH!&Io@DJ6S#e80elqQoLf1%vWT z*(xYOsX5JLN#F8OA_X#}=1eOkJfy=(6DC-)ekg#nS&MchSfN})K7y1i2`)=H{TH}m z1udh+*JcI*1V@NP=mA!)&V7glV@<$Pq?I7nP{z!d*Q=cgtq`bko-qUC;6O1`>L^jM zQX*jqUHJw0y^PdWBbxwk@!7CNiA*Xh85#9E|1U5{>*lJ4S9clIzG*T}R?YG<=SXZU zSp5o4r8NdU{NpVCH2TV$5ldNELUd|PGHfcAxP&o5Q|jr|bXj_) zPF)d@y5bCzh%;L^A)Sg1I8@c1vFT{dzxTZ|6>{`U?h1p3k~*sDgq3_WuX9DShNdQ!LU%)khAo$!v6uTcv^NJhg>$z)~{mRKgI2dyDBHl&mS) zP)&Y-X{aW@O6Bf>`w0Z4<;Ff49kL&w_6hndQc`)M5MYsG^ybsffO4R^$T-yXmh zA`S`3%%q-gde^nKML-Bw`6?{dSBs8TIro4jPnl8G8H2se>OZaPZxIAJ3k7g}s2Upo z!75&gQd=c(CX&IYXoTx7lVhe|m@Oneim-f~o{^IRB9Vv~CVCctuxe6+Ut_*llc|Eg zis&1$BbzJ`%f9PD{yO$fRYZ5+u~{PB9*ydldT&!yciS;qvgwk?aOS@DjP3}0#uWbj znoFtbrlsx}olW{gsr;%@}mZnknq{cn{Rj8>l_)cp?i^kdA?7WfqttQ8*rGmo-c}&b>kFSjCOOr zNwRNpHIgTy)!#y45+vovOPFwwc9)lxmCSE23`J3q@MV$M76}V>5O~{=7ZG(7t0a9E z3&xe5lJV_Q>4TM=I;!`T9QVgoYfD+qc*+lkk-tn-V<>~Yk0ukSD(feeq^@dEI2X78 z*E`yUca%+}EUenqIM+2>6I3eb&SXZ4BTULwBK>O|iZ(h*!Iu5L-|&VsLW6ieMjTRP zC^@dVgq)z2QT-qS2#NO&<+CD?+mR$|g2H-bNw(sGMaEja@(tDGSiSR4_DX)OOHWzU zT+f@eDc}w3*q}QY(a1A9NUN2Sat`#h7$ zN>$sbz5<(7j#nd~`{8q54fE1yQO%Cpl~%k;)$qv(mu>vOmu=x^_L?@kZFT3i6dKoM zr^_RAnABx5SI$MBU_^BgQUhfe4X!fUWK7*No4EIcfNRY&Ws{f1+>PhoRoy>hIFnyx ztfYJ!NzH!vnlQG8A86=;tJqASS1&9%f&p|fFWybqU~Fa0Ka}WYtTgG^acd*AOyJcb zs<<(Xjwl}Gw)cO~#1!TeWCHM-)n(3Y^>=f?x>o*tpwiOS{AU+(`U=3kv|els58($V ziTnxEYAI_Cejuwo@_x#XqtBhgKJMOb-<1QN{ECeZ7+N}SBCkwRHEMDxqZ2%d^;vU9 zoYR^9gt>gyo-gr@=Z68MbHox!o;(zZo;(~Pq)SAO%sOF1kj@H44&{U=kFmp(!(n~Q z0CJvMic}tz?dEXKEk`fCVt?FUf>frL%VzmuepaM%ya4zo8-P4EF&cn}n2}wmhk=`C z$7Nyj!fjTWJZ7{B_cWP2P2=|rYlkFL}4?FU(+cet?{Bxb%SCoGsf`tezNjFE>h zdLY*|Pwpqv@#8-IM4aytq7F~=24;zS_CI0rKe5{&wzn?tb6CX5-j&hD*K%7VW_%#I zGht?b!ZeyCW^StLkD2sZWWuW@1302%$@=t*(+r*lWiE30|8!I}hGE*UgvE}LO!P9` zs!}2abA(|#9t11qZX7wS+OR3+IfgY6Anj4~n-#gSBZ_tq_!qeD53U!Etx|v)lV)JT zngiMkA(Jn#=p#2fC4D{d_cniB4q4UCqxU?*@!n+IY*i{htc@)9TCuEvc5G|-wh9J~ zj7B@ZS?#?SrCJjg2JfLH+p!@Aa}w>DOY($tNp2I40TEJqZ71;2uHeG9;})fop?H!Y zUrI+`V&p=^#Ky+Nh!pfokl-jeb<-!yowJF~2e!;RQ6;aSlH$TD-hygg=0rbF(1)?0 z;6jrRjr}1qByytkHWW}I5Jl{g8{b2W5&ifYTTbPL8$WY?OHKWhds}qffh`H>NAb;7 zNU-*j_=edzk-S@?iJVG>&L%qY-nl-kF_?X zCfPIBL^(tyk}jahKI!=)(JNMhP+CAfzk+cF@nTCSu~+~TA1fhlgO@?4u=C$84HAx@ zN93D4*@fqN`X1zc{L(M^WAF94 zcTn>pFos?~F6V_4Lx2i2hRP0^2v|1h*bf7b2og|b9zuch;BJj%ubc|gE%rVF#O-G7 zroEtGYAr7H=UR?T&-ZO0xYYGB2L~%-lb0Y1!|n0$kDmAb*xeoCVsD(NFMflevA6;E zEQn@OjF8+zYidz zadh_$dcv;Gmc}PYWjgd{-&aXE)222-DGDIM-^pNVQJW}=V~U`lpr)OnE^VtSFA!ZMZ-&e;9iIx3V72ZB}kWRku-Q35w~=V0n_28D|}bQ9Moe26`v zyBoaac&5KN>gF*%C*J?D_gaim(+4%6>=AYsN8O!FLBR4K~ zeH0rr1rDA~c_0uz^eN!gdRLAw?DWO%#(l<9KX``AqrGh5-J7q)P=fRqn1fDHCqna0 z5vq`cy<%ybrqub;542Nxa;)AECSL(6(q&O?M0KFHwgLX5RHhOijyWk#%sbRNsO!eIirjdE61sPD1sFI`#B1H8X69qL@%>e|`1f5Sch>{z{Oh7IP}h|oT;Jf>>B zu{ZCCfgf5mfg6gGE0x2ZI9{ODDz??iJA3K4OadsBWn3?+j8aeMmlv|PeW}we%L97@ zX0Q?;!!CF^ntqDU$r5x&!v_m4rB$jf8)8=?j%FC6MvTfzGVI296qF&NJ5y#_fq*8o z>`u}ku758DL(2mW&dnG*Ay?w%Er&!_mdoaP?W1RT zo7$b5BbcR^e(Du!fm^hz^rS$la<0V#4`5?OSZ_9iDS2BKQ3sJaZJKQng&anUxv{p= zt1Dkp>ju;1b?#+Df&1-$~1t0!2#r^Jw>0V&g&QHRjWMGF+@{=HEv#51#NZTi-v2 zmqrKB?vr8xt6kx%AdCCW|6n#-~YstLB|mt_b9xh0+7{ zh&7B*bVNQeOFxWewDd4HdV7X^k(TWhGrP&!b{!DZE|L>89%mrTHBcZm<=7}Oa};3W zLW789!gG8{AtEN@|Mn@Qm4bFFjBefj9l%e7GdMYQWdBzC)wz4m%}dv{R?~xXo7rRI z1)}3)zOPWi5EtbPh9bCDB#)i&=21vkYlTd58(OrgMzt=o6ekNKHh{)Z{F>>oQAfh( ztp?|615cV%&e=|$z9_Dbe)glp#kg&z3RUjEVePj>fd*@h-)Z|>%+xpcq zi|7FQb@>OEZi!qlN@(mJD4p2%mmSp-*=4~H-ION%gkZ3gt!1Nh%R3uCfH9|Q=$|8m zOBW?akDwK7<-r*1^Jw?2?A%oqjIF!<&D9qF*k7)DpXoH)QsbA*tuv@6cR%iv*7!oV zq|U5}*HJ-%y6lv50lyC{_);wQOCfPC)z40c+MG*Ub0jnIDzac((dS%T@+!G&Qa>jA*b*d3nCN;ZZ5-Q@xAU)F%G7sIVTz3gHU$=Z9P$;Q zrTe)@kI}Pmx4*JzO^m_NRGbY+81AGEwj2i=z4atc3#3E zuyP`MExlyEvq*vsn1u91-+7scob-93UB!S8$QizXo4U ztg`1{!gvDfyS=}llG27?oDg(F@CchCgCxl3eB{D-{GKofp?c0yR*fqQK7$b6rGq$T z@;`wIXEx@xNrxWOmU*&EP!St~&^MUs``1y{#B&BW)e&tVD;w3vxZfw8rE+T-EI-*d z&$#MQcL+#Qwl#oFiB~%k!ufMzlMS1=SzrpO)wl#`@lCF zeBPzEA|NxVUYDjmC2Q^}rN^e0`~~*%8kVbqWKs=ZUiA7af7!-TG*CPYTn+lAY`0Am z1u02NCB5BG-E>Qmm{SRD{I{X2D6X9HZs%mW3gh35KrH`h7iIi!_PyV~b2|V4vb5#v z|1H&jf%0eOVCMY)F)gvNvNQc}rX_Vx>tBD|zh}JTi71u4CQE2^{zfFx=q^M&I#{on zN{q+8AZogxG1(X{B;c=IjL0=k>GF=+|K&+ylbnY&Z#BdSAreR_;!Z*v)!ATyU|>1J zJFRo^y@;LmwH{PM8U7jrqsbip?D3S;l)J0~Ci{E$G2{A=ZOPS55+Od8E>Y_ELs>qf z2l@O9DT)17o74X3Fx@C~h?Iy?2n8mq%J+-rR7WJAGHN@qls=2&E$fcucrnfAVCnWP z;FUe~D}cfs_#C-ZfZdoJP!Z+f>o|3x+CB9>{;sjxeNcqyGTTD`vOjTa9O}C-g==IdXlg5he+4@ z2L{LH2gdoY8_Z(GTaEkLq4s0&%l5n6eMMCWbGmUhQeKVp@{Hpj8Rlt{#|p)-8LLmi zsaTOqi-cDzN+|c;kk-w}ZH*~ju#i-hG_mps2T8Un?m}r{u_C`ys;_QJo{?T=Lr+=O z$dWR_q|I#BD$gI9C>9f=l`i%=?4krl6KL-tXkNRQjwsm0Nax#5H2tf@KqtjZmZz!} z5kav+BiWdIuv{FZfa9M*yPOr3N=+kAHgSX|JfY2S zKI2^ibi8CZoYdGzfZ9*n%CN3fodKKrV^Z>8%1Czz`Xiop-@O(A`I}}%_AIk{Nr2IP zdel5%UW8V)QmvBGO&VwbxEZL-W&@6!W)nt9YYJ4Uq<`mq9~-Llz4 za9P`rSFJoFwZldTm^Kh6Dd)~w)T1ilL5oxb;FqPl1;#4x#q5q! z<@A)aH%IhvL%TVhkeZRmY@cu_Rr8vPca2tk#aRVqWGJR3^<9aodl=Y^<>RH{t5K8VPELpm; zIKAGUM4+3>B5+g!&oa|lnoWOkR7Tg5_WdN7K}k2Xh?>;A*HP!)Q!gC=Iw_ndo0>BN zT8!o#%>0%xB_uV^{xT$R7_+08h|w*T-ZxBwRa#6ay!!9~03asl@MI2FO@^yufID-_ zG42JrOQh^MOlw!AGr_bTnG9{a7A?%7l~e*Z+_yRN(HB1T2q$}o>KIbNdMxFSUVw>C zz^h@!OK3)TNQO9SJ4jS35fAC+Mn)IGSbC{7D~;#bc8WN{P2;IWFxvZD{Cxo7I`7*O;cG<29he zVv~@+sdE{m_`9>DA=~OwdXNv<<8hD=k9KwR0N~<)5%}G0YJd+9+yFmTxGr`y`iBfw zM~(W~O0$BtjD@XTr$rW#n;VdoPz?MXU4~LJ9UPGV-r^+<*xu94H~sxZV|$T15pQ_T z-YUEafyJC(-1Z+U9+c zLGt=$NtL}kC0+%MRf%m$N^@0DkJi52x$t637Vb(-2FpY)%^xgR?q{`yiDppgzile@ zRmta+yI8Ir@>k`;tPj3c=!VvU19Uz0UMAvDGo67yZq4Oj84v;a#Cs2V9H`_CNSJCu z!>*Ny+X=xUX_oH;AgZ%1UIw!LvK#8DMYEbaCYPr9IK#M=bjC*7^3q&NlxfOsbDHmH z^Typ;`Eg=kjonthoo#|$$}O!0CiWB8+J%zsxHVYceXm91mk8+d{7@IeI!u~1Qzdq# z8OqB-Mj}HBt|Cp1kC#&0k%tM*UE%Uvg%6OhXbX*2QJ4?EczS9;uzk3_fZ1(xsO!8H$$5Wk}i%)D> zcB|W4)SvWQXj5CXd@M8@{|0p132xGQeqad(i$gmAsrr2DoW9#-g^3=K-1z+3j@$$A zv59?Q0IT{11y(#Y*jc~>w>Ql)`HOhdEYLErG zAFlz|_3^;OFvABTPYv!C75-tFqZFqXi{I=rD1*4`d4l~D@kl72di(7rR z^Y0YS(~0)j#cXHXnqJ=w+F&G|afm27)1dTI!p^G+b@Wm~Ng1=7g%EaCio=4Zb_HC+%{x~YUTj6!XIN7~fD?hAS2qTZO@v#Ie}mSshop8acS=YGDa@;(lSQo}PQ-b2R%G#H=Vu z8XVZ7gfW(_4-J+Z`E}`zw`U-M?1iiDdjzJNggWXc(^*D^RqCpw^JzA>K!%tzaInFm zU>BxX-==s+0cD4aCTfHOd5hj%n`JWwYLeEU>@cTbE?%z3NFR8df@ib6`1$E@k}QKh zOtoIbSW+=|W>^#sF_aoU@1r%?gZa9hopfvuHg6<2CrM2k=B~t&y*c2r{IO` zS)WJOnvwUx4!!5#I8c^Qdf;}XJPuev*%?rBo+65%D)V3pykI^o&>+1~zQWIgy?RCU z7FGz>k0FW11&9s&>wmzhf^HNgxieRIB@hP zB3B!`25VjIALbdjaU5iCicfeVUA>`el#9$bDqbs~+Iv%dQ|R?^>h`jKQPVl25UsGX zHE;$45gqh5HbW9ULiaJUQ6vlp-$HSzkTRyzZg=oUPG5Ap+7%Sm?R+}U{8KajN$+!% ze3I*XL{0Co)yKXgPUkw$rA}u~#YF|<(5U&l^iKx~$@^{v9U{|8N5o?47NQM0!pFk% z^0ikflB8`_)bV{G>eHa%_0LrGV+kGMq%~P;BTTEo7j6wrM%WAE{KUma zX|@_3w0UM=F4tW+Lq4{<)!Fv^gr!T0|+@&tB4dqYTuV|+D3)Qq6 z+dV*LzlIyrRvR2z&BWtA8H4@!@`W_@T}o2su2-kzvvGPDt*1Ynsf7|d=k7_u~1Kp>Qft~gkEXh(7t~AFz>xw0o-W|(mplK zx^g>l_s`QC=?FTd;msGeCcLWwa=}?TTZ^c{WczGVcAQ-*FJd$D*=D7oe-DwiAZ>85 zHmiQn0H$T|3&vbf&WrOSO_tU77{VWuR7fyX6b3?Zk&IPS+UCu(vN|{ac59oRIuglc zPV*l0LL-!xUas}+bz@<9yhc&_4i^0YUjCSIJHD12l`Q#oa1-d=WF|3>niM#bk+TX%~ z3h)ci@4o=ZHqW$2VIER^c){M~g?0!OUH0EI6X9y~0xs7byCcoUhIchqpJ2zR=`{K6 z=*!20ubZ7Acw;v4!+)nSbK67EZPzWk@iORO z9J)W(b%12ik!1x-e<;;W%2o3+_>%DS|BmRnoM=n<0cS$P>7mO|FMc`-5n7yl3lLmf zeBcM9zRLW!h4sIJk z@lyTYeL*}S-F_{npK_i^sb|t!rP{d1J2kJS9LlB~(zejJC%cZyk&wq6xk(D42|*wv zu#g~_TTaNCPckho_=iAFIs+v!6$ziotv>XxKnprKM^-lZrjicK=g;1Nz-fqpO`s|h+Z`7Vn zkIA2@WN-ty(6}d?Hfq<)PM5uOU#7d84?v+S-%VbA=2AR})in6)5cH2aYrK2~ zJf2RMYksf877rUhov%K!QrRzKlY-I zB5!1FKS4g*ze{#Yp`GKwg4$|Lwn=TMujk(1o)@sW60sHpEP$u5MWC(z_?Md==WA`qr?R?tNT*(yLoG*nLI6*um^75pa_aK6BXu zwW+}6hJCmo%93;{xp;mvOK`8#-(`{~8V1T%Nfe`BL?TPZx0&_ii%79>Q(rW3;t)xN zQ_wl-3SbN`*87Eh7Vvf>AcXJmnW5+6BbwxlL!)ZoUT0h)z19>7A8wY{+en7)*3pt( z?vFuqMU+^()W^qQDO0{DfbcSttMyf0BemT6|yNB)gB#@b#z%gTru za6*yWSSVMSAT!jXA`LSq;mnl+6`A=B&cpN!qd*oLOCs8ifb32P=2aw;1sBHD3*fYN zl5)sxNDC$AWPm4Vt$1uipk8Tll-s$Z^l1x6;Gc!sz!r9nkmghSc+vwa)H ziETpL=_`=*E-Jd|3WzAF^mFJWBOnRgkf}(6qu@}ZKrlruR2Womc0xt?EFZBj_a#ao zhHNQ?L`PzL#e<%Lxk4AU+L1;Y)dX-QM>&goK#65Eeo%s?D#ReINl4^`!+O-~0k#tt(8BCZKKfwB> zp)QYL>YzYa@sQUW3z+=t4GID@Ky*y_5FAoku(zlUkBy$phA1rrEy3T9&x3K&HEpvA z(&JfZaiD_j9sZ1q9h&YY&fV_#ZuXZ{1wk*Ob`=E#^jjGjnj6JTQ0W-jqxo2`7le9H zmi~6}1ZfqwJ{xPq2kF*o2Z%Zv_7=%|C&)G+??fOu55F%ww@yXX+`K;0peP^-YPy0J zXbhtg>Oy>4!UfhG6zHI|Zs{ez+j3BbwlrSY4gTUkMn$6atA-xqeeXlFuhw!1iI8s0 zZ$JfWy+LPNKn^9YmA>JH&qCh`QQMIp(heT^I`qc)PLN-F^7o>Ht3xo;QA_r-OaeRrA@z2HGy#mq^+1@;5JA z_F~+G1Ktc^+4N4SH*F0|s zM{N`I?bXEE0&Tz6XD&XE-H}Y1X4?oIDDko>A7cps2;7b$!{{GwAR-~nb6L~iKXT<7P&H(dPEzCiRKP$3}{6)+CALl{}L28w4B3Tp`C0!S2Ga$;ss zM17v7SA%x(JSW<N+M<_2I3PhQfO~MKkeZp2j}ie_H1xK&=M4(tyC^Zn0AHc zbyBYAUQxYOG;KfX$=H!v%|n`ioM2w{khtl+fpz{&-TV= zGnl4leMbvqv()2PE)N14tQNUkM>L~R(vrRi$tn$)RgCo^Gq4V653VEuck|sJ=K1Bj zMtc+xQl1WY+xT~P+M~_`O40dy} zE$_Aiep)w95u%@U6N%XNsNC-C?{~QsC+(Pkb)$@o_HMv&+6&MR1t!eU=frT)>$jGP zh*8I0h*AO#W`q&~$EJ+Ig;C1j#IV;3p;!wn_Der#&AjrPC}o?}fTUYmkwZp25hW(N zMUjJTU2bpHJmLy7v>&d699L$M_l!XHxhN15Y7sUt`zI+=N*LTJMGUSqGpAwwroPjH zLY*i&uJ!33hWCf*h?*A__r%n3YKr|~-UUadE1`J$a)#J2bm?F>4BX$$4d=ILa@1kOa+nZM#A=@of8%QZR3RI{tEM9-PzC7$+UVlQiKO^O=^(Z*g&Tu?$ zzks*DmJY%l3Uskrv3BCl{-JD108pFp@O5@PzJ=TM^I^0(!%`K5`Q1J1K~~|y-h$n$ zWg+E#Qn`Q`+c}iXoDM~vm5RW1nIGR4ezl4bWupwm`|V*5>6JN#H24bmZl7* zSuFFe7#AX8Jlr~G6eqN_&vx+>iY8TfGHMP6t4^y~%PPIOsYt_WKBF5>5R#jS3Q`ci z$_(f}Bk)m14eSL4#1Vl$myaf=``DQ0ZYkwBCa338xb*^K)Ts4Z2APqw-h#pRHTRd$ zH0)%rb%aju)PqXz9hy&|w$LyIN;Nr#J!l^l5hU)541TeX7TDqC75Lp4%a|cNAR&NL z{Nz!JasZ85FnH2%rYsr(nPG86K?W4~?Gf?z`U2U>+|S9x+hXFf-#PtO`#OIf5~bnt z>&tFNI)8s_hto1~+$C4S`MQIs2pow-5s;%YDe;b_Ya6FQfw|0#i&l$C*r;INu>zDi z-D5E$7>rMd=BJYEBifyxO~YrmU9WV^&_d@=%ZkA4I35RkhOf4MR9fM2*fpcOm3p}2 zJT2yBl;P(KyCWS$+(9o%QI``!e? zGwBfZJO$R4rqU+1EgR6!rf0)XG@)qnC9;nRi6aKr? z^MIuP;r;vA*Z5JyZB7}|GP1=k$W8(pi_vgS4oD_SUyjH-BVlHVG!ty$xsF#VZn~Vk zZ8Pa18Y(gf678 zu_#0Vav1LSYpzR3;D4mFme!XwD6uDB$%ITZDw{~-YBU*plC_jVy%wNKaRMTe9cD!p zZUjoteVQO38&joA^)qw5(BQ(&P}q$?E5C$)|3F9l{*)u4y3d{>;tMO({N)B?H>v2} z6lBzp-_r_wG(;@!(5+ii573e~kl%aL!v*|7|9w<9^b5qi^T(r61<~0GRR9Tm9vEcW zz$u{PgvuYRd%P%7nGiZ_bP_U4w0|DJ1SVla*_4*A+ZpjBJt5yp9*;YOm>);iC$+4_ zhyI?IAa!t()4Rfeo|YkFI@JQiRSi7SW4!C#NbPH& z469&>yl==nJ(T#bTUHh@B-38Tx*eV{f6kqplAi9&*C!T$OF`h**9Q!ioho_&foSQw z%jI2sxH}IWw*9?Q+t-g9@&z^1iCaV7Aywk!V!R9mHnhTPzs?5L<)35uJi?kmiU* z{f?Qug{9N7X6y$l1W#*u(N2gp1ujRq(9xX9_Atb-tnReFpHs!{`>OvX_Qup}#N@V$ zcx?p{^)Z}G5LBAW;T&3d_>*Ho^>t$0%1tXTE(0Ckjf-OImLvy?^B4wJz+clZe zWg?OLm~jB#f7>~-8oDD^0h$-H`V(u3bw_3<@YpO{6f^lHfUo(D zG$HtC-jAV>B>5k`k8k<~jY2tmQ|^uz-YOOznwQCqndp04(SiE8Q_SYE*U|X(+wAc> zYZbC{bjVZm|n>w+lxaY;HXS!By9NYIszM+aoXr}h_#zOMHfd$0u z&!e>xY{AW)Fv5i-R66RD^B|!c5Sh zloudC06A;`*+O+VpsNG1#lkWE%|C6%$xca0X`c*XD`@9#L1xd`cylZ@n5V+((Qhzi zipP|hSi_fCEH8^Kk2u3Ax8(ST1D9Fmk|tA_`cu>13YgI7z)Xq+XQ)HB@~ zU_6eZfn?)N6u1wiCNRFF-1PLLlwQ8LK&%^&&^vq^3{WT(D(ajlaq$3jG4izk0XE8A zHy=E=kKHCSyDSX#jyO?NN0oTbgHXjBW+VJEB~vcPnLBg5b~#8T|J~<$G>@O1EMR8?v-eJn))>Fj5dO}Lf z0qOFv>iqmGwJZgwE1n$3}*Hq+> zYP^u*4@r{L&DH4QFS{wUi>$w}-p|2>Rs^idVA;XOf2T-yj$HAyzlx}Huh7G*xz#iE z)LG5q+=!ce0FAAJe1H}t^6~!Kyq8 z3S_#uYgTU#b(@>EYPC?e@&)hn4K(**Y0V=w62-V5SpOL}n-Q>i; zrnF&}Y!0*__4AeS$n&%oeHLX!r2-NpRSZSdhZPmDBnB}`1}Z0Ly>rkd;|COkL?+!X z9-&G$#G*v;q%`kyULqqeSJ=QmBUQ|Ng zx`Mh|1M3;Xt=97P`cDZ*>Qi@=hYz43MqntBN~oo(hUH`A8gwwuQnJeOF~0|}ehN+& z+8YgpWwSvTz7=Ll4x_#C@r5f(L+tD6tbx!#f82CYEES()XoA!C1HU6|oY<@zVd^J? z2WB)qKRBlx^FM#z)?#bVXXTMD?|cDvCnhE~sFyXhYaZKHJtM4yyZPVeJ-)l<5GfIP zN+cbEhT^q7T{m-FfdFt$h>kIO^`uJkW2B30;@U!ALmr1FT~`D3=$LEXv#b z?^c9gn+0xh=7sx;;JiER7jkNu*MdKe!5q3hUa{zRYQ#C$;>ihZlkyG}RqHiN6BKEs z=IbzM98)+c`KwhBa&|W81Dz%cvQc1Yos{4bdBg?P&G>C7gM_v$uTNPxqN$>3&5#mA zjeiSL!wTI9!nu^JYn?0GWd2nWjyPu2v-&ErH_SW*ByOkb=DpWEOEd>3Kd)S@^s09& z6MxU0$tW2@iQZ{c!j}eqs0cRYWMbL?9ab*eTq36{Fu-kDB*tyF!CGNoXEX87Xi)}O z#8a}CLfkm+VO?B-vk_if{e;d_1m*_-ziUyjAEpc!^PjwG60cYTF$dzd|U-F@XO(vL1=hHUwDgxV*2L00U5u|t7W#yBKogsf$*8j5*fp8 z_1RkK@A&2i_%+{!g|pnWnsjq4xbaptjn7Pi&+Fh-)tY`w*Ja$&Jb+V+nHOrR`YuO< zKh&I_J3)brZQHhO+qP}nwr$(Cjp=#0$=vx*=04nqFR9vl zr|O}SO4Ya5`Yi}x@p()T)B&^fBJ(i}w@p>u#@B!Bwe~m8@{=}49Ugf$%f!CGm^8hwyi`!!H6x-}Qj5-)Ah%B(CTC0WZ531q735!qEwlm@Y!)%G8(r-gr0O9F`^yoOOZNr8icM8~eh&4X zjHKS>1D29P4+Kw|(igJQYFy?IgjXHlpFL6Uqj09Uv;d|c#)ilupiNNd1}rJM@*tT; z?S(_;D?m<3D8-7pVf)6?xO(EkrM+ZlqR$@rJ}+ZA>$|#K!%v`{sP1xNM5n-zNLCQ zJ@+is;Ow}VP7LM&mDOD_luaQscvCMxtmYL@1m3y7-jpWPPQ2qp)KYuz(lA zFLSYa{J!{56ewgtP(n zkY`cxPT;KNlvsCZ%uaj+ECT9AdL=I`u|{POgr6#(Ep8wo!wdxVDpava8kZi&sIm1u z%neSMhje^WZC=x9@W5p@rGLTN)Xu6d)&mOC3^bIo zakWU68$0OF=26?mm#rA?zwIZ}t&N1Wi6AbL(d;fzRJDD4+T95_OhavK-)!jq2W>ub(W*DQ@m$#6zOI!;IYmokDWc5F-Pw{8 zC7^muTX$5^_gVO-(|W&YXrwTf_D_Spq&XVadF7*~Gje>V^B&AI@=cF&d>w?$+DI#| z4g5jmJRFpN;9vHr8=+y5QV1hm2&02`!N0(mubjCYlWk(S!Q>kXVy&)5n|psxZNN8V zd^pJYhb-SNQW@a|G$~=VwAs^ygs_$0hA)i!MFiK7wP5uF)p>k!xvc5iNQOE;6;XQrwyg!l=|;yr`#1Zofv~gtu(eV{ zV&(3d9ES*7wo$urULv$ACAivUvb_cZSMqHQsO)*eo@g|Mdo(J19F|LofR{p-OwG-TaN z*LF|jnfTx@{Tea5xAb0{^ss;Krvk=W^BsWsi1-Co7m4Zn9^O-`B8Nt$SMn8Z&X0oB zSD!w7e?OdlELyU&gTBWJByzLSbg^v!ls#2~!)3cWr;srxa!U#jgP$SQNtwi3$cFjy zaS%1dgwVkyzaY8I<@Vj{_dr6z2{dx8q1p;}OULPK**~+7&Fi4H7;I{sI?DF1Ki~q6 zk{`AKdnZB)qWA^8(&GE3I)XQ3U>QL%V5g7l{w5a}6T@{qzmSgG15pLf3o5MGl%XSG z`P-NsD)kKN)cKULf1s??&&$GK0X0KPa&B=FMv*E`RJJcsv1iY$RI@4)SWD<=$V5ft z6NxmpvH zneD~o7gA9{I92s8pcU!%^YYe2%}DE4J`q>HdS zc``bApr8PIZZ7WEbJw5NE7MFKxAgF=#Yu%uAms?_PzzhCmu~|CRCWJY!IaH(jzQnDy*x- zW>vO|aL&mC5Bm=}I(S1P15htu;=tc0o70)QF@4^lECDCICb>j98I|&~)k14_ig~G* zCC!!c2p49Fu>u;K$qUJYfI>yOUjTSn2>FOrEa&>LH z{x?UVpqifP@-9hv@y+Xcdt8-tR;^i(+A54C<^yLflMxq(N0vcBLxlmsY~#4*rshJ@ zc~Pk?y*#rjX~}PLAj@yKbmOb#veFT^&ERMS>mh~6yZWJLR78UFobaNuZcDEPg#&8{ z>xR-lR8~GnUnH6faIT#h6>ey*Qd$izRvo||8#0iF;~_>J{66eB(H)Xx{N zI-q9ndw&{8e1KtQ{clrpdqG>B2b^FZ0d4Q4TLnvrlWh4gM|xn&IRau4$7PQg8modV zV5?8y=q^vEI8pduu?jKuY%fo7jElg!aVypM+YyV`6chnOFDT!2%;` zP5cQ4pe?3qYmBg}Q{e0WNGZEg2X=SB4+qWe|LsdB=#>M0{EI6xx(xpJR_V_}5v>ZO zV{#w25v>j^W8%Qa{Ru)nkj^vYdx^CzAe?hdqY?zx3(?ggv5e7u2asPO*>4 zNTofnNGyVt$ug!e*Qv3qi$^!em~QhA`s2JRV*OSX8G=L)fVV9KnZDeT*2>iuMooZ_ z(xsY9!hNiL2z{QVqT<+uA*9js)77V)Hw(|S%jgB`U%i^9I@qLxxA>E)8O-bz;iVah zY%oglRN4Vx!K)`8OMihZ32IMcMl#_U!j#swX(Bi;cV#!kMI0^$j_g9bGGwk%o&wHF zNeZyUDaf8pYK223t^gHlWTO^Jghe+wZZK*%et{ndL*YoD|B}r72ilX4>Awvw|1Twu z4{|K@_pf(mgK_1*F8m)z9VSM`{{vI!|Iy;GG5!*2{+Amyse9NeuKZ$IHoeSL=DS^p zs&HIht_4hM0%y-bz*QUFeSw<+#@0aso#S|QgU}2t4LIuRV9+S)EJ})7jA2lX_MpIvckVYUIp0h)8OepWMo;zf8`|8II2R}PfMPxGBJ**!f$O7ML zXnSt!Jd7bDV^|o9XWLR_P^PnveU!dnk9$TmxxJ28&wMC=wfifWQh!3f%6z^-ePrqs z@>A%}C?tB21SV`2TAjU|Os2NGF178l==O{()#hGww7eArQ+61QFI=}#w(r}gpRU0k zs<@=gy?Jmw4A_+RBTg@Pw4@VX2`*+1IQm?Gzkd@XfAK!rQ{d!SHjLCAK)%4T!Z{NyM73rBg z+vN~S*-1^92I*wpx8@8jCZHyuOcT1ym11?9-vVp3h_F2-?fW9l4NEl4L(b(PR&sF3x>xD&^91Pj?&rPlfF4|$%{DNtsdX%l1^m=ib? zN9s&sNp{g>%D#rjld8%L6kq8=XCXLjQ70Nq3FW-hZq26L>og0nVp#NqxjE@fJgfy` zRC<=ihahghEYXcAI?^_p3|uIb=aYJI>db_uM?cDE{zCP$Z{?{<^JU3azl?T|t-~gGLB`f*OO@r4`Rw!zHL0s|Y0|UvZ&-DQV2*ND=Smd;MxY-W{S?hL zvMV3`)|veY@c2Mo5BIzN@_0R`&-(cFWyB$PhHB!jB4p5LDy-bQPE_G7s-{X!O*Bg7 z?ffd(&JfeEWP6$ttx6U05&Y2R4MBd&Rq7xGlom;82=3T{^EnIUrp>qwT&pBQBE8%} z@^~rOOzENDLh9PLm2h`^3G8$JSQs%jf03VPz9gv_2@!*iG^8t>rGPPk^_r*vw0g6} zT-0=IWhym%e+PNa8Hkz7kO&~8j)84;jww&opt3~)uBHv=swbLO%0&=kSS;nI4YN0y z=Ft_RRxvJD2w_ISnAiCa!<5T6cNmWi^oMU2-;qJaDpwgz8S5H7Xd5uJ88dX(yZvfa z6w{QGK9L?R{Jno;mxH|-gY$5s5Kcu3{(PB6^7CLA%*G6}J{HgcewkYS&X$*NmJBp1 z4K-bNX8PGYpl>CCb0yWT7n@g!RiVhWA^_4-`uP4$;;-RHzY}2NFZB8dw{YX#Se0jV z_|ZiTi$vaRT&BO-xt2Ym*4jpXeck<_;d9)6wpTatOL;P9uGKoDa<=6mTY&)L-QR$U zEG2zxHrF!OsI5`D_})?V+eNQ^=_R3rPuMur3-?^Lf9db9rH@pM6AI%s7Ggg=-nz1+7FlsfdmJUI&o7luj6!qAB$%HRqf0`aD z;ne0WUdViCD0HG64BwxoaX=?CHd%^EkdULqNT!fF)I5sJpZkzFYVB15P#3$MgwLwb z2O}^G7vK#w-7!TJ9!D=VifHSPK1$znqnIg*G31DU>o6&rRN>P1qA~6qTW21fa+&+s zC#a#)%$U*5QwY6KblBC6@(@Q)1l4e7nXwrXFEO8jY7}2_`9}h}VauYTW3O|gul0iZHFd;(qbZX1V=Z*G3%a`e?X7Iz<9DRG#6uS6j0_<_kWrOXbEEE`~-+M)y?* z?(?v;(uI`wYS34CGg}+L8n}+^Igr}kEOQl%jiF-_M21lgJS7US1m^xEs}q157*XNm zD*`X)r%#Z^yuZ9+jz481DE^+N*f8JW^0wg`tU#)jbZ}BUk$8F~DHn9nm#}X^7cZs9 zMx*rLLp7Z0PSio`Oofvlj$9KCbb(wW$-eXx z`HIRg?$F@-Rvfq=fc1^*l3wwkoIxXsa>AqnNWvo{_uVO1Ow-~-(l1qAI^~`+gRs_BJ zKAS=8phM2|fCQ(>-TiWs!p(}wJ0=_&Vb@(QAL0jFrh>lfC|=l}UI1aRNbg3A{Wi&C z+VryDsMzJ--+7w7DZ~MV-}w}n zc(iQg8l_ahHnl4m^Jar|Wb9x3z(Cb4x@1r1Wai``j@o;^DgDyk#mcz8B~pd>hQ>a1 z#?W9|8Q0kFS2f!uY=rNQN!`92!CiIr^>y`hD`MSw!}N6`iR?NcReCb)Lk!Iq!wp-S z`IYVZ)pWIM);xS;8n%+gKh&I=vq6LMj{&2HwrQSDBJV6|C#$+<_VRM919?{g*7Ml% zOYNO`r<{eOmyS$s;^aFoD)rkd(;=7lS0@e@2yXiFrf8!DZ`0n^Fl-b4Ly@WY-Ok>Z z!1*W1)WHNslg~eQsl=&cgSUC6`Ywm_OOZ;ewwX&;&Kg*KhOBw2C^q903Wze|3;oY@+QsZi;6NmVwy#V++FH)POR2w3~$Ei9JEmCi@vp_TmRieD6O? zlQO0(A!|_44CT>AvUle-(@;Jl(?}*Pjhk6go>s(0$qF@3W*4nDt zm9RVV5Pp`y-ur@i%Od-P``GNv|4JU-hfYA-!_W7gr@yIOTw3n>v*&KYE)u{#ge!a= zkHTQWik_3F3s^>9qF&is!c^3#I8vSa1?5rD%hLs#q$BxJ=wLpwk!ABy zEm-;W9U`InNF*{eH`63k_KVb&ks<~s+ei5E33w2so_?j(pQ_xjx&#(PCHBa(G}nr>M5zYZHA! zey@RJ6Wa^3YZAH+~tGi!GoTa_22G5(DCqBw4Lgjb9Wrt?Sch_5x`aR~R{jb| z8ADB=cNWI;u{fZWP$`9IlSrZ38U{0 zK=ecfP_&7#*>%Mz<{VSGr2^mKO}MsPNA3)~0ge#SD4=*%COF*Xt(EJIw{_1ak+pZp zhkoXIIKR#UvRhiIBl9wuX#RNS&guEbygt7?m&_e^#j!@CZKX8gaj?g0&{a}w^3(h% zc{3-*HouK!14SHtz2;sj(BcNb{-r7y=aRmLZU}L@AL2{Tl0k`h$dn;o&eRV;%)r72 zh%W_1^-zE+PD|k%jYsKgOs8Vph-OwgX++$q$imFb%tDMPN0eU6Zk`~=m5yYjSrYjt z*4N)QerJAb!6=nrs7LE6d84_N8GDV%?uUyi?y#6EoIN9x<6S1az`FpWoJ+-o%Q#%{ z1qUOGQ?r8(HT~`#7T2w-quQ9b4nP02-I;(p%{8Sh?`onzovHC&Nnl?#i&hLJRvn|P z99dt*bc>#b<|I-vHpsBuNQ^Hu= zrIygs2dIOS5ac$2&&{Ss3AW}&r<=veTFsva*ne=$06;6geo38Ig`HRJR@>P>qi!4+ zS}83OX;5h!w`{qYI12N9$?46_QRcMTDd?Q`$9GjF&Jm?p)9#xduqGjy*#aEg4tn=t z`2S=W`L=cXVx&>^XE3_&-FGR(T=J0Wujn;V7Pb0Dk&aPhP?R}Q)VGQgYaS|tErF|j zD_#pK4@nrNBomCNkw|!y+BBk&0)Zn*@6jZ^?WIYe2A&K z^v+BzE|Xm@d7Q2jPNcIqUkKVWTF=I9%!Av3`ogwUvN?a&OtKYSE?3$4QwbD3F}Uv= zWQwkEtm!=18e$Kr<2T2tP#+lM-{iPr8ps3zGV&7D;48N20;1BW99s0mLc{`~C@5Ef zXMpc+$-3|^gB&t#D{|hD8x5>$V8q=iy?w^Tg?P`z&)DVbyVP99y2nPbwy{*x9 zE2U(Y_?O z6nS`B+{~?<;ec7VqdTR-T(oG7Y(rP)-Ly5dSvX;VJ>vzbA#Dhya6AP>k2#8)!BRKh zWNpZ~tYe-jztKcxHX^LP^lc|q@?6y>2#83=>k?@sEWI+0Rfd#j#J!MAL`0U8pUIA4 z+0Em_-}qC_(IU3uVyIQtsW3Cz*x#VTJ5*=PFr^-M8EJ&w{M*J@LpmFm<+W|-;HTx< zCd~i_4>>l=SRzQ9VkjV9{AL;}jQ;h!srC|3Cci1cLMk=FAvH?xHrfsnx;yCSUUQ~6 z^Z5!d!`pfM%MNYnM<5pfT$)95+P?b819st_HVx2yqwy*0O~ zIUeNWyV-J6b@J2Wej$Rx;WKk4g40RzjoA<}lJX;IipQ5~K*8`iXdl=``U<}h9=iq%|zM)=kB__Zcu543rzNW z8q#!RimS<+Sh1{h@WNkczSI7Uzt?gudXKh++61dJX4Ppip}VoauzU>>gJ=fB!WeOC zl8xcx*?NMV;%YH*I^SG_>TL5x(-fJCFyc-t(*vL=tab=7lS8XI%1Bh!VGSb)?p`tu!?N_IW(Ir0xl z&pyE6U+E#_yQmXYvtM0j+a?cQkg%q)r*@#kRw_qP#JTj{3bh)C14qc;3?!+DGcT8` zzzS41sKmbU)-REjkQ@TQ;V{Rva&?zbL!P;+*<>|A9lXJ+kp(wZV~5s;d5{h)*CSj{v^;)Lw%i1H31l-qL% zF;26XqOfH#ncq^Z^Qrk5#BR&{iYYmTV55K!WyG`<|bOSE$Hnsq; zG&`4S*DNtf%PK#CLj)dyUljX!W^XO}|1J=cD&ti2JbjrU(G9?GD9m>^DDl!&Nqo|n zLTN4bZ|Xq1FUFZ`D1GOWl}YIhEuO-4N!m{BiLPY{SFwjCtSCC zA5hN)F=i$rmAVF1pU`kB*?jyL!yUFv?t+3DFZ#M$aAeZGRYY2(Q(tn=v6rh>r-Ii? zYMWJ2bQK9ibo6$%a;WUTEu{~JeF(Cs=`DQP_h)c3awaYNC8*vvoyMGpod=oqFPfTD zF{P9>%-+~0NGM4t50bNvrQ{V)CzifADEe8>ZGdfDtrbhISSnd;#X*=qS9Q;ve4b#! zV2}$w@4G9LyECc88-Rvbr@DkjP~(>0s3nvSe~@j{j5YRqaB8rpjk zf0-5-g!(|M(@X%l&|<&fSY{8%|D!|8{2#pi|6f|a%>NMt@{2_Jzu7R^=>IotlDdVh z#)#AQ7SygkFgUzT{O*DOU%2?zTtRZ$K`;2wH*;`QZ zg_J}Kl0;N5m)C2*-QR~*2O|7Pcyf^w_>jQQvV?v=x{C$c2TFd|i}||%5g95@cbwA| z_;OpE$t@qOWpV`iEnjV)+tC1t?PZf5paU0#dTtL>x)#~*?-0G36B}JFdvIb`svjY= z9$15$yaEy#674xh{KZngI~^Rhm|;T=Jr%NpoU>3qU7-cXO?SJ*S1FO(~m=?VtNqDE$*o{(91GCaY_+U?2Zn(A#l zrV5tDIpS;`c!tZap{IzBTP>3kF$+)4HIKL17L@`bZl~{%iYk}=e;`;u-O#Hgaak`4 zn=qbfOxz%1{{GK}Na%c`T71P@WI`-#3Cir7;tIqagq4?K6oV-r{y1lH+%!109-NTl zq@>ia+QMi<4Rx{pL_(v~LC6FUQ2zE-nscuv)GT}Vt^_%|Yl7N)>YTM`f0YAKT61faE`W$!N*WHXHwB5Qj5*Qy;z$;1kBiHb zuHnek#r6*RCPGU^&vZ$L1$i|ikC5$k#roW0`RAGgk+l&^OM_j%!$Gm(Pa(oHr(}~a z@sN~gw2om&vqPI)m+NQ}m^bn@xj?}90$ES9P!K8fqt}D>f;N#Aglq$1E#&>31~+rv zgZ8L5P-rgsuQkf8HVqR~`BPwyu+TQB-07*ZW99Ktz{N`m0C{vK0l8fbG}-A`mV>uDi|wXtLf> z_($Y}yev1*t4VQozFV05)bu79lJm-<$UpnpNj@*~c`Cj&xFdh!Pk;Vw`7Rp<9)6M0 zK)!?59k&x*tKM8s_b(~EG9^|X;q%|41;E!iA2r}(K^NF#f!DuN5f6mlo?mT+?@T)$eP5dH4O zzP0RGV?`<=YdksGAC&{qOw>@ZuQ_V8)1^%dkv*+bZ+9TfC3KiT zEcyJcAg^(dBYfYg9++qco)BA-xbAP%&m$dk5haeMrWp!Io(stI#r7mYW4Q?#Mk=5* z-`IR1{*5$`46w8*Ty)aW^JmwiY}Jb+(4D5#mgn z-}Jno^G7yTD9D+Xq(7ZdD?Y?K--xx}!?kT#X|W`XAq1^IDyPIpw!)rZd0Y$xAkWB> zqT2;^t=9|&?4L>VFCwf#ZC}%k_xOC13o*M;ZSks=4p>~J;y~JT@fOIg+e7&?iG)8% z7E{3NxRK7*o?A)>TVquc$%th(FIKUH-NxmVRDjkhZd09Kv83u`;bKMf**Go(31pAP z>QGgyuz>Ae3+I6zo(tukBV9cAU-=mbYf?))xMUCJ-lTd_5OSsNy@7TCgch` znhg+65(xf9DEpFJPVo1zocI=zKVT#{??3k%n|#d$ECX zF0=oVV@b{Gs~_P>uVjI+#-T!uG%Dr+?>Y~tA2{|{EnCR4c;O_(k=v1nr~m<=#9Sp- zVlm=Mp(x1kT*OlF)d1-rfr|%I9nl-o?C@46t;Z7p^!@K;_2Yjl{I_BrISso2bD#eN zq5s-SVwTz%WzRK(@Abr|WVwZ}3Opmzi+-!XW!P_3=B99vvnv5n&7FkEK9K}s5O7=| zjPodO@Xv1%Bv61ZA|^!0gQaOEvJW2SFX|EhExOjTmorZr6Ds>BNiB{I66vuF<4S`` z_Qi{%Fm}a@Qd2VL;7i%xZyDJwSaz;nK&aU_w=nPqd|E%$!AK zoz;@T%-q{U&ZGUHzDohm&*ij8sKK5eQRRK+W6aSc#5Sb2P?Dl?cK1x;Yq7j zkHpicC844eR_Ksc1U!V76&7JKPAFE0qXwuBwuqO1igVr+)&c-bx7w;v)r)&u7Dm3! zl}A;s#9=jS@7Yu_GMLSLcpA3$Uw8e=hStszF2^Pg=IXYV58980>Dg-EhqL!1cpJuT z%aU@IyB;^!-doJxev;oq4A#d>1Rj!Za5a!IR(Wz30Jm>Je?R;YWo92jqh0=$yEU;$ zU9k_5@1oc10PSo(Xj}5YqN}4f5BVA#Y9ngI@NVFi-nK!6YA<9VZZcgFsFLt;gwHAyXoKJnNm&cY(#|s>%x8<4P<(+{Cs`~Vmwkdk-*ph_FjoZ`wkO-{zRox!LjFk6x z-bwNCye-d?#K@z4zOx%tZh7ATyRChwTxV#bx;3nwCbN(t)f92a)FC4W7ivTlm{nYK zOIYS;+4e|Fif8nxa};+fN4iD!7?+#tTZ;mR$05QmcgWD{PN%L0+^)&xb4-nG(>+1I z<9+%Z=95`>SER~*_G~vaSk?xp;143!NNn$eZq>k~y7%D&sF(Wj8xbzhUk5e`U*LRc zk_Z5wULE`9f9N)i-8(By4iTK}%~#!XAtUXW@fz_S>!8HJ1QK-iO+{pzvX~dpjmwOY zH=E6kUd)@Ttf&e7*TadM%{7?4r$Cvk$#9(ZTp$4%1@%S>7t)2r0OY90WO(|Cw$VLX z91SlHpz>&4ZxHdgMK@@x9bmsd;w_p(W!%ut)8)?1ZrD+aVV*=2{$O_O#%kvhJ=Lr| zj2R?hX?*rGy`pNK#}W-U8dxsqcRr{UQPBeb>^?ysmdIkK!Clbgc%LyIv3{-ORlx_$ zt-sGHZqB@pf4T>dRd!8u3_c&2&n(BDjv*M;gAd9Y zrV!QAR@P(uT?)UKK*>c=1P48G{>Y@JZeytdU0c)6i^=Y7yPwjQkp+TRQ7MNz|EwCv z)Azl;jLhy>)-ER~>nZ@X7XL~ff))G}l>%?K3(Vako2@y2I*yiQ~zjL9%l&{MZYS-dYT&QLEjCO!RC@#W4J^o$zX-^FBkIL3YW~ zp>nyTl@7Lcah%ikq^^>ECk-qMSHrtgu2^^g^muCj_)s)|k*Zt4i-B({VZk&~f)4CiPt)uG<^=xc|=>QYp~>ik_+q(!ZO zi{$UT4J~iH;oV85(Ljn1XtGWOFqHgxcD4)r!oez_u$4$u*6CXnWv8BK@o8bVe%^>d ziKx-^cYSn%mS*$GJ2pIByhFDZQ&P4FHeUTyoN`Hm-1yJ_1quWX!Ri^S=)9TP$+tmspY>nW?VR-Vg2V&p&s^o|P}la_K;a zT~RzYqW$d?P=H4UP$#c^y{S4!-RT?uWh`CHCW|wx6VCQp7XrgLf4cIVWnSZ12^7pf z<~fpP6JHN9m(;!DfBGiecwj+>uuO#Os0)LiTd14;q*Dk)m4++vct645F`$A1feZ-F_1ze60-G9VtZWBW#iOo4`SHyQ-!L_`6H7m~t}R=YVY zqIyAhkW)8NuES8wR=ls6t=`K9F=n(V&o}rf4FSB^WVt@Y>VOYTyNKu;-YO@fZ)W5zCXxDtK|hpt%+rKGaS_sQ ziK%nl4O7jku=#;Y!IeBl4df+TXQjr6de~+RsD9!Fct}!z|ATkWbG8JCWx+kYyoPiU z7Dqd%@soySyw5kcS0ch}Xh-FaZT(DN+p33}!>33zW7cp1AJxf)?vz8dg-q|+K0uaq z{}kj|fw*rb5lL&@o?|92SyJx|#jU;gDAP#&OTbmc`6Lip1}VBPD^cCWI8ml?1BVv3 z6u(ql4%1ZVz(qAT0@hhukocr>%ziy{nFh6!bG9=_+X0h)w|#l4gUyz{^>jFwxAx!_ zbNRvhqn7?}3Vz0>Z_BvU;AP^NoS#t>B)E~sau`@XKH>Q7=`dTSZZKO(2Yd7(bh?V@ zGMH0G%r3vRa%>%K*A1Br{}`HwHXl6|4J)eCMyEoNCkm!xu<~ zPWiW~xKV*rjCpji;=jqXxG{YswataWwmzo2Z}XM~f}t%yTB;jq@xtJod1)C`AIV7x zEm@c9Z&1s3xmcM(8aUpOH7nT=e@4ukbw!+rQaNbr&a3AA*XDIs0@TPyumLJ;ps%>L z(|cKu8`;L+U6Ndl^h*LJd)CFnDio_~Lzfd%2Xd^d=l4I)C_3?D$aTdq84U2@jY#A`w&jx9(2C>AH?rLE1CKk6~f+A}2_zdzF^9tpi+f z-t+9*+-tOkT*f+_6PQ}n_5;jyH3~K(9Ec{5CrFCXR(K;Wcxi0-#8#AEN&4}$E(LLE zMsaBerjp6VdZPpk64z?{4i~7ecT}-bB0boRl)vx*OYtf8LWLgQI`!ZKn=UU? zcb^p~^Kk0%SB%&G3)^W4+i7g`>(49;>sMB&+k7f`XQ4ZZAcl_;p5%{|qqZ!Qu;1SM z6U%n*HD*m`zoBLq;1h7toZv%G+!#1mL0*(h=#ueYKcw-vKZWQs?=2JboSCyMj)Mn%J^-6LLM278 z>~&EHs-tOaEs)wce8>6MwYlkG*n2rUuGOS4xLN-VG?Qng^Y-Qk#cf26tZMh%`m510 zP1jjh8Yy>CS0Q?!=7_+6XcN^34;;AJj_;F=1x;V~2=muXD8L)3;9<IF0`8TurmRr1j{zo(=9ozrR4^VWoHNvBj(KlCcw1T9O#$)_HHOGa`>>V8O7-(t#S5fqos+G+K zGyFHj=c;}vVf@H%LcnpM6sF}xaIr=U`q%D|I{9QAjE2^VPtQqov;L5ErlAlWa2@Hn ztBdD#+ku#{(l|MNcw)4en-O`9KRteFsiinMnMve)(*0rLGWlz6qZ~s2y8gCnQJu1f zCcZ9y8C|0o1&o+U9jiY1E`IXssqUW`O0ofhKng+r`f*;JN?RkHOgT`A{1KG*c)b$a zCO)-L#aln6RbL9l_t?ZIw0>&A(*2Lp(O)QND?g8!(3n!EhKiD_=&D9L!#ml z+*4y3*36IGL3t_iPsbr7Qf3QzJT-u^Aq%RdbVzyYD;d6 z7*X2YuHQ?hOlo*+#ZDdNB_bmaYmO5f+G=I@Y94es%vVL^Gk7aZTO1aP{~37ROYVW%nm4CT}NlDl^%vA@3$}!FzW< zK4(jXX-*F$0QqGmLmgxGax^_vZq2Q!I$IJ;9n~6@*@;IXaJb><;>fUj$w`S)8pdC0 zUk4kj9`?_PCa-C~MxMU-hnR}$Zgz{GOb4WRI4Q~lJemw479D#Tf(4t_!zgTZcyY~_ zSQ!Ika~!ux51c*x^YRgJspZsJe71>)K7Imo91tevXbbl7i`8M@IN^UR&wd^-sLQPN z_)?sOz)WtaPHvILqQRUNhM_n%lD2nLEavc|^<_H7GqJwcKG z5JQE^C%C7I8FK;qFVj0#@|EJ`^t4362AzXs5cFQBxL`gb^o<)ipKpIaCvXcNa3wMVLgiQQEdw z&0AoxcAM~TW8g& zG4=Dq<0GeK=_=&iHMN5dBV^IFv`pw#L)h>Gfr<>(smo1?#R+88&4e&#r6Ywrjwgj~ ziFC6tot8>E#How*K!^H+$VH{vmp#TTMHDKJqru%_)V0T@v0As5ycdO;HHKGb$2V+A zB0K2_0Dq1wdr6g>w9{2)js?XDj|ud{-G##L;UY3eNfSPb3HTI%6jxs~dz`?$I5 znE7e5dC@_`b1V=Qo<6Ur-H>16-H?C6nm&){12ps9Fq3CVcL#qOjJ;2|(hGQ^3@&W@q7n8hG=n3y4@CRXA2cGD!$YK3m=%h@ zAVi(z1agMT(m$pwz-kUeuTtpynHLiIJBj%7)(Pc=Yt-nH)Yg#EgMK`8bXNPhpxQZ5 z(Nw`sFprpS#@Fd2_R+>XoEnXZV|hnWi6MBLt7#de$xHlcg7?|foO&;B3v$vhSDY)+ zky4@_ZTrn1cA3>v-Lb6KYgBnSzI^-Tc^Q`)U9Fr6e+X&m9F4 z^te4_h?c|?X(#DOvV&U;ypSXeMfhduth9iW>|_V*^!NtJ8aGTW7zYd5{eqJ-ftd== zB=}q;K3d_p+JW4e3rw&IPNH%}9@*v=KGVR_TVQfA|D5)~`-Y^Cf%%{Qvw0n5_s*?K zfx;NXByGnJ--eNUq=S`vTp_Km#pFi|h99N@-uu<#04bnRsSU?8-$h(!zY=lu&YW9) z%JT_)&I9o1c;SD-W>%o{VO@Zcx+2@y(-uYM71Fw+j~yCbPxSqdnLJ6jame69`Mq48 zy>dx6VRXm%gWqLbQ#sn-OqO#lqOkz{1Gb z#mULg)WX!z&BVaXz|Fqllh8?dz1t;POyXq=reUNkeP;^eK#rfrofcF*)DxWN%T^V3-|H zZD6=&1EW{sVW)HZe@vQuCQ0RQbfoGPzMht^Qok75J(OCNWgfFEw>WHh>4ZWz_mhH7 zn{@#Wg4Z>6%ATBSztei!{CQ9BY1G_(AeMUPp&b8;9s4<|TUI^RDB&$Vet)5KM%9B0 z{TY=TCdSu2`99S~_vB{FYoChL>-U_TAN@01 tags, String codeUrl cv("cv-charcoal-gold-v2", "CharcoalGoldExample", "Charcoal Gold", "Charcoal sidebar with a ringed photograph, rated skills and languages, beside a paper column with a two-tone name, a dated experience rail and paired credential columns.", "sidebar", "photo", "gold"); cv("cv-terracotta-rail-v2", "TerracottaRailExample", "Terracotta Rail", "Serif monogram over a terracotta rule, contact channels behind their marks and two bulleted lists, beside a letter-spaced masthead, roles on a ringed rail, a projects grid and the degrees.", "sidebar", "monogram", "terracotta"); cv("cv-teal-pulse-v2", "TealPulseExample", "Teal Pulse", "Clinical sheet in five bands: a heart crossed by a pulse beside the name, a contact strip on rules, competencies beside the summary and roles, and a three-column closing band over a tracked tagline.", "clinical", "badges", "teal"); + cv("cv-slate-orange-v2", "SlateOrangeExample", "Slate Orange", "Full-bleed slate masthead with an orange monogram tile, over a sidebar of marked competencies, trophied achievements and rated languages beside a profile, a dated experience rail and a credentials footer.", "sidebar", "masthead", "orange"); // ===== Templates / Cover Letter (v2 layered, paired 1:1 with CV) ===== // Registered directly: letter() points at the layered preset examples under diff --git a/examples/src/main/java/com/demcha/examples/support/SlateOrangeSampleData.java b/examples/src/main/java/com/demcha/examples/support/SlateOrangeSampleData.java new file mode 100644 index 000000000..00220b388 --- /dev/null +++ b/examples/src/main/java/com/demcha/examples/support/SlateOrangeSampleData.java @@ -0,0 +1,207 @@ +package com.demcha.examples.support; + +import com.demcha.compose.document.templates.core.identity.Contact; +import com.demcha.compose.document.templates.core.identity.Link; +import com.demcha.compose.document.templates.cv.data.CvDocument; +import com.demcha.compose.document.templates.cv.data.CvEntry; +import com.demcha.compose.document.templates.cv.data.CvIdentity; +import com.demcha.compose.document.templates.cv.data.CvName; +import com.demcha.compose.document.templates.cv.data.CvSkill; +import com.demcha.compose.document.templates.cv.data.EntriesSection; +import com.demcha.compose.document.templates.cv.data.ParagraphSection; +import com.demcha.compose.document.templates.cv.data.SkillGroup; +import com.demcha.compose.document.templates.cv.data.SkillsSection; +import com.demcha.compose.document.templates.cv.data.Slot; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Shared sample data for the Slate Orange CV example. + * + *

The sample is the preset's reference content: a one-page CV with four + * contact lines including a link, ten marked competencies, three + * achievements, three rated languages, three closing facts, a profile, four + * roles, a degree and four certifications.

+ * + *

Kept in lockstep with the qa module's {@code SlateOrangeFixtures} — + * the two modules cannot share a source file, so a content change here + * belongs there too.

+ */ +public final class SlateOrangeSampleData { + + /** The break a body stacks its lines on. */ + private static final String NEWLINE = String.valueOf((char) 10); + + private SlateOrangeSampleData() { + } + + /** The single-page reference CV. */ + public static CvDocument sample() { + List placements = new ArrayList<>(); + placements.add(new CvDocument.Placement(Slot.MAIN, specialisms())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, competencies())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, achievements())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, languages())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, facts())); + placements.add(new CvDocument.Placement(Slot.MAIN, profile())); + placements.add(new CvDocument.Placement(Slot.MAIN, experience())); + placements.add(new CvDocument.Placement(Slot.FOOTER, education())); + placements.add(new CvDocument.Placement(Slot.FOOTER, certifications())); + return new CvDocument(identity(), placements); + } + + private static CvIdentity identity() { + return new CvIdentity( + CvName.of("DANIEL", "HARPER"), + "VERSATILE PROFESSIONAL", + new Contact("(555) 123-4567", + "daniel.harper@email.com", + "Austin, Texas \u2022 Open to Relocate"), + List.of(new Link("LinkedIn", "https://www.linkedin.com/in/danielharper")), + Optional.empty()); + } + + /** The strip under the role. Only the body is drawn; the title names the berth. */ + private static ParagraphSection specialisms() { + return new ParagraphSection("SPECIALISMS", String.join(NEWLINE, + "OPERATIONS", "CUSTOMER SUCCESS", "COORDINATION")); + } + + /** The competencies, each behind the mark its entry names. */ + private static EntriesSection competencies() { + return new EntriesSection("CORE COMPETENCIES", List.of( + CvEntry.builder("Customer Service Excellence").icon("customer-service").build(), + CvEntry.builder("Operations & Process Support").icon("operations").build(), + CvEntry.builder("Project & Calendar Management").icon("calendar").build(), + CvEntry.builder("Data Management & Reporting").icon("reporting").build(), + CvEntry.builder("Communication & Stakeholders").icon("communication").build(), + CvEntry.builder("Problem Solving & Adaptability").icon("problem-solving").build(), + CvEntry.builder("Sales & Relationship Building").icon("sales").build(), + CvEntry.builder("Microsoft Office & Google Suite").icon("office-suite").build(), + CvEntry.builder("CRM Systems (Salesforce, HubSpot)").icon("crm").build(), + CvEntry.builder("Time Management & Prioritization").icon("time-management").build())); + } + + /** The achievements: a bold title over its body, beside one shared trophy. */ + private static EntriesSection achievements() { + return new EntriesSection("SELECTED ACHIEVEMENTS", List.of( + CvEntry.builder("Process Improvement") + .icon("achievement") + .body("Designed a new tracking system that reduced reporting time " + + "by 30% and improved accuracy.") + .build(), + CvEntry.builder("Customer Satisfaction") + .icon("achievement") + .body("Maintained a 96% customer satisfaction rating through " + + "responsive support and issue resolution.") + .build(), + CvEntry.builder("Revenue Contribution") + .icon("achievement") + .body("Consistently exceeded monthly sales goals by 15\u201320% " + + "through relationship building and consultative service.") + .build())); + } + + /** The languages, each carrying both the rating and the word for it. */ + private static SkillsSection languages() { + return new SkillsSection("LANGUAGES", List.of(new SkillGroup("LANGUAGES", List.of( + CvSkill.of("English", 1.0, "Native"), + CvSkill.of("Spanish", 0.8, "Professional Working"), + CvSkill.of("French", 0.4, "Basic"))))); + } + + /** The closing facts, on the same mark column at a wider pitch. */ + private static EntriesSection facts() { + return new EntriesSection("ADDITIONAL INFORMATION", List.of( + CvEntry.builder("Availability: Full-time").icon("availability").build(), + CvEntry.builder("Willing to Relocate: Yes").icon("relocation").build(), + CvEntry.builder("Remote Work: Open to Hybrid/Remote").icon("remote-work").build())); + } + + private static ParagraphSection profile() { + return new ParagraphSection("PROFESSIONAL PROFILE", + "Adaptable and resourceful professional with 6+ years of " + + "experience across operations, customer service, sales, and " + + "project support. Known for strong communication, " + + "organizational skills, and the ability to thrive in " + + "fast-paced environments. Adept at managing priorities, " + + "building relationships, and delivering results that drive " + + "efficiency, customer satisfaction, and business growth."); + } + + /** The roles held, each a headline over its bullets. */ + private static EntriesSection experience() { + return new EntriesSection("PROFESSIONAL EXPERIENCE", List.of( + CvEntry.builder("Operations Coordinator") + .subtitle("BrightStart Logistics, Austin, TX") + .date("Jan 2022 \u2013 Present") + .body(String.join(NEWLINE, + "Coordinate daily operations and scheduling for a team of " + + "12 across multiple sites.", + "Develop and maintain dashboards and reports to track KPIs " + + "and operational metrics.", + "Streamline communication between departments, reducing " + + "response time by 25%.", + "Manage vendor relationships and assist with contract and " + + "invoice reconciliation.")) + .build(), + CvEntry.builder("Customer Support Specialist") + .subtitle("TechWave Solutions, Remote") + .date("Jun 2020 \u2013 Dec 2021") + .body(String.join(NEWLINE, + "Provided technical support to customers via phone, email, " + + "and live chat.", + "Resolved an average of 40+ inquiries daily with a " + + "first-contact resolution rate of 92%.", + "Created knowledge base articles and improved internal " + + "documentation.", + "Collaborated with product and engineering teams to " + + "escalate and resolve issues.")) + .build(), + CvEntry.builder("Sales Associate") + .subtitle("Urban Outfitters, Austin, TX") + .date("Mar 2019 \u2013 May 2020") + .body(String.join(NEWLINE, + "Consistently exceeded sales targets by 15\u201320% through " + + "product knowledge and personalized customer service.", + "Built and maintained strong customer relationships, " + + "driving repeat business.", + "Merchandised floor displays and contributed to visual " + + "standards and promotions.", + "Recognized as \u201cTop Performer\u201d for Q4 2019.")) + .build(), + CvEntry.builder("Administrative Assistant / Project Assistant") + .subtitle("Greenfield Nonprofit Initiative, Austin, TX") + .date("May 2018 \u2013 Feb 2019") + .body(String.join(NEWLINE, + "Supported project managers with scheduling, documentation, " + + "and meeting logistics.", + "Managed calendars, travel arrangements, and expense " + + "reports.", + "Maintained donor records and prepared reports for " + + "leadership and stakeholders.", + "Assisted with event planning and community outreach " + + "initiatives.")) + .build())); + } + + /** The degree; the design's third line is where and when, as one line. */ + private static EntriesSection education() { + return new EntriesSection("EDUCATION", List.of( + CvEntry.builder("Bachelor of Arts in Communications") + .subtitle("University of Texas at Austin") + .place("Austin, TX \u2022 Graduated May 2018") + .build())); + } + + /** The certifications, one bulleted line each. */ + private static EntriesSection certifications() { + return new EntriesSection("CERTIFICATIONS & TRAINING", List.of( + CvEntry.builder("Google Project Management Certificate (Coursera) \u2013 2023").build(), + CvEntry.builder("HubSpot Customer Service Certification \u2013 2022").build(), + CvEntry.builder("Microsoft Excel: Advanced Formulas & Functions \u2013 2021").build(), + CvEntry.builder("ServSafe Food Handler Certification \u2013 2019").build())); + } +} diff --git a/examples/src/main/java/com/demcha/examples/templates/cv/v2/SlateOrangeExample.java b/examples/src/main/java/com/demcha/examples/templates/cv/v2/SlateOrangeExample.java new file mode 100644 index 000000000..698d32580 --- /dev/null +++ b/examples/src/main/java/com/demcha/examples/templates/cv/v2/SlateOrangeExample.java @@ -0,0 +1,51 @@ +package com.demcha.examples.templates.cv.v2; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.templates.api.DocumentTemplate; +import com.demcha.compose.document.templates.cv.data.CvDocument; +import com.demcha.compose.document.templates.cv.presets.SlateOrange; +import com.demcha.examples.support.ExampleOutputPaths; +import com.demcha.examples.support.SlateOrangeSampleData; + +import java.nio.file.Path; + +/** + * Renders the layered {@code cv.v2} Slate Orange preset against the + * operations sample. + * + *

Output: + * {@code examples/target/generated-pdfs/templates/cv/cv-slate-orange-v2.pdf}.

+ * + *

The preset owns its page geometry — the sheet is drawn to the paper edge + * and every column pads itself — so the session starts unconfigured.

+ */ +public final class SlateOrangeExample { + + private SlateOrangeExample() { + } + + /** + * @return absolute path of the rendered PDF + * @throws Exception if rendering fails + */ + public static Path generate() throws Exception { + Path outputFile = ExampleOutputPaths.prepare("templates/cv", "cv-slate-orange-v2.pdf"); + CvDocument doc = SlateOrangeSampleData.sample(); + DocumentTemplate template = SlateOrange.create(); + + try (DocumentSession document = GraphCompose.document(outputFile).create()) { + template.compose(document, doc); + document.buildPdf(); + } + return outputFile; + } + + /** + * @param args ignored + * @throws Exception if rendering fails + */ + public static void main(String[] args) throws Exception { + System.out.println("Generated: " + generate()); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeFixtures.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeFixtures.java new file mode 100644 index 000000000..7557c0bf3 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeFixtures.java @@ -0,0 +1,206 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.templates.core.identity.Contact; +import com.demcha.compose.document.templates.core.identity.Link; +import com.demcha.compose.document.templates.cv.data.CvDocument; +import com.demcha.compose.document.templates.cv.data.CvEntry; +import com.demcha.compose.document.templates.cv.data.CvIdentity; +import com.demcha.compose.document.templates.cv.data.CvName; +import com.demcha.compose.document.templates.cv.data.CvSkill; +import com.demcha.compose.document.templates.cv.data.EntriesSection; +import com.demcha.compose.document.templates.cv.data.ParagraphSection; +import com.demcha.compose.document.templates.cv.data.SkillGroup; +import com.demcha.compose.document.templates.cv.data.SkillsSection; +import com.demcha.compose.document.templates.cv.data.Slot; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Shared fixture data for the {@link SlateOrange} gates — the SAME document + * feeds the pixel parity test and the layout snapshot test, so a geometry + * shift the pixel budget absorbs still trips the exact snapshot, and vice + * versa. + */ +final class SlateOrangeFixtures { + + /** The break a body stacks its lines on. */ + private static final String NEWLINE = String.valueOf((char) 10); + + private SlateOrangeFixtures() { + } + + /** + * The canonical one-page CV — the monogram tile, four contact lines + * including a link, ten marked competencies, three achievements, three + * rated languages, three closing facts, a profile, four roles, a degree + * and four certifications. + */ + static CvDocument canonicalCv() { + List placements = new ArrayList<>(); + placements.add(new CvDocument.Placement(Slot.MAIN, specialisms())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, competencies())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, achievements())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, languages())); + placements.add(new CvDocument.Placement(Slot.SIDEBAR, facts())); + placements.add(new CvDocument.Placement(Slot.MAIN, profile())); + placements.add(new CvDocument.Placement(Slot.MAIN, experience())); + placements.add(new CvDocument.Placement(Slot.FOOTER, education())); + placements.add(new CvDocument.Placement(Slot.FOOTER, certifications())); + return new CvDocument(identity(), placements); + } + + static CvIdentity identity() { + return new CvIdentity( + CvName.of("DANIEL", "HARPER"), + "VERSATILE PROFESSIONAL", + new Contact("(555) 123-4567", + "daniel.harper@email.com", + "Austin, Texas \u2022 Open to Relocate"), + List.of(new Link("LinkedIn", "https://www.linkedin.com/in/danielharper")), + Optional.empty()); + } + + /** The strip under the role. Only the body is drawn; the title names the berth. */ + static ParagraphSection specialisms() { + return new ParagraphSection("SPECIALISMS", String.join(NEWLINE, + "OPERATIONS", "CUSTOMER SUCCESS", "COORDINATION")); + } + + /** The competencies, each behind the mark its entry names. */ + static EntriesSection competencies() { + return new EntriesSection("CORE COMPETENCIES", List.of( + CvEntry.builder("Customer Service Excellence").icon("customer-service").build(), + CvEntry.builder("Operations & Process Support").icon("operations").build(), + CvEntry.builder("Project & Calendar Management").icon("calendar").build(), + CvEntry.builder("Data Management & Reporting").icon("reporting").build(), + CvEntry.builder("Communication & Stakeholders").icon("communication").build(), + CvEntry.builder("Problem Solving & Adaptability").icon("problem-solving").build(), + CvEntry.builder("Sales & Relationship Building").icon("sales").build(), + CvEntry.builder("Microsoft Office & Google Suite").icon("office-suite").build(), + CvEntry.builder("CRM Systems (Salesforce, HubSpot)").icon("crm").build(), + CvEntry.builder("Time Management & Prioritization").icon("time-management").build())); + } + + /** The achievements: a bold title over its body, beside one shared trophy. */ + static EntriesSection achievements() { + return new EntriesSection("SELECTED ACHIEVEMENTS", List.of( + CvEntry.builder("Process Improvement") + .icon("achievement") + .body("Designed a new tracking system that reduced reporting time " + + "by 30% and improved accuracy.") + .build(), + CvEntry.builder("Customer Satisfaction") + .icon("achievement") + .body("Maintained a 96% customer satisfaction rating through " + + "responsive support and issue resolution.") + .build(), + CvEntry.builder("Revenue Contribution") + .icon("achievement") + .body("Consistently exceeded monthly sales goals by 15\u201320% " + + "through relationship building and consultative service.") + .build())); + } + + /** The languages, each carrying both the rating and the word for it. */ + static SkillsSection languages() { + return new SkillsSection("LANGUAGES", List.of(new SkillGroup("LANGUAGES", List.of( + CvSkill.of("English", 1.0, "Native"), + CvSkill.of("Spanish", 0.8, "Professional Working"), + CvSkill.of("French", 0.4, "Basic"))))); + } + + /** The closing facts, on the same mark column at a wider pitch. */ + static EntriesSection facts() { + return new EntriesSection("ADDITIONAL INFORMATION", List.of( + CvEntry.builder("Availability: Full-time").icon("availability").build(), + CvEntry.builder("Willing to Relocate: Yes").icon("relocation").build(), + CvEntry.builder("Remote Work: Open to Hybrid/Remote").icon("remote-work").build())); + } + + static ParagraphSection profile() { + return new ParagraphSection("PROFESSIONAL PROFILE", + "Adaptable and resourceful professional with 6+ years of " + + "experience across operations, customer service, sales, and " + + "project support. Known for strong communication, " + + "organizational skills, and the ability to thrive in " + + "fast-paced environments. Adept at managing priorities, " + + "building relationships, and delivering results that drive " + + "efficiency, customer satisfaction, and business growth."); + } + + /** The roles held, each a headline over its bullets. */ + static EntriesSection experience() { + return new EntriesSection("PROFESSIONAL EXPERIENCE", List.of( + CvEntry.builder("Operations Coordinator") + .subtitle("BrightStart Logistics, Austin, TX") + .date("Jan 2022 \u2013 Present") + .body(String.join(NEWLINE, + "Coordinate daily operations and scheduling for a team of " + + "12 across multiple sites.", + "Develop and maintain dashboards and reports to track KPIs " + + "and operational metrics.", + "Streamline communication between departments, reducing " + + "response time by 25%.", + "Manage vendor relationships and assist with contract and " + + "invoice reconciliation.")) + .build(), + CvEntry.builder("Customer Support Specialist") + .subtitle("TechWave Solutions, Remote") + .date("Jun 2020 \u2013 Dec 2021") + .body(String.join(NEWLINE, + "Provided technical support to customers via phone, email, " + + "and live chat.", + "Resolved an average of 40+ inquiries daily with a " + + "first-contact resolution rate of 92%.", + "Created knowledge base articles and improved internal " + + "documentation.", + "Collaborated with product and engineering teams to " + + "escalate and resolve issues.")) + .build(), + CvEntry.builder("Sales Associate") + .subtitle("Urban Outfitters, Austin, TX") + .date("Mar 2019 \u2013 May 2020") + .body(String.join(NEWLINE, + "Consistently exceeded sales targets by 15\u201320% through " + + "product knowledge and personalized customer service.", + "Built and maintained strong customer relationships, " + + "driving repeat business.", + "Merchandised floor displays and contributed to visual " + + "standards and promotions.", + "Recognized as \u201cTop Performer\u201d for Q4 2019.")) + .build(), + CvEntry.builder("Administrative Assistant / Project Assistant") + .subtitle("Greenfield Nonprofit Initiative, Austin, TX") + .date("May 2018 \u2013 Feb 2019") + .body(String.join(NEWLINE, + "Supported project managers with scheduling, documentation, " + + "and meeting logistics.", + "Managed calendars, travel arrangements, and expense " + + "reports.", + "Maintained donor records and prepared reports for " + + "leadership and stakeholders.", + "Assisted with event planning and community outreach " + + "initiatives.")) + .build())); + } + + /** The degree; the design's third line is where and when, as one line. */ + static EntriesSection education() { + return new EntriesSection("EDUCATION", List.of( + CvEntry.builder("Bachelor of Arts in Communications") + .subtitle("University of Texas at Austin") + .place("Austin, TX \u2022 Graduated May 2018") + .build())); + } + + /** The certifications, one bulleted line each. */ + static EntriesSection certifications() { + return new EntriesSection("CERTIFICATIONS & TRAINING", List.of( + CvEntry.builder("Google Project Management Certificate (Coursera) \u2013 2023").build(), + CvEntry.builder("HubSpot Customer Service Certification \u2013 2022").build(), + CvEntry.builder("Microsoft Excel: Advanced Formulas & Functions \u2013 2021").build(), + CvEntry.builder("ServSafe Food Handler Certification \u2013 2019").build())); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeLayoutSnapshotTest.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeLayoutSnapshotTest.java new file mode 100644 index 000000000..38afc1408 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeLayoutSnapshotTest.java @@ -0,0 +1,32 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.templates.TemplateTestSupport; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Exact layout snapshot gate for {@link SlateOrange} — freezes the resolved + * geometry of the canonical one-page CV, which the pixel budget cannot see: a + * small column or spacing shift stays under the visual-diff budget but changes + * the snapshot. + * + *

The preset owns its page geometry, so the session starts unconfigured.

+ * + *

Refresh with {@code -Dgraphcompose.updateSnapshots=true} after a + * deliberate layout change, and commit the JSON with the change.

+ */ +class SlateOrangeLayoutSnapshotTest { + + @Test + void canonicalCvMatchesLayoutSnapshot() throws Exception { + try (DocumentSession session = GraphCompose.document().create()) { + SlateOrange.create().compose(session, SlateOrangeFixtures.canonicalCv()); + assertThat(session.layoutSnapshot().totalPages()).isEqualTo(1); + TemplateTestSupport.assertCanonicalSnapshot( + session, "slate_orange_layout", "cv-v2"); + } + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeSmokeTest.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeSmokeTest.java new file mode 100644 index 000000000..17e635b89 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeSmokeTest.java @@ -0,0 +1,277 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.templates.api.DocumentTemplate; +import com.demcha.compose.document.templates.core.identity.Contact; +import com.demcha.compose.document.templates.cv.data.CvDocument; +import com.demcha.compose.document.templates.cv.data.CvEntry; +import com.demcha.compose.document.templates.cv.data.CvIdentity; +import com.demcha.compose.document.templates.cv.data.CvName; +import com.demcha.compose.document.templates.cv.data.CvSkill; +import com.demcha.compose.document.templates.cv.data.EntriesSection; +import com.demcha.compose.document.templates.cv.data.SkillGroup; +import com.demcha.compose.document.templates.cv.data.SkillsSection; +import com.demcha.compose.document.templates.cv.data.Slot; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.interactive.action.PDActionURI; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; +import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink; +import org.apache.pdfbox.text.PDFTextStripper; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Smoke test for {@link SlateOrange} — proves the preset renders a + * {@link CvDocument} end-to-end with its packaged marks, draws the monogram + * from the name and the specialism strip from its berth's body, reports an + * unknown mark as a data error, draws both channels of a rated language, + * refuses a CV taller than its sheet rather than losing a role, and carries + * the channels and the titles as link annotations — which move no pixel and + * no layout node, so neither gate would notice them going missing. + */ +class SlateOrangeSmokeTest { + + private static byte[] render(CvDocument doc) throws Exception { + // The preset owns its page geometry, so the session starts unconfigured. + try (DocumentSession session = GraphCompose.document().create()) { + SlateOrange.create().compose(session, doc); + assertThat(session.roots()).isNotEmpty(); + byte[] pdfBytes = session.toPdfBytes(); + assertThat(pdfBytes).isNotEmpty(); + return pdfBytes; + } + } + + private static String textOf(byte[] pdfBytes) throws Exception { + try (PDDocument document = Loader.loadPDF(pdfBytes)) { + return new PDFTextStripper().getText(document); + } + } + + private static List linkTargets(byte[] pdfBytes) throws Exception { + List targets = new ArrayList<>(); + try (PDDocument document = Loader.loadPDF(pdfBytes)) { + for (PDPage page : document.getPages()) { + for (PDAnnotation annotation : page.getAnnotations()) { + if (annotation instanceof PDAnnotationLink link + && link.getAction() instanceof PDActionURI uri) { + targets.add(uri.getURI()); + } + } + } + } + return targets; + } + + /** The canonical document with one section replaced. */ + private static CvDocument withSection(Slot slot, EntriesSection replacement, + String replacedTitle) { + List placements = new ArrayList<>(); + for (CvDocument.Placement placement : SlateOrangeFixtures.canonicalCv().placements()) { + if (placement.section().title().equals(replacedTitle)) { + placements.add(new CvDocument.Placement(slot, replacement)); + } else { + placements.add(placement); + } + } + return new CvDocument(SlateOrangeFixtures.identity(), placements); + } + + @Test + void exposesStableIdentity() { + DocumentTemplate template = SlateOrange.create(); + assertThat(template.id()).isEqualTo(SlateOrange.ID); + assertThat(template.displayName()).isEqualTo(SlateOrange.DISPLAY_NAME); + } + + @Test + void rendersCanonicalCvWithPackagedMarks() throws Exception { + render(SlateOrangeFixtures.canonicalCv()); + } + + @Test + void canonicalRenderCarriesEveryBlocksText() throws Exception { + String text = textOf(render(SlateOrangeFixtures.canonicalCv())); + assertThat(text) + .contains("DANIEL HARPER") + .contains("VERSATILE PROFESSIONAL") + .contains("Customer Service Excellence") + .contains("Process Improvement") + .contains("Professional Working") + .contains("Adaptable and resourceful professional") + .contains("BrightStart Logistics, Austin, TX") + .contains("Bachelor of Arts in Communications") + .contains("ServSafe Food Handler Certification"); + } + + @Test + void theMonogramAndTheSpecialismStripAreDrawn() throws Exception { + // The monogram comes from the name's own initials, and the strip is + // the specialism berth's body joined by the design's own separator. + String text = textOf(render(SlateOrangeFixtures.canonicalCv())); + assertThat(text.lines().map(String::strip).toList()) + .anyMatch(line -> line.startsWith("DH")); + assertThat(text.replaceAll("(?U)\\s", "")) + .contains("OPERATIONS") + .contains("CUSTOMERSUCCESS") + .contains("COORDINATION") + .doesNotContain("SPECIALISMS"); + } + + @Test + void aLanguageDrawsBothItsRatingAndItsWording() throws Exception { + // The discs come from the level and the words beside them from the + // note; this is the block that wants both channels of a rated skill. + SkillsSection languages = new SkillsSection("LANGUAGES", + List.of(new SkillGroup("LANGUAGES", List.of( + CvSkill.of("Dutch", 0.6, "Conversational"))))); + List placements = new ArrayList<>(); + for (CvDocument.Placement placement : SlateOrangeFixtures.canonicalCv().placements()) { + placements.add(placement.section().title().equals("LANGUAGES") + ? new CvDocument.Placement(Slot.SIDEBAR, languages) + : placement); + } + + String text = textOf(render(new CvDocument(SlateOrangeFixtures.identity(), placements))); + assertThat(text).contains("Dutch").contains("Conversational"); + } + + @Test + void aSkillWithoutANoteLeavesThatColumnEmpty() throws Exception { + SkillsSection languages = new SkillsSection("LANGUAGES", + List.of(new SkillGroup("LANGUAGES", List.of( + new CvSkill("Dutch", OptionalDouble.of(0.6)))))); + List placements = new ArrayList<>(); + for (CvDocument.Placement placement : SlateOrangeFixtures.canonicalCv().placements()) { + placements.add(placement.section().title().equals("LANGUAGES") + ? new CvDocument.Placement(Slot.SIDEBAR, languages) + : placement); + } + + String text = textOf(render(new CvDocument(SlateOrangeFixtures.identity(), placements))); + assertThat(text).contains("Dutch").doesNotContain("Conversational"); + } + + @Test + void contactChannelsAndLinksAreClickable() throws Exception { + // The dial target is derived from the number as the document writes + // it: this one carries no country code, so neither does the target. + List targets = linkTargets(render(SlateOrangeFixtures.canonicalCv())); + assertThat(targets) + .contains("tel:5551234567") + .contains("mailto:daniel.harper@email.com") + .contains("https://www.linkedin.com/in/danielharper"); + } + + @Test + void aLinkShowsItsLabelAndHidesItsAddress() throws Exception { + byte[] pdfBytes = render(SlateOrangeFixtures.canonicalCv()); + assertThat(textOf(pdfBytes)) + .contains("LinkedIn") + .doesNotContain("linkedin.com/in/danielharper"); + assertThat(linkTargets(pdfBytes)).contains("https://www.linkedin.com/in/danielharper"); + } + + @Test + void aRoleAndADegreeBecomeLinksWhenTheirEntryCarriesOne() throws Exception { + List placements = new ArrayList<>(); + for (CvDocument.Placement placement : SlateOrangeFixtures.canonicalCv().placements()) { + placements.add(switch (placement.section().title()) { + case "PROFESSIONAL EXPERIENCE" -> new CvDocument.Placement(Slot.MAIN, + new EntriesSection("PROFESSIONAL EXPERIENCE", List.of( + CvEntry.builder("Operations Coordinator") + .subtitle("BrightStart Logistics, Austin, TX") + .date("Jan 2022") + .link("https://example.test/brightstart") + .body("Coordinate daily operations.") + .build()))); + case "EDUCATION" -> new CvDocument.Placement(Slot.FOOTER, + new EntriesSection("EDUCATION", List.of( + CvEntry.builder("Bachelor of Arts in Communications") + .subtitle("University of Texas at Austin") + .link("https://example.test/utexas") + .build()))); + default -> placement; + }); + } + + List targets = linkTargets( + render(new CvDocument(SlateOrangeFixtures.identity(), placements))); + assertThat(targets) + .contains("https://example.test/brightstart") + .contains("https://example.test/utexas"); + } + + @Test + void anUnknownMarkIsReportedAsADataError() { + EntriesSection wrong = new EntriesSection("CORE COMPETENCIES", List.of( + CvEntry.builder("Telepathy").icon("telescope").build())); + + assertThatThrownBy(() -> render(withSection(Slot.SIDEBAR, wrong, "CORE COMPETENCIES"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("telescope") + .hasMessageContaining("time-management"); + } + + @Test + void anAchievementWithoutAMarkTakesTheTrophy() throws Exception { + // Every achievement carries the same mark in this design, so an entry + // that names none is drawn with it rather than without one. + EntriesSection unmarked = new EntriesSection("SELECTED ACHIEVEMENTS", List.of( + CvEntry.builder("Process Improvement").body("Reduced reporting time.").build())); + + String text = textOf(render(withSection(Slot.SIDEBAR, unmarked, + "SELECTED ACHIEVEMENTS"))); + assertThat(text).contains("Process Improvement").contains("Reduced reporting time."); + } + + @Test + void aDocumentWithNothingButAnIdentityStillRenders() throws Exception { + // Every berth empty: the band, the monogram and the name, and nothing + // in either column. + render(new CvDocument(SlateOrangeFixtures.identity(), List.of())); + } + + @Test + void anIdentityWithoutLinksDrawsTheThreeChannels() throws Exception { + CvIdentity noLinks = new CvIdentity(CvName.of("Ada", "Lovelace"), "Analyst", + new Contact("+44 20 7946 0000", "ada@example.test", "London, UK"), + List.of(), Optional.empty()); + + // A run that breaks at a space carries one annotation per piece, so it + // is the set of targets that is asserted, not the count. + byte[] pdfBytes = render(new CvDocument(noLinks, List.of())); + assertThat(Set.copyOf(linkTargets(pdfBytes))) + .containsExactlyInAnyOrder("mailto:ada@example.test", "tel:+442079460000"); + } + + @Test + void refusesACvTallerThanTheSheet() { + // The body's two columns are one row, and a row is atomic: a CV that + // outgrows the sheet raises rather than losing a role to a silent cap. + List many = new ArrayList<>(); + for (int index = 0; index < 14; index++) { + many.add(CvEntry.builder("Operations Coordinator " + index) + .subtitle("BrightStart Logistics, Austin, TX") + .date("Jan 2022") + .body("Coordinate daily operations and scheduling for a team of 12.") + .build()); + } + + assertThatThrownBy(() -> render(withSection(Slot.MAIN, + new EntriesSection("PROFESSIONAL EXPERIENCE", many), + "PROFESSIONAL EXPERIENCE"))) + .hasMessageContaining("Body"); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeVisualParityTest.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeVisualParityTest.java new file mode 100644 index 000000000..041eb0c5e --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeVisualParityTest.java @@ -0,0 +1,41 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.GraphCompose; +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.testing.visual.PdfVisualRegression; +import org.junit.jupiter.api.Test; + +import java.nio.file.Path; + +/** + * Pixel-diff visual parity gate for {@link SlateOrange} — the canonical + * one-page CV against a checked-in baseline. + * + *

Re-blessing baselines — after a deliberate visual + * change, re-run with {@code -Dgraphcompose.visual.approve=true} and commit + * the updated PNG with the change. Baselines live under + * {@code src/test/resources/visual-baselines/cv-v2-layered/}.

+ */ +class SlateOrangeVisualParityTest { + + private static final Path BASELINE_ROOT = Path.of( + "src", "test", "resources", "visual-baselines", "cv-v2-layered"); + + private static final long PIXEL_DIFF_BUDGET = 50_000L; + private static final int PER_PIXEL_TOLERANCE = 8; + + @Test + void rendersWithinPixelDiffBudget() throws Exception { + byte[] pdfBytes; + try (DocumentSession document = GraphCompose.document().create()) { + SlateOrange.create().compose(document, SlateOrangeFixtures.canonicalCv()); + pdfBytes = document.toPdfBytes(); + } + + PdfVisualRegression.standard() + .baselineRoot(BASELINE_ROOT) + .perPixelTolerance(PER_PIXEL_TOLERANCE) + .mismatchedPixelBudget(PIXEL_DIFF_BUDGET) + .assertMatchesBaseline("slate_orange", pdfBytes); + } +} diff --git a/qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/slate_orange_layout.json b/qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/slate_orange_layout.json new file mode 100644 index 000000000..aea329edd --- /dev/null +++ b/qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/slate_orange_layout.json @@ -0,0 +1,2147 @@ +{ + "formatVersion" : "2.0", + "canvas" : { + "pageWidth" : 595.276, + "pageHeight" : 841.89, + "innerWidth" : 595.276, + "innerHeight" : 841.89, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, + "totalPages" : 1, + "nodes" : [ { + "path" : "SlateOrangeCv[0]", + "entityName" : "SlateOrangeCv", + "entityKind" : "ContainerNode", + "parentPath" : null, + "childIndex" : 0, + "depth" : 1, + "layer" : 1, + "computedX" : 0.0, + "computedY" : 2.07, + "placementX" : 0.0, + "placementY" : 2.07, + "placementWidth" : 595.276, + "placementHeight" : 839.82, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 595.276, + "contentHeight" : 839.82, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]", + "entityName" : "Masthead", + "entityKind" : "RowNode", + "parentPath" : "SlateOrangeCv[0]", + "childIndex" : 0, + "depth" : 2, + "layer" : 2, + "computedX" : 0.0, + "computedY" : 705.29, + "placementX" : 0.0, + "placementY" : 705.29, + "placementWidth" : 595.276, + "placementHeight" : 136.6, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 595.276, + "contentHeight" : 136.6, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Monogram[0]", + "entityName" : "Monogram", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 0.0, + "computedY" : 745.39, + "placementX" : 0.0, + "placementY" : 745.39, + "placementWidth" : 85.8, + "placementHeight" : 96.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 85.8, + "contentHeight" : 96.5, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 35.8, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Monogram[0]/Initials[0]", + "entityName" : "Initials", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Monogram[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 0.0, + "computedY" : 748.79, + "placementX" : 0.0, + "placementY" : 748.79, + "placementWidth" : 85.8, + "placementHeight" : 57.3, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 85.8, + "contentHeight" : 57.3, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 1.7, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Monogram[0]/Align[1]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Monogram[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 0.0, + "computedY" : 745.39, + "placementX" : 0.0, + "placementY" : 745.39, + "placementWidth" : 85.8, + "placementHeight" : 1.7, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 85.8, + "contentHeight" : 1.7, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Monogram[0]/Align[1]/MonogramRule[0]", + "entityName" : "MonogramRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Monogram[0]/Align[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 24.3, + "computedY" : 745.39, + "placementX" : 24.3, + "placementY" : 745.39, + "placementWidth" : 37.2, + "placementHeight" : 1.7, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 37.2, + "contentHeight" : 1.7, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Identity[1]", + "entityName" : "Identity", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 85.8, + "computedY" : 728.135, + "placementX" : 85.8, + "placementY" : 728.135, + "placementWidth" : 268.949, + "placementHeight" : 113.755, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 268.949, + "contentHeight" : 113.755, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 27.4, + "right" : 0.0, + "bottom" : 0.0, + "left" : 22.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Identity[1]/Name[0]", + "entityName" : "Name", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Identity[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 107.8, + "computedY" : 768.077, + "placementX" : 107.8, + "placementY" : 768.077, + "placementWidth" : 236.196, + "placementHeight" : 46.413, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 236.196, + "contentHeight" : 46.413, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 1.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Identity[1]/RoleLine[1]", + "entityName" : "RoleLine", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Identity[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 107.8, + "computedY" : 747.668, + "placementX" : 107.8, + "placementY" : 747.668, + "placementWidth" : 157.064, + "placementHeight" : 18.909, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 157.064, + "contentHeight" : 18.909, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 7.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Identity[1]/Tagline[2]", + "entityName" : "Tagline", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Identity[1]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 107.8, + "computedY" : 728.135, + "placementX" : 107.8, + "placementY" : 728.135, + "placementWidth" : 246.949, + "placementHeight" : 12.033, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 246.949, + "contentHeight" : 12.033, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/MastheadHairline[2]", + "entityName" : "MastheadHairline", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]", + "childIndex" : 2, + "depth" : 3, + "layer" : 3, + "computedX" : 383.7, + "computedY" : 705.29, + "placementX" : 383.7, + "placementY" : 705.29, + "placementWidth" : 1.2, + "placementHeight" : 136.6, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.2, + "contentHeight" : 136.6, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 34.4, + "right" : 0.0, + "bottom" : 23.2, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/MastheadHairline[2]/MastheadHairlineRule[0]", + "entityName" : "MastheadHairlineRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/MastheadHairline[2]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 383.7, + "computedY" : 728.49, + "placementX" : 383.7, + "placementY" : 728.49, + "placementWidth" : 1.2, + "placementHeight" : 79.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.2, + "contentHeight" : 79.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]", + "entityName" : "Contact", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]", + "childIndex" : 3, + "depth" : 3, + "layer" : 3, + "computedX" : 384.9, + "computedY" : 730.27, + "placementX" : 384.9, + "placementY" : 730.27, + "placementWidth" : 169.418, + "placementHeight" : 111.62, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 169.418, + "contentHeight" : 111.62, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 36.8, + "right" : 0.0, + "bottom" : 0.0, + "left" : 21.4 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]/Contact_0_phone[0]", + "entityName" : "Contact_0_phone", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 406.3, + "computedY" : 793.57, + "placementX" : 406.3, + "placementY" : 793.57, + "placementWidth" : 71.659, + "placementHeight" : 11.52, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 71.659, + "contentHeight" : 11.52, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 9.58, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]/Contact_1_email[1]", + "entityName" : "Contact_1_email", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 406.3, + "computedY" : 772.47, + "placementX" : 406.3, + "placementY" : 772.47, + "placementWidth" : 119.15, + "placementHeight" : 11.52, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 119.15, + "contentHeight" : 11.52, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 9.58, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]/Contact_2_linkedin[2]", + "entityName" : "Contact_2_linkedin", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 406.3, + "computedY" : 751.37, + "placementX" : 406.3, + "placementY" : 751.37, + "placementWidth" : 50.635, + "placementHeight" : 11.52, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 50.635, + "contentHeight" : 11.52, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 9.58, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]/Contact_3_location[3]", + "entityName" : "Contact_3_location", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Masthead[0]/Contact[3]", + "childIndex" : 3, + "depth" : 4, + "layer" : 4, + "computedX" : 406.3, + "computedY" : 730.27, + "placementX" : 406.3, + "placementY" : 730.27, + "placementWidth" : 148.018, + "placementHeight" : 11.52, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 148.018, + "contentHeight" : 11.52, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]", + "entityName" : "Body", + "entityKind" : "RowNode", + "parentPath" : "SlateOrangeCv[0]", + "childIndex" : 1, + "depth" : 2, + "layer" : 2, + "computedX" : 0.0, + "computedY" : 2.07, + "placementX" : 0.0, + "placementY" : 2.07, + "placementWidth" : 595.276, + "placementHeight" : 703.22, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 595.276, + "contentHeight" : 703.22, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]", + "entityName" : "Sidebar", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 0.0, + "computedY" : 7.94, + "placementX" : 0.0, + "placementY" : 7.94, + "placementWidth" : 204.177, + "placementHeight" : 697.35, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 204.177, + "contentHeight" : 697.35, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 18.5, + "right" : 22.85, + "bottom" : 22.0, + "left" : 22.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Competencies[0]", + "entityName" : "Competencies", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 22.0, + "computedY" : 437.715, + "placementX" : 22.0, + "placementY" : 437.715, + "placementWidth" : 159.327, + "placementHeight" : 249.075, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 249.075, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Competencies[0]/CompetenciesHeading[0]", + "entityName" : "CompetenciesHeading", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Competencies[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 672.465, + "placementX" : 22.0, + "placementY" : 672.465, + "placementWidth" : 96.538, + "placementHeight" : 14.325, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 96.538, + "contentHeight" : 14.325, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 3.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Competencies[0]/CompetenciesHeadingRule[1]", + "entityName" : "CompetenciesHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Competencies[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 667.965, + "placementX" : 22.0, + "placementY" : 667.965, + "placementWidth" : 159.327, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 1.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Competencies[0]/CompetencyTable[2]", + "entityName" : "CompetencyTable", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Competencies[0]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 437.715, + "placementX" : 22.0, + "placementY" : 437.715, + "placementWidth" : 159.317, + "placementHeight" : 220.75, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.317, + "contentHeight" : 220.75, + "margin" : { + "top" : 9.5, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Achievements[1]", + "entityName" : "Achievements", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 22.0, + "computedY" : 242.11, + "placementX" : 22.0, + "placementY" : 242.11, + "placementWidth" : 159.327, + "placementHeight" : 172.005, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 172.005, + "margin" : { + "top" : 23.6, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Achievements[1]/AchievementsHeading[0]", + "entityName" : "AchievementsHeading", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Achievements[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 399.79, + "placementX" : 22.0, + "placementY" : 399.79, + "placementWidth" : 116.675, + "placementHeight" : 14.325, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 116.675, + "contentHeight" : 14.325, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 3.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Achievements[1]/AchievementsHeadingRule[1]", + "entityName" : "AchievementsHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Achievements[1]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 395.29, + "placementX" : 22.0, + "placementY" : 395.29, + "placementWidth" : 159.327, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 1.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Achievements[1]/AchievementTable[2]", + "entityName" : "AchievementTable", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Achievements[1]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 242.11, + "placementX" : 22.0, + "placementY" : 242.11, + "placementWidth" : 159.317, + "placementHeight" : 143.68, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.317, + "contentHeight" : 143.68, + "margin" : { + "top" : 9.5, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Languages[2]", + "entityName" : "Languages", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 22.0, + "computedY" : 153.125, + "placementX" : 22.0, + "placementY" : 153.125, + "placementWidth" : 159.327, + "placementHeight" : 71.685, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 71.685, + "margin" : { + "top" : 17.3, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Languages[2]/LanguagesHeading[0]", + "entityName" : "LanguagesHeading", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Languages[2]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 210.485, + "placementX" : 22.0, + "placementY" : 210.485, + "placementWidth" : 55.663, + "placementHeight" : 14.325, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 55.663, + "contentHeight" : 14.325, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 3.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Languages[2]/LanguagesHeadingRule[1]", + "entityName" : "LanguagesHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Languages[2]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 205.985, + "placementX" : 22.0, + "placementY" : 205.985, + "placementWidth" : 159.327, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 1.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Languages[2]/LanguageTable[2]", + "entityName" : "LanguageTable", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Languages[2]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 153.125, + "placementX" : 22.0, + "placementY" : 153.125, + "placementWidth" : 159.317, + "placementHeight" : 43.36, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.317, + "contentHeight" : 43.36, + "margin" : { + "top" : 9.5, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Additional[3]", + "entityName" : "Additional", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]", + "childIndex" : 3, + "depth" : 4, + "layer" : 4, + "computedX" : 22.0, + "computedY" : 29.94, + "placementX" : 22.0, + "placementY" : 29.94, + "placementWidth" : 159.327, + "placementHeight" : 99.285, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 99.285, + "margin" : { + "top" : 23.9, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Additional[3]/AdditionalHeading[0]", + "entityName" : "AdditionalHeading", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Additional[3]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 114.9, + "placementX" : 22.0, + "placementY" : 114.9, + "placementWidth" : 126.337, + "placementHeight" : 14.325, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 126.337, + "contentHeight" : 14.325, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 3.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Additional[3]/AdditionalHeadingRule[1]", + "entityName" : "AdditionalHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Additional[3]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 110.4, + "placementX" : 22.0, + "placementY" : 110.4, + "placementWidth" : 159.327, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.327, + "contentHeight" : 1.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Additional[3]/AdditionalTable[2]", + "entityName" : "AdditionalTable", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/Sidebar[0]/Additional[3]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 22.0, + "computedY" : 29.94, + "placementX" : 22.0, + "placementY" : 29.94, + "placementWidth" : 159.317, + "placementHeight" : 70.96, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.317, + "contentHeight" : 70.96, + "margin" : { + "top" : 9.5, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]", + "entityName" : "MainColumn", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 204.177, + "computedY" : 2.07, + "placementX" : 204.177, + "placementY" : 2.07, + "placementWidth" : 391.099, + "placementHeight" : 703.22, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 391.099, + "contentHeight" : 703.22, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 18.5, + "right" : 22.0, + "bottom" : 22.0, + "left" : 22.85 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Profile[0]", + "entityName" : "Profile", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 227.027, + "computedY" : 588.365, + "placementX" : 227.027, + "placementY" : 588.365, + "placementWidth" : 346.249, + "placementHeight" : 98.425, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.249, + "contentHeight" : 98.425, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Profile[0]/ProfileHeading[0]", + "entityName" : "ProfileHeading", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Profile[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 672.465, + "placementX" : 227.027, + "placementY" : 672.465, + "placementWidth" : 109.138, + "placementHeight" : 14.325, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 109.138, + "contentHeight" : 14.325, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 3.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Profile[0]/ProfileHeadingRule[1]", + "entityName" : "ProfileHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Profile[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 667.965, + "placementX" : 227.027, + "placementY" : 667.965, + "placementWidth" : 346.249, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.249, + "contentHeight" : 1.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Profile[0]/ProfileBody[2]", + "entityName" : "ProfileBody", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Profile[0]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 588.365, + "placementX" : 227.027, + "placementY" : 588.365, + "placementWidth" : 333.296, + "placementHeight" : 66.6, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.296, + "contentHeight" : 66.6, + "margin" : { + "top" : 13.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]", + "entityName" : "Experience", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 227.027, + "computedY" : 114.63, + "placementX" : 227.027, + "placementY" : 114.63, + "placementWidth" : 346.249, + "placementHeight" : 450.735, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.249, + "contentHeight" : 450.735, + "margin" : { + "top" : 23.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceHeading[0]", + "entityName" : "ExperienceHeading", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 551.04, + "placementX" : 227.027, + "placementY" : 551.04, + "placementWidth" : 126.563, + "placementHeight" : 14.325, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 126.563, + "contentHeight" : 14.325, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 3.5, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceHeadingRule[1]", + "entityName" : "ExperienceHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 546.54, + "placementX" : 227.027, + "placementY" : 546.54, + "placementWidth" : 346.249, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.249, + "contentHeight" : 1.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]", + "entityName" : "ExperienceEntries", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 114.63, + "placementX" : 227.027, + "placementY" : 114.63, + "placementWidth" : 346.239, + "placementHeight" : 418.91, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.239, + "contentHeight" : 418.91, + "margin" : { + "top" : 13.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]", + "entityName" : "ExperienceEntry_0", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 227.027, + "computedY" : 427.46, + "placementX" : 227.027, + "placementY" : 427.46, + "placementWidth" : 346.239, + "placementHeight" : 106.08, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.239, + "contentHeight" : 106.08, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 18.4, + "left" : 13.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]/RoleLine_0[0]", + "entityName" : "RoleLine_0", + "entityKind" : "LayerStackNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 521.12, + "placementX" : 240.027, + "placementY" : 521.12, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]/RoleLine_0[0]/RoleTable_0[0]", + "entityName" : "RoleTable_0", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]/RoleLine_0[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 240.027, + "computedY" : 521.12, + "placementX" : 240.027, + "placementY" : 521.12, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]/RoleLine_0[0]/Marker_0[1]", + "entityName" : "Marker_0", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]/RoleLine_0[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 224.227, + "computedY" : 526.82, + "placementX" : 224.227, + "placementY" : 526.82, + "placementWidth" : 5.6, + "placementHeight" : 6.72, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 5.6, + "contentHeight" : 6.72, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]/Employer_0[1]", + "entityName" : "Employer_0", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 508.2, + "placementX" : 240.027, + "placementY" : 508.2, + "placementWidth" : 116.025, + "placementHeight" : 10.92, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 116.025, + "contentHeight" : 10.92, + "margin" : { + "top" : 2.0, + "right" : 0.0, + "bottom" : 6.6, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]/Highlights_0[2]", + "entityName" : "Highlights_0", + "entityKind" : "ListNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_0[0]", + "childIndex" : 2, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 445.86, + "placementX" : 240.027, + "placementY" : 445.86, + "placementWidth" : 319.311, + "placementHeight" : 55.74, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 319.311, + "contentHeight" : 55.74, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]", + "entityName" : "ExperienceEntry_1", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]", + "childIndex" : 1, + "depth" : 6, + "layer" : 6, + "computedX" : 227.027, + "computedY" : 321.38, + "placementX" : 227.027, + "placementY" : 321.38, + "placementWidth" : 346.239, + "placementHeight" : 106.08, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.239, + "contentHeight" : 106.08, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 18.4, + "left" : 13.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]/RoleLine_1[0]", + "entityName" : "RoleLine_1", + "entityKind" : "LayerStackNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 415.04, + "placementX" : 240.027, + "placementY" : 415.04, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]/RoleLine_1[0]/RoleTable_1[0]", + "entityName" : "RoleTable_1", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]/RoleLine_1[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 240.027, + "computedY" : 415.04, + "placementX" : 240.027, + "placementY" : 415.04, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]/RoleLine_1[0]/Marker_1[1]", + "entityName" : "Marker_1", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]/RoleLine_1[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 224.227, + "computedY" : 420.74, + "placementX" : 224.227, + "placementY" : 420.74, + "placementWidth" : 5.6, + "placementHeight" : 6.72, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 5.6, + "contentHeight" : 6.72, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]/Employer_1[1]", + "entityName" : "Employer_1", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 402.12, + "placementX" : 240.027, + "placementY" : 402.12, + "placementWidth" : 106.379, + "placementHeight" : 10.92, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 106.379, + "contentHeight" : 10.92, + "margin" : { + "top" : 2.0, + "right" : 0.0, + "bottom" : 6.6, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]/Highlights_1[2]", + "entityName" : "Highlights_1", + "entityKind" : "ListNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_1[1]", + "childIndex" : 2, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 339.78, + "placementX" : 240.027, + "placementY" : 339.78, + "placementWidth" : 320.307, + "placementHeight" : 55.74, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 320.307, + "contentHeight" : 55.74, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]", + "entityName" : "ExperienceEntry_2", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]", + "childIndex" : 2, + "depth" : 6, + "layer" : 6, + "computedX" : 227.027, + "computedY" : 202.31, + "placementX" : 227.027, + "placementY" : 202.31, + "placementWidth" : 346.239, + "placementHeight" : 119.07, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.239, + "contentHeight" : 119.07, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 18.4, + "left" : 13.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]/RoleLine_2[0]", + "entityName" : "RoleLine_2", + "entityKind" : "LayerStackNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 308.96, + "placementX" : 240.027, + "placementY" : 308.96, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]/RoleLine_2[0]/RoleTable_2[0]", + "entityName" : "RoleTable_2", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]/RoleLine_2[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 240.027, + "computedY" : 308.96, + "placementX" : 240.027, + "placementY" : 308.96, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]/RoleLine_2[0]/Marker_2[1]", + "entityName" : "Marker_2", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]/RoleLine_2[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 224.227, + "computedY" : 314.66, + "placementX" : 224.227, + "placementY" : 314.66, + "placementWidth" : 5.6, + "placementHeight" : 6.72, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 5.6, + "contentHeight" : 6.72, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]/Employer_2[1]", + "entityName" : "Employer_2", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 296.04, + "placementX" : 240.027, + "placementY" : 296.04, + "placementWidth" : 100.528, + "placementHeight" : 10.92, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 100.528, + "contentHeight" : 10.92, + "margin" : { + "top" : 2.0, + "right" : 0.0, + "bottom" : 6.6, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]/Highlights_2[2]", + "entityName" : "Highlights_2", + "entityKind" : "ListNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_2[2]", + "childIndex" : 2, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 220.71, + "placementX" : 240.027, + "placementY" : 220.71, + "placementWidth" : 307.972, + "placementHeight" : 68.73, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 307.972, + "contentHeight" : 68.73, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]", + "entityName" : "ExperienceEntry_3", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]", + "childIndex" : 3, + "depth" : 6, + "layer" : 6, + "computedX" : 227.027, + "computedY" : 114.63, + "placementX" : 227.027, + "placementY" : 114.63, + "placementWidth" : 346.239, + "placementHeight" : 87.68, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.239, + "contentHeight" : 87.68, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 13.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]/RoleLine_3[0]", + "entityName" : "RoleLine_3", + "entityKind" : "LayerStackNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 189.89, + "placementX" : 240.027, + "placementY" : 189.89, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]/RoleLine_3[0]/RoleTable_3[0]", + "entityName" : "RoleTable_3", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]/RoleLine_3[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 240.027, + "computedY" : 189.89, + "placementX" : 240.027, + "placementY" : 189.89, + "placementWidth" : 333.239, + "placementHeight" : 12.42, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 333.239, + "contentHeight" : 12.42, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]/RoleLine_3[0]/Marker_3[1]", + "entityName" : "Marker_3", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]/RoleLine_3[0]", + "childIndex" : 1, + "depth" : 8, + "layer" : 8, + "computedX" : 224.227, + "computedY" : 195.59, + "placementX" : 224.227, + "placementY" : 195.59, + "placementWidth" : 5.6, + "placementHeight" : 6.72, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 5.6, + "contentHeight" : 6.72, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]/Employer_3[1]", + "entityName" : "Employer_3", + "entityKind" : "ParagraphNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]", + "childIndex" : 1, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 176.97, + "placementX" : 240.027, + "placementY" : 176.97, + "placementWidth" : 151.251, + "placementHeight" : 10.92, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 151.251, + "contentHeight" : 10.92, + "margin" : { + "top" : 2.0, + "right" : 0.0, + "bottom" : 6.6, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]/Highlights_3[2]", + "entityName" : "Highlights_3", + "entityKind" : "ListNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Experience[1]/ExperienceEntries[2]/ExperienceEntry_3[3]", + "childIndex" : 2, + "depth" : 7, + "layer" : 7, + "computedX" : 240.027, + "computedY" : 114.63, + "placementX" : 240.027, + "placementY" : 114.63, + "placementWidth" : 316.795, + "placementHeight" : 55.74, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 316.795, + "contentHeight" : 55.74, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Credentials[2]", + "entityName" : "Credentials", + "entityKind" : "SectionNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 227.027, + "computedY" : 24.07, + "placementX" : 227.027, + "placementY" : 24.07, + "placementWidth" : 346.249, + "placementHeight" : 78.56, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.249, + "contentHeight" : 78.56, + "margin" : { + "top" : 12.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Credentials[2]/CredentialsRule[0]", + "entityName" : "CredentialsRule", + "entityKind" : "LineNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Credentials[2]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 101.63, + "placementX" : 227.027, + "placementY" : 101.63, + "placementWidth" : 346.249, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.249, + "contentHeight" : 1.0, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Credentials[2]/CredentialTable[1]", + "entityName" : "CredentialTable", + "entityKind" : "TableNode", + "parentPath" : "SlateOrangeCv[0]/Body[1]/MainColumn[1]/Credentials[2]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 227.027, + "computedY" : 24.07, + "placementX" : 227.027, + "placementY" : 24.07, + "placementWidth" : 346.239, + "placementHeight" : 65.46, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 346.239, + "contentHeight" : 65.46, + "margin" : { + "top" : 12.1, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + } ] +} diff --git a/qa/src/test/resources/visual-baselines/cv-v2-layered/slate_orange-page-0.png b/qa/src/test/resources/visual-baselines/cv-v2-layered/slate_orange-page-0.png new file mode 100644 index 0000000000000000000000000000000000000000..1d0c506654ab5d1910b026dbfc13d6df59c75a16 GIT binary patch literal 155530 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 @PgSQ~{h4zIu zLxL@`@6Ue#A3FGQm&Q*YjwPPN1%)V&zl|XB<4Cz~2;kn1tsO6g?AKdO!sY7^b41O>n{eRqZNgx{{^ouN^1C1gL%;tmb;g_56vR)f z$o5x&gP6R|W$|`xIQ`P|9yXQ6X`(ZH&HsyGM8N8FHD?Y&@kD^L<1?V&-fKq^PD9!M z2Z-7QtcO=bEUa=mb!nNm15et}7XkBjFvA3$LvBu(GSyy6Yt?csuI~j3CN>&J4AK)+ zcXUeJY^6Y<$p^w`>z5!K()1}Z0e0%y4$O?;HCaUjP4I%*O+j=2I#B+Pmcp}sy|hy8 zHvH{*_K7J~!wv9VR1uw0SoDldj9hF_f(QQ^1q?QU4)XgkiS|TJ!VgjGuO2t&SZb{{ zFa6HFexTgDPblW6u+~5pLW?o8M6zub)mX%~+3S6=MEQ|f{Ck<|}nKnSQi3)8l; z5)Q=>aKR$w$KBrk<@gygtzg5^)#%xlNKQUHYMW>Za9;b?xM%O>7OY5WNq zjf{{u0jQjdx(samUv=&kjE#--Zvctlp9k%~vGBiSJhuO0aQ-=5;s5nw|JPUg|8b2d zM9rwC-?RB0`sw_j?Z(pW`_bLn|39CsudmN0`5|hi@%N*3phW79&SQ|h<8$=8gRQJL zGs@}fH)pOEwx60t5OJ0RmGAqn50WV{x@3I}>fhhX7q=D_eOP~&Ir|<(vw}UC>F-Z^ z(_c)M4sB`p74n!!Jxhr64W^+lr4VI|w+R!J!^GvNs~?2zxPAh1_I4%z{z?7ytE4-X zADA*0jQA0qu(O2iGc3^AH658$u={CE*h-#oat94tdOu@6)9TC>92&}TChu=N9Xrnk`v9f9hw z<19Y_oN@>}cNeFb38Z&wsn##?3*E|r@;RQbM;4=yH{nk7=5(cW?8maaMXsW9bG;pG z7CL39XLz&l_t7IwsC)9|b|k<thjYkdV{#dW`eWawqCqLCjcQLWkE{3)dnrcU3dc z0|F0n+PkIdO;s+Vp!@QrI6FHX#S2Ac;3;Qfy$07}tgSss1_fg=Ma&T+P5RBCeWr2i z)VV(oOkdAfqZk?3jX#5Tm+lp&{kDfQjYs1iYWyQJUX+5!a62?!!bT+A$Mb#-J%yNmkADPN4ssY6ar zg3{aTNYgck1_!?@cr-OLzS2!qx2M;ltLMd8Evy)nxzNITdzLR@&n}h&GHhO3dV}h| zKTuPnbcKWVEgWpIre93>!aJq+t1qmj1pa%0|LK?dzBK3H4yHabwfCi8pgK#)q0o3L z*c?4Ac>4GcKUu>OK2)kd=vJl?3}O5XY~Aqu{D%F*^pN_y>y1Sz_V<=|Jr1FhqnJvgIJRW8#gZ+rad))1X4hLJpL1a8+#OJlI_JEvDGzzQM?cR>!&I74Qp>c{V0=9=PA_BgZ;~V!H*cZsT|1*_(BvHSPw4kIWb!qoV%QX7 zKYTa!PQ_U^zdi_fudv@|x&j*JGX*ji@~j&Wtb^CXrN_J7v`S6F`5*REI8)$+AaqFm zIeRmW&OQ>#Ma2+<9ww0#d_l>=#lY4FH%hYA4Y`E8FQ_gZF?od~;Y*X34_Y+lrpcGW zm06p5%yC8K@Gj)3mJ`Ci|GDU701izfbP?KE8}U;SQFneC&EB0^U*d?TC2*T5>zz2= z5H}>F?oc*w59+7#2=WKqOSX(YZOY5w_rvNUA@E)cpw&Gi;fW&rj+Rg`Ml%ZZ)p2hf zni1qDNzqunHFUQ=SH^eR^*d+DIVBR_Pky2{!yexs^o;#>iSL$J*#MjAQLFoGfj=?d zo*EKn#Ps_oZbH^j+hK>jL-&c#yk4PRSf3<8$Pm~}j6uvAA@%NxT|^KlMy0&>YSd&w zo?L;!h>WQ_?6}n?9g#D`8c_AG3$syH?S3%Q1<)w+Y+C}-T8Z<}kTaZo9jCG+fkA}v z6-;!xrK%U`xl_Qto7%P>knoWrF&a=FFQu(8Rb^iT2N)L>Y0lRe1eflR zdKc4d*g(RUFjF9@aw6V`TcSM4s=-=y~aMPY7DOhOpiWF|!cRQr#so__ik8eUT%KpKM`4WcCWnj+~K#Nw3phTxy8vWhqGTVN6` z%}lUFLQhD^=L2O!)wp!UeFxyqWyB9u@B2>i(YhL=fee)G(uIG`8ZiaD+>`=NNHL64FcD90N?1ME146xyHjEB%QDh(N@%E1~ zkTG?1r>L2>QM;OgnDejm(;84N<5<{5*Hf@jefGte`90Xn7telYDHgh^!u3{shd{5P zx=Nsp3y-1H>-CP|9=HK{nZr#KsOAvytLUN|@kOxl7`CoILwv;vi=AC#;>cptu^8Cl zAwijCt^V0r3sOx#wORp=*i@-w>Ib%M)+(|Q1wlV@iIAZm?yEYR#!cfEDx;qCRa&%t}BJKAVQhoe)^ za0N;2N`Y2^%$`RbApp_bNWD((p5|r;au)R4L(XtG>W@aXkB95a_TS#B-C%j=6#%}h z(7g;^kSTIAQsTDnJcm25>*gdGj(+kc{~7YTHzZt4DYpzBGJ1Wa2x*^P)TVcJkv9(*FuK{FeZi`ot{=fMKDF8u zr=;d#@B4OTi!hQNe32)bSgg6pI2AbB4`&qf=-0Jz>4HV+LluQu4@}lTn6N!!ihI@g z;7K0g!qd7P{Xue0ecZuB?=6v3%M1){q*B80SMXF~94^b;RN-<@Kr}u!Bw@IFja_u? zva`^VJn?>|I=CQ>)|KZn^8i?`emWctgh;%K&agRtg>PbBZl;n%TP@aO4pmaIaUs-N z)#H)$s}*M%nF7RX{Aa)c+??ev%R9-V0oj)vD4w#N?#T}n^Ka`uY|liy1Qe) z`@(|GbO&kpW6Q85@n@JbUm}j`vQ2!Lo8^j4==R;Sb<9D=hzDw!)=Z6?EVt4Lh8pP> zZmvlo=1y8adYh7$#B$&uZH(=C+?xK#(dEN}Jo@$GUhnRj2j3QG9smm42Mz{XFR^}HEy%=9;)zwSbLsZEv9!a?0m z?a2rf>-+H)nS?w(bh-qkJ`56Gf5IyxHFndlNue?|mV1-1nFOSfAz5!R1*$+48*2lL z&7}pYiXGDsAsNlf++W_n#>R-SKoB7^vuvu@}TML}r z$Rc#K&v+L*x}1?X+XK7{H`4FETwEY8{J=wO`flnpl@@G5UwTil)|8if=JR0M)8n)4 zyp{ghRp_{A9s<+d`8GF9_#Jba+3&_?`#R=>xp>Fe1KyholuasscE>mpb$t{S|-+~TvKE`1apa+v>pns`|vyTRk_{cin_`CHqQ6^pZv8*;GV z>bI6!r!%dd{WnBfZ^h3D|M}3Z{hgXAV^r+HhRhuPq$@$W_IZ9(xCZMzLSp{w5Od9? zk6OR>5t?ecAs|952odZ69h9(=5hC9$hq=BA+cDFs@^WQG)tSIUz?EQ1n6_7j9#%2V z>0D3&wglPYZRuP)e#m6J^U>&0`3FY-ePZ*1llczjm=L!KcLNU4-|6bCuCBXIw|F{CKV*d$wAGeYe!t!T3qyBPMx$RJSbN;Q4-K=@ zqY)5oD^OrQS|1+foNEm-{V>!LI2J1ofnV=A3A}4X0~Z4|?uj0P%8)@`B0yvfLtHEQ zsU(9FT#SZ@WQ6%i}`yvZ#Z zoqutuq!cW*M4&oy|N6Bp5M1-`U+dbiWj(N=4{T4Lh%5@|DqNs8XteGJ%IB3KL);?G zgHOxm?eXzz5Jw$s{K+*NubsKwet(i3ui78eIJ5e2;7j*i=bNjOu+0YY{Z2OgvO&`O zx`UBN1LXKYHq^!eKeU@{n!KkQNIuJ~Czlamb_1w^ThRmiJh)=opT6RVUE$1Ckp!*tZ%T;=g{~==g!;f%XRJ zQwZ3O=8@wQJEpa5*B)QA{ZNQc*kotRBL6FNyeH;@-0*W^WV9MY8iL9pjdp>sLA8G4 z)cH6-gOCdcNS~WBsL$rcpX5cSXXMO+Pzp#!QmwBJGPwXn`S=ZPKZru68Mq+>&d7N& z=+zA(sDpz6^`dEY7j_BgrIx&oNCgI(TIIYnLIT1r#A8yTUBw#UxgIQ4LwS{Y%nlbI zu@AK#U;!K}&~N>mtgYAZCUKO{UBB~Mom!!l%HLV2=e@&DoV?xL7-MyB5L7`ceNTn6 z1TG?Yh=#%VAVBVF_7DAXGv8JkFS>1fCnP&&l+whUx%|H=;V^>UlpP6}%55$h|vQ9DKo^?+P5j=!P*0p!F#T7|JyW z=n=&R-lD1KR-1xWBw#v*$trMx!KOw1j$Py&s#tjX^^6QjlSUFW1p@6*FNHKxglRN` zsKIRp1XGVWyrL-)aF6pmy6Ilh4A%0KO*zjBKH>{>n23YA!$eKB4js>%U1E^d9k#&&jRlB^Z_NheJEzK28{=A zvFBT45@tCBw{8ZHfKdoYCLg~y5fVPf`Zp7UC%ijN)&|lx+uIIab|9T@*7P~j&Oz&N z8Dx7yU8g{&Mk@o~83;#E%UzD0(cW&X6D@sJ#9&vfg3j>b@lFO^I)O;N=$DV?=*;9p z?qa3LZPgWw5?D9^RLaGwr|oRK9HXa=I}0vT;-%Uer#K$r7{R zm|IDC0N6dwu7g?V@^%)pDdPG@y0qn#_itGds1ic(gGy9zk*V) zof;8ih0MdEofpQ}nhaR^CV!0DeTpNb>p!FL|7D^#AKCAT`1PJGR7rnY*})(Y%ghIC zH`Jd^uf^acfnoh#{0DJxHI`ZC{;s-C^z5gP{`KyEI8YT>2*OHvz@FVsIzm9*$1ajn z>4fUR=~P&eR(2w&TFm&pH(|A-m%B@#I~TeEsuZ-osiVs>B@$;G_Gb)!u}XoPD%Oe( zL1FJAY;u8qTZT7jgb{7zhrIUWds)FJbLZ;$kWP_&yxllXK$(~_-i1zDU zktNm-m$M<)FE2)3;u2NNic$m>20RT;C48cmEp^VN3#SMWM%ESyFLYwKDkAtj&_P`2 z>4dKDi%DSeB2q;;xSa4OKeb9NIAw>MN?(@jN6>jwBIUIII)5Ut{3Hb3n6-6;Os3wv zPjx%s)&is?Iir#A5tqi$XRJ)~$9zp1xrl$V#eKOeV}}USam617a$ZJ!M~ndKCuzk? z8Mmjfv0mfkfZ<`*i0DK3lAJ>ZR`njFDVG5?Rt>CH>26@3w%UkDE-gt!jAwYi7GU)o zC`zJCDA**R#dL6oUPJSDIC(8#P{!REy%AB(H^HDh2gMBetL$Vm@JO_&UvSK!-+zH8 zT-h%;%LlAbm7GOjm`NSt;c7MnmYjE9C=zk*7)O+;EL_BjlgGK^)L(Z3jq&g^je#)Y zJzf_mThyI<*;`PfC1~^(nT>;mqZra!(Z#?I*IKj;2;NjWV-P*k`fE%|gu3mr7$K*6 z_{;T)t=Y|EVn>3PNMPkspnE)Mf#&E%wxDx!+uTH*@+{O?1RAPzw4g&G+*OvWGD!1; z??e{mQq{bM_uhT%)#CI6xlmfVipU4lRt$i|_W+V4-ZI=2em|B;C6B# z7r$%#upjUjpJ69!Eh&jsjv)SptIX(19yH_b=bv(WZuf7kv+C=?m<@ZgOs)|IdaZ^4 zHAv~s6=g(!V;sdSex`4+C-3t5xU{vp?5Tf|kNk&E8Mz@eOIF0p-&H%lnjhtQqpR%y z!i}grJf5k0XP&89!AgbvtoW$-L-|t?8|1#@j`ME~Ah}XYDcbAkf3xcBI$ZS62U>d5 z7OA^E(WcHg@=G9;Z2R78th>7i6)fKZfTg?-oCL2y=}>JO&N9FA%7V{!=QlCHlQh`l zvuo7k40tbq6TwSWz26ve*P1+BI%Yhgj+Xg^lH33H4U)9l4JqHJvuz|pGjBQAyXD+q zEcQ0X-22^$c*BjaAx9H4F8N|g{wpa9yE1>yA_1QDJNi{hV%nyhC-5?VZTc+s0xIVX z{hkWY%`uZmQQJSsi@$I%V-TRz(8E=Kd7vG-uLGUsYmoXWxaQ(VGf*3PoO7-K$E~ph z=KBVxaqL$wYwOi@5XJ(I7qvVn6feUS9P1aHCIhT1XEd;v0n%Cyd!H^%bae9tJ>gVl z6sHv1D5fXBz!|mR6_8x+2LJ8>rx2TRU5tg}#~*Lf8Ofmz*3W9hWJt!l6Ibsp%7tJ?STP5RLSB*OoNYpWV(_CZ!* z^^>)K`mTZW&z#6%u50Llz0ah)q zs7S~c&cCJJIIizKer*d@gw7WiJO`kvGP2m8effh&?eGvQ$kVT{K5={P^zPk@?K_0K zl#C?*j`Hot7--Rxzkc~;lguwIoi^t$Oo#;Dd3ZRG3c1d;zIgdkZFENJ6*9{QS`ir?o|=&6mA=_cN=_5+Tf( zOs2aRpYGW>3dHrZGWR9=sK92emX{A(I6lz8lSN$#MAksBshg0d#LUhk^csqy!G$ zuAhh)-P&&oa=}_L7A)Dau;~Kk962myW#ttPV+P)MLjwbOnn<|>{*ylARj&z^4Ig8do>lsz9I-<%6Ler4UvAMC~}O4)c57%&wd zrU!eELfIzXPINEyY!ur1VX-aULu5}%tqQRU;`l(KJ*d|UG{8w?bU;RZOG$c)#48qZ zr!9I->w4gQ`{mjA03Lr+(yNr!C3!8$GYN35^xY8VoXAaw2uXPnbOz8mt|j2$J~8S@ zQbj8@<1rFD?s=PDMZc6O7I;q1*duZ(-reTIzP#R((|TDEOUpz_$w8OnJ6{o}av7*; z{5>)>z;&UB10@0eh>?YUZ?w&J40ti}PXD>+;c1n32)O9M^Wb)EA<)1>O%3n4P;9Ky zF5`Ka@vemw!4o-IP0gBDMPaX}pFEb5!%Z?l%*14lVGh%h#o4&n_4l?WS7vh>Z)(rK z4V`iPUHQzhV=SPwGV)8A3Eyum9*lH4SrrwP3gk)t)h{aR=2zoh9W6-rc=@#{3QppB zBvHe-MI|LAli}L|$M*I@R>T|%F==UOFR_(V)Q49d{`z~7cUfufjN&yZJA1}ud$`xD zlasnr4aP~OV|l(&?SF&=ct*uvT(n(J@_hVL!F+zXwHQ?A*OQj(%v6nvHe+yo_@jjN zqg1s-jjfi)kRyBNpZcfFPfb31z2iOIBd9r8dfu~!5%l~A<2HBCX#I4^8{SQ8=b0J> zn`_6449n6Mhr)G^RL1DKZA?qC$g%B=D&@{=c_bk45+1~aE-?1u{go2r_y}qPdK-vjOqpptH-5dTLncPBW zuhLp&F*K$f^Lkcc+pmp&T2&>{E(vZ??Yuu%Cytvide%_3o_#mo<@_QYS3n(dRFkY- z1*n3S4UA*-L>PY6dlPKEM*H(_>pREa*}q@!;kOa_eb3;mnEQma5MMLh#NK+)iJP&M z{L@fh2nO7_M|lTgS#9c4jP*s^rwTb6oe z{ox_^MIdLyh+!@KzIfm{Mm4jaC-F1gO0v5d$l^Pzi$l%%+ihg0o+s@VpNg=lirZCg z5R|}$0J3<6@-xjav-n?S#jBfCO`$y6T(4jA+j^<*;O2MrO0-`kRckm*PqS#TJkBGN z>r2L>RF|=&TPvgxBud0a4l{-#8$DOaf9A^_=;%P@!M0WyA%Q_DmvxErs}Hj5h5}=z z?0fdf8`-|bU3&u*yS<$INKdCm$bMe%;UyY1Es;U2WhCS>4svE(lg4{|>5f06`Bd%s z$d8m)t6LMLD!R=Zb4y;)`_t@iR5ckCif}VMbr#3n#OOrqRvLuj(zK(7zP@-B3WrvD z2fX5`KrVQ!V>|!h^H>KNar=ej)+Y}VzvbJ+uYs98v(e=BPwnVz({Qq;Ol-ClX}zA{ zSQ{j+5NHsW55nFB^SDK%(=L8GMoWg`T#;qsrQkn*Y)`Aq9J!I|?qLgK3)Io=Upzp< z*l>bER>CG=ANiB|)w739lvS?y*g{}W^-*9?pB`xO2NQ+)N4@hB@^Sw#H-8ymQ&XX% z7T^+0^YK>DYh)$@{U*%HdEm_-ANSq2^VjIEq_T9kVcpru!51q3KCiu=!tRWB#p>;0 z!pCPHmPr9XH0=~7NxS3o!U*XBw++L6U9~1d!Oi!IMX(kt26Y~Aa!%YxC@Yt@1)7Lh zWV~`|7M)13W6>o&99C8v7OE-9+Fa_07QIhkf<|dby_H7oSw7U~O_kfxZ*bO+R-)1N zD{?pRQaFs0B=wJScr3@Qd!0Y6oMew(3^#rJg~f!>3il<+WS<`@M~}kw*;7W+HhyaG|)bHG+3^|NC)k(}t?iYG`{0pULTrVOlJ!6~2Eb^}%HWm=}AIDbK zKN=)BK?aSBcW-EgUPA|K@iM%3@9x4CR2xIa(O`<9nA>tF1HHcQ;bLWmE3xNY44hT6 za68YNvUeNdkMy89exceHaFlUqnx8e`8Xqw~fWKg7xedOe2#J}MmTX4&e z->9{~eYZ0xDLNABD9~MKEqaubwV6?Tidk=TSdfJOab>XSvP?!{i>sEDz>)%f{_XBC zuV9!YxrTm*blU6pb+YR^Eh3VeSV)8j(dyKWn}7C`Bg~YL%uUb9;793-EjFbEwQ9qP z17|)Gty(71%oiLKB%OMyF>hp{!MjcvP=fE<>(ol$EEylU!Ti0w@!tDYuj7S9>~+rX z1LF~@gDvOFbmJvxClE}ljz{wLiOEM)w+g>G)|oRDkP%$p`+x-Ogz%P^y-@aHo=;R{ ztq0Ew#vGeeyQgt3Y5yLiF&l`liK~Pc*t^tFJIPn^S0Y3EDka7B9iBu#YBn^w}J&ziK!~BkHI(AKhue&IT2^~)$R*HBekortoYC}xJJFYmZ0S))$QJcdc ztDfk`O0MhI24u7p;zwp7Q&R>SJ9Zz4)x`{;>~)yJL@fYvZUD)7WZ*l=nbQy zB2Ph13(AvT*IJ@}wPo^>Pme`dm5mx4l_BAR7n9Us9-Bqa=hWNw1+d(HhWzgA5 z&m@?(;iexmN-hQQeL9I)XFK=$oxBuLj~EzgC90r{xszYhX;m_b`DRvO>eM~ z7qvLZS4b{_ayqfS&KCnid&#eOIyjDfd0KVwT-&Jl7Hg(cQ>iSXpv=XNsV<+nw7V1* z)gX-xQ4vAvA+@QTnb&AkCAH`TeaZt79tn%j64Z@^h~=gB?UW((49fMsyf5a{putdF zah<;O-s?uasn>R0m$Tx`QOt!Ngg-5YEwjUeRrs8AzRIas8yU4G#GAWILkPL=rMi@S z|ACK(SSu-2e5XBp2X|r-gd|40s(wUt9&mu)QNm2EZi&l=lB9a|mV4nl7T^ze1(kTX zkf$Z%^(JTJKup8I9wOwCHruDHqBa_YeriE!&wKa_A0^InsW50vUyoNPk9(xr0EXd) ztItbBqVj4ucZtVRn;XIfeP5knt@xucYDK8seo{OhZp)mN*FX_&jvpdvO5}BpV^$)M zwE-CkJgLN%yQ|jK0TXWV*rJV|E|&L;Fz2J2^C;A?*8a|5zN%|^1-Pf)~8GT&wzVsj=tB0tfY?G{nQfb*_h-#^4az1aY zH^uT3-e!2?>SWj0TSiDhMZ^PStENk z7^9&2L0{aGNo`zhMIi>Med$Q61(h zw@&FvCjHi#B4BZNhf#;NHab@L<-tDpcQkn6O^lW0l_SZALn*a9-_$$kg8cSH<}WDP z5PAiV;EKb}mHr*$d5JhbcJYT!nkfhwPn1mZF1}bG=YZ<(zQPU@c32Bd*IoUBdv}!O ziyGDRGxTPgtEpXzy>;G&xYnNZdy4OgUTV7+w1sANZ z7?ox650Jb+&~P0RG$gIRt#^4TPkQY~tQInb6M(XH;br3Qjp2dZIjJ4@F=YL*er#x~ z(#SfWNKcAKhllT&V|WB@pX!Bom(e^jy9651QMC2QN$ji_0X}72z}fyCbn}K0P=q=e zjGEP?R{W}QuOH+yj3eOY<}Rnzo=K<#oxDSW^%fnT z?28-2@#8@fSiW$V0iIlZh1rsq*vdu!V$pK4X-ez4_aqy8GV3RkXZ>ou)?3R8t$AVD z-t{|>xF3@r%0;rg(-0!v-SQqZMz~Ni_g&eVTnDH@{`Hxf%h?X{%!tDOfb~3O&;Ey7 z^LpI;FK|n}9~s>hOX9)?$(d16p{Ga49|-boVq#)P%HuwA53*9NWv#mVjj5$|78r4R zSfwG2A(T~)MDXr--TKZA$ja+P-ZO7Q136E%<=7nzLGQUicH2lYt(c^jpg{g0N-jIl zVKr*<88#^1UeZ=I4$pO%*}OTMAaQ+mSasM+aol3|tPu?_|FE8lJm%gW=TWsod*F3P zE61c0MpE4T_xt|<(G7M4jW`7vK}+MQF0%HN3j+yHO)oH?DMv&J)31E|63KVCh*U-j zJHFZ=&QVsWXz}G`_{o1m2WJYc9J5${L~&L3@c!+CDx*yPBeQSH%9rAPiy4iJFRRkq zEM47}l=0~wKNdpqd!Jr*iX5I-IzQ0ExxQF9)5SR6kkq87={Jra`sXVnOHeN%PIAcM z^M1G>ua+|hv%p^gEK{1L>fO|2J^JB`H5|t!iZ}H;#y)Ajqb*HMmn*qFx>)(V0-_S^ zNRE+a4a=Th6E^ndSe%T+TviAjkLlp+G0Mf?c1;22-$t)LsO}SP&waV%FKny1(BD;# ze->%*^5yO>)zd6@LW%gzy=@nUxb<02I`Wg!e|=?lkxlwLSm|jW)akx|f2qDzCsyim zCFh!7Id(ssHLkG6=Xv;=Yp9K_t?jRO%Mu9NRT9n^!t?_ zy!VuXY(*zpI5I0MYrcZ#v?&QoYgvvgNvr9Ed$4}0#9<9a`&QTMZ(gCN5Vo?};*H#C z_~>@WSk1UI^yi7CwUcO&H!JxlgIzUE2A`^_0R$=GhAnp$D z8LDMi#z`BZ*7#^k!92hq4f(tV(5)NUmCT}+3szaMP?ENz{~BB$@`a4Y?ejiAxUVZe zJT6jMLGuykfp$`~uVCg089+nuXG}NienZMD#0U+e+z{x3=QGVaXPPacMR1ZJ2JH{C zY{y0vkL?P)JbvBFbWzbV*p^R+<#;S#L^^x<)k)Z<-8{ z3I&F(DZFU~-ssxSIh<>Xa!zYX>#GF5Dk2mS-Fm>A2l2f*Y;8ALry<#fYQjs z;}&3zKY@6h6~GoYV4C=ePiRh2vE@7zfSX#|fjDsTJ3|6biNSly4$_vMjJ(Xi3VR`TW5>$-dN%op_YRN)qWO| zqyF+%3Kh#P*n$w%m1{uFa<4FCeSNIl45545)u8o? z9c%w+DRAwqGgO5M3-A3Dps)@MRyfjiFsl$SX{tTmO6N&3UeDDdteTU`A0;lDl4_uN z=uJ*ool!e$UL6tkqeN!&ri~?>evgvg9}|=bh7Azv-?2rYcoV}wC*W7iW~6g0q(kCQK!wy*dE379bZPeGlI`T&gKO@OMypk%Um2kAHZ!<9B z`R_3%7{^+{8!lUR|1*%EpydV|7_MIr%?Io`S+eBVY*7lM!hJ$xp-_cub zs0#*LNQp`C!zl-^zwu){#-nCI^$(F(Wge?~q-9uaMIUO{WbJHRH3gM|P~HuATeydV zlRcgN@j(CmJz?ma(_7ob_=%7b>tnp)Qc+xz@QcCZ&DRL_%b zV6TYw!~3xodNc~lzGk3EAW#x=T#n(E$IlXTWWTrMFlCV;2D74L>XUekf_@_^5@X^-I1`St$J!4=tnq?{~7>GPeanzy?P-~ zP=Y{BFlx&}C#kTu9FBSi%GmM?0IqVO4O-^&RW~quS|RPkc%$zATOp?S5NL)kHUIHL zv%t@5>?cay0{XM+p&!ul_KEJwK&q=aUUf974zkY-XtcBrlx7r{1xw)Pq_#d<@|xn`oQ=9om0aJDFh;qus{toJ3c4(ZUXF_RRWm;%p1)`BoA zKO-HJ9rEf!`WWp;9Cz-RFeu7OX_F+H&koLyjwp|XTdC#drj zyRO5vKiLw}04%QW8OT$lTc)R3Qzy&|e_20hg!??Ua?nKI!ie-0iYuZebtk9*Yno&; z&iLiT4u>tm_Ko46j^>_yjWWHl*___qXypH)xH#+>BG%E@DTFKDya(@oWkxg?MiU?R zWJtke`m|FQ7VY4X&cnc-nJ5~GvnE?409X@ekKHpG+}5Hmx2uHoPr=H^y_>9G@9FPf z8DAYGf=^K!7OtLvUnajE{d;C4V=KD*lQ*f~1$j7mMzNJ;VuQf~*cSo2t^D!6IVy4# zZLLT$D}|cwxcz21!ltBFlcw%F_#)Zv8d0+iqkI*)aG(wjiWB#5;zk}t*$5x0-&Gir zf@Enpwy$+J=1NpjM1?sFMpUW@evCH6bx(-jEA^fzCO$;AUFfWmCOryI7+QX87#L-q zKo6}=9b|xiiUs9>{F6Br<$NuJ2~=IglQ%=hz5O5E1cs^SWaqiPKTpW- z`GHZ`uYSDnZR+Gbbqk9SNqLMpOvqNu{tt~KOef9%fBllMr(@hcUV*iYLzI<7sJwUM>bwW{^ZS|i%s{jmI*)1uw2 z5)tU0I~eS(ZDz1m^bWZG{ThGGsDD2Ie~mPcku_pG-Of*>Yrv1s^DL+VZMsJ=$J@os}n+DExcHD`MHv-4*;gHC>$X0XaDjHXK^Q#H8qrk;*%Sp@wI-izPZj*fqnyf0)es{|=i897zhe!y+fe+j2` zjqea>Q5{&Owj*fa5BeOq3J%B;_6sD6?{2ex#hhA=eaiJMAm2h!h#@RASa-fy)gX$9 z%}w$VClYp9P9kAyd6km33D&d%NNr(9Ym4 z|K=IX{oy&47H|Ee`zyYyK$k? zWvM|nuU|sE>i(QVjZ?Ls;=M~LO;AZKGig{)<06sATgfJZ+Ew14T3U_t3|f^M3XGFe znxceEd`+lZ=U`gp%I?+MQSjAdqD;0Mf-f;*OEN^JnLMBM`l?`%x26W9lO#+*62!N$ zlzdq>cuiw;G1E8Vn)sRM-j?+TNu`APa1y`>TUl;RWcul$V774-Vo|nz@B$(8!D)E+NGo{CzVOgD&Z1Enodha=Rz~k?WHV! zSTL;Mhsc{omUeV`%}T>}o*wokAw^&U4CC{H1Y3g>3e4i2Ci;79h{A`8BvNLQG zm^D9$QRPI*BS?3;wIV+Lwo*MGqN>(d=V5I*RO`M6vo%Bb$kkDM^BgnUFpS;$T{%XWg|;d%A{d zRpT{Zr^02@d2li8NWAnp(V`@zRC4fr3bG*7|L(3r0{=OUh;#w_-QFT)J(w%P3j6tu z?s7Q-e^K(CZdRY~stM12MkBWY~! zWwuA}4{9*AD+>W&!<;hac#y~0g04o{RTNTV0=!eZ& zH-&!&SLQO}yASL~L$VC^1iS4X^LPCuOW55BY|tXz(V(qgffzkjhyNF zUh`UCy+uY$F{$X)Z+c-&tVErlJ@~z6u!&{!fO?i-=sM3^Vq{g9C*~u6y@zsa0||yu zhz{=HW7bN^fr#T^&!Nh$B5YRY*Yip7<{@r78}uvt2+VAp$5$q= zrP!dLXF{(5HPGbqc|aa&y9LzFM73tP+hdOcFfvK#{zCDnE2op3{Z58lA z-%06ZICu+nPER9*zqQOZR%(6%{x+#=19sJ)H2mpZ?6G1xO0e*-%6igUE&+Bu(Macq zkZ<1-_uxM&xuo^&Qxb9+=}4?`WtV!ll1b9x&cevgI4zp!VywBjEM-s&&Kfbfpwwyx^RWdkpfoQ`xIW1rO6-r3)!HF5y zMXkU@`fGD?rX(w}cITw^4#1i0$Ge#4VWwn9m(+I9l6r>D;Jztx4)%!0(8Dj2#dhtF zHXrbV=-0h;FKdw&H^S0*`!Ma9(r}PB$qPDrqC($}&kuylUq`~(aF$Vwl=v<34mbJE z3yu`h($M^w6>J}^c$4oqvt8^q*ix6auuU@3>GV;Wo9U=bHnGYd9Ow+-IGKA&4TFw3 zAnQRc?o6!RQQd9KnLW(D>O2%eq&P>W=Bm!Y zI?ESMcVARh4iXHbRIf5qR)^j?XFb_O%WrS6a}rWUA`2Bb2tUbrls;rG{7vCGEBb&{ z!9a7U`wgqrP;x-w+o-RYduXwI@ne!Ss=Jp0_wYEB&B)6Jhjbs;F2<-dxrb5jmnpZ2 z{yiUm^I0jb@bqN#sGXEaD$5=Fdj4mM))oHyu*vTFk@?><4ih-FS__$9O6MUvn4Xc{U2)g?#cugOj|%68 z!6hJ!H*5{`Y$-54)vKO35g+Tc%GeoS1Ltse}yX5Jb1vrZ(zpzuZGvmcxs+dY^@)yG-zK{zeKw_`9WdeyJci z^1+m6{&@jkW!TggJ#3`MC+?R?QeekoTM4aVK?Z7w{T; zR(C%qOAcTt%-$@J`5~ja_4YV)KuxuWO4w*uYruLW67~ZambF z$Y1Kl0-JwCpD2#O2V=&+AeD?JD^g5zY^^$u2E5;4G^A~MiSd>$*uJ)iR@n9fSF2{C zZyp;@zf4SiP#4t~c~uf`!aBY4HIb;gf5|QQvG|)V6Lgg`r1Xkr(yQhqvYg!aG|?3m z#;*dDKh9h?%U?5F&1b0@6cV|-`aZ%`$?~hK?Li^NmGZd~fF|iz#F|~8K7TiaDZ$E$ zi>;<)o%(sW)yr@O`jJ zh{)G$A;;U@{j()zVbInqy!Ar><60jhjrB!VR?g^dnv79K7Y4KEX9XMm79tOpD$|gI zd~f*I5DUtVzn{vOC_Jon4R1@Vnx~j+tUMqbddxQV96y?&a`A(=k!pUktXx`U*^H5> z?XPHL_q>jL8IG+-NK+tmW@3qy+JGA3*_0l}COTeGQhaWAuhH|~DBb`o9@y+>t+I6&2kr57KmbKB2so%j;8mEHvP%z$u>&y%K-v zCI>p5mAvk>mWG9dpMb|MZIFyD25Y7Yl^n;ueMw zTchphi`ijU<1lc|-tDh*h^CrqTO9MbS8AVXE>YWgAg&>~jI+>hl<7x1)}Mu(2C=iI zppT5S00Z|0n#OHJ;?6Ce{4EuX5pMk7qPu=#&vGMW9JH|X$b`$hV?2T~lXoCO^@Fjq!lhX4s(j~o=n8vo zRF*4d$g>COKTDiFfrDH17_&!$r^PlwG`7wLN%@JFqI`i^&iWw}qgHd6|6PFBhk7!I z^L$(ya-r#!C6CBi?iY zWuX5` z9S0@3QW~O3bo*J)S5LIJKglB#O|Ou3lo;`givKD5ld${xpU@E+Xqp#bm0R4Sq~Rj! zV8ZHjrC0U4Z=pql;h&L=Ma*pp_zN7g&b+E^c&NBG*TH0ZX$N`|9fsyCKhsJC^I<;M z85IRkN(#SQKJS#QbXg?SRf_6F31d}uU~2G%^)twx2t@otHog#!O#9(G->%oqUyL@}$Z-ix5*L;QA*klO{CwC|oVdgkMY z4^EAczitwi53;md@><0#rE4(5k)X~r&uF2)E7A0IpHN$CF(oaHbhU{8!5jTDAjq35 z4V8Q+maN%X_7g>-UjTQv|P#Y2A1e#mbxZ3*7NrU+i^>Xs(R`QD8!o!LJ?N! zcd@PeChT*Qsey5&;o}0QQn%kfqWe9a-q_dCDIgKpuy7v0@H`ZPcpkl;4bx$#linVwiJRFP# z%x#VHii(!{6qB&XYfA+RnMl^2J9IW{3U^t32-m!^p5I4QI~d@+|JFI5q+a5>>1pdc|r;Qp4h_k{nZ+L?A8^9~4^=@lI$2Rb;smVNWC)C$n!y|9*~=Xa%20ojZ00u%Y(;6Vi#JtmFde6CcOxT zp0-AbrjBD!?pT-($z8}tSxHg!Z)y<#oYv3snhPu|$mn!iqBrOy zA2)a2LSLv{whpQBtg-=P6lQ(;!rI*~x*1{j*N)6~PQ zyb_$Yw+Elc=7;1$CG?}IGIU9LhAp+F&`iK5=)a-*p3qp}DI;AW!5ht{_tk{HUF=$D z9gc5bKE%0cEb}}Q+eqR60SytJl!JuxBZhd8yMFkV{JX<&6q&iUds4B_CQJEg7C}wN5T1#pjPk3LJ~bAV}o%)U;k+ zCFGI$UO#T05(!gV5lYD4{g&*q(}rfG-!^-8x1pc?J!*9x9y zpG0K){D@=P#+;nqFr^!#_)En^HfCwp-d0%o!;M_>119 zPQvV)s&ORzHsHB%8uuSB#KAX#UDfAveR*=d)V;8Q5Az0GzI6+oZoWdeOd{`(B8@Wm z>Xu&D`;4w$PwX+ZwjB3W_0C%1in~-z?aZllU_mI#C*SnE81{oSZ3CCXyCu~^SywYY zdA-C!kw{b5`Nduop{EOazr%-Ul<-(zCl%a&Eqs@4yVT9ZG!&vr?9^8?Ag_3#zzBBZ z1hr8IuT(Mep^7Tw3}8n3x4Eek8>uaeu1m_@+kxcw+_k+XEoB;;1Ur)9c$v21U2+2a z%Zxd6l)cHm7}C1o*?{lIt}=YVo@$$EONmXKNO{bT&x0eEUu2^=iEt|A|8^!zlXPWQ zQY%X=LF$aD|B;I=tf43U3JMF&Bi1=MNff~=Zt#;O!j2+marS3_9}|L1y-y_&CY0Fx z;2IVl?`5)8Bnbb;O1)tMR+JJ%q5iZD;Ok}&d{cwvktsGD0aHwU;+(#ZC?vMsm?z)> zUMJd$c5Ib8($az>*Zg=jh4gnv>tp=5|!=_X#me z`@)Vj%P+u5=PqAK{f{7I1iazZsprm{EseMqCA-QnJ73#y=-hf=>MiB%XtX% ztUfvXI^rQzLtmyks5CSP;3cN;BcGY1_*DG8`u~sMq)nDkDJ1db^vLlyQpR7TaqQ&x zbVu3aaQ!rY7@Ha>|2YN!V{S`NtYo}-ap1Gk@5KqunVcTA$@tHH=eE9x;#aR~#!6=2EBO8r9)?k^GDv_LK0* zffFP@CR%UJz~N7T=&w%}z;C?%h#xv8gIKD8f7nVz=ZDUI{SPe|;>Ub=QW^r; z%Mu%AWniahIz14z@!LKF5JLP@**$Ml^~Cs&y~S%lTHr2Ki-Jvoz~huORlA!xG#mpLCz|1zHe%4x1_OWb#@Oi)NK7LeH9VQpED?suiFNRhC8+`$6fLZV~8egC?%_ogR*G|^TxR3Ea zH+j*;mm?fWkVln5bZbx!iFCwgd03;uHNu&v~&^9Ab7SjLv`p}$~6 zpxFeWeL&T}4y7QRbGdoL%uLjAbYI|+7jOH7coj&py#p2aM&drzupW5IL{tFDfWb#p zGTxk(wwwmlh=@ZEvyY8|v;gtYaG$vgh|E4kYqvHwe5 zwVR3o8xhp92T4ht@Z`-+;6j~oz!vp8Yq2%MwSz#lG2oO`baYQ$rBTe7sfWf!$uJ(V zR<0VZpRhhr+?RHZvX?0RXhcY!NZfxzE%9{P0TKpBe4q&1s%B zY4kBzqW{;?RBSt!1|Xi}@W%6-W*OB#^xaMfQ@-x`Kh^Oc69U!t^6wp>yCWYzemo#2 z=jo`djN==d1bh8c-ySeYt~Xs)V!o42Fu!$`>&6o@;5D6|y|_4S>;Z2fl#H09tO#&7 zl_kaLX^mTE-q#K6JPbci=T2NNa)&-$6e*XNQ~%yu-zYn)e^T3IcwR==psu^#+aFI? z_C-reD?2lp6(9&-Isk|(8?@g1RO0A29v?`P93x~1C7NAaOiDA}lu;+`Rgmb;fw42jU2nG~d)m**!FFQK@7K zZt;AEX_ZW@kj76S)n?b4`FFovmIPJjKeX=car*e544DJucK{9kehV4b?}9_g0;>%; z5hk3EBH(84W!>%R3~$wQa-6#M{X>6g@7WCYougWYml8Ly6)^Yki33>b*n4~Z#R)@l z^j+-21toCy)J4V?vi``in%H3^S$;eXT1gDez)g8+pU_<&qDz7Qf8D>nEG1g zX7|t!kl>$CC>j#FfY9R}nI9gT+VKU8EHKhu;Okrsw_z{qSkALyiQk*nLsd4&EaT}p zR#iSMkBg@c2j-JLie3li0U|@o?dLat5_k{Xe_szbwEKOV@#=L-_8>4}fvk9K0Lgmr z%tYc4CqC#{{`MlP5|MLPk^2-!1Uj-LaBsSC#rFoV$DP^Tb^B4ws8K{~y!inbjoplA ze?aWxa@M=-_k3^9C!OZiyo!JA{4EK*xd%WZiVD@TS}#jgXG0q|5_+v`)^&uoanyVB z`i}-~H)LOiVWCc-dIr*Rp#-0){O?eKnn#8(bEa@PpMakf1@;64EXtRB=ol=l9q*9{ zSRy5A2Qifc%Ah+~?KxoGwI>Wjh$huBS(Vpukj`{iivdS(Q77o$VWuQK$p!&Nn3wt# zLtPluJBPqZUy^TNZ^`THwxU27)IB4(z#K@QMdSD(F1!nFJkpm&So`~P$6740~wJiDCx&s)FKg-}cCY2us0$%x37_T&5F*_-@d1QBCCMxP43t)C;3}O21 zs@1cAH=HA)b#VaWhM(jeM!SXoihu%di0Ne~Zb(wxz?Pr|#8Lc%`T(o-NsyqLG$)FT zocAdCBeSNFlBqQ4#~Fd8r9K~4?Dkj!fX4y>_YUkam}auY6~5!A$Aub=ej>h8QUWMBp(6d+l$5%~eT_xJN2 z3s36YEZyn_#_GwBu-pVCrH4Q@`Bp)#AXLw9Mhy;r43!r}4q(>D$8FKmITy>FN)G7x zl;t?%Vf3XaJrthy5%|~Joo}7j*Yqh%_po|!kHPEpgn*lm{>;!Hx6ec##G_q1>KPNk zRWGJNN#|?jHs@X12UzAj)q;0Bv%{bne2gs!CDOG(GN?8oXZqvKRr+iVGGbzTKS1`hUnP%)RCPc;l#r<8KPUE#CPs&KcY@@c zTU?E&W_Xl0L@gDaFM2K(3k;KPFEuJz3sD$N?uErKWWp<2xqSif>@M8Q~R=ahnq9 zw@32(a1dwSYBqNO505-A3)7pfFb0&udSHGJwL!GT{;Rr^6Q7q;R#GHQ2u~{bQy&rdMRXtnwup?1@gt z>S+M7W_V=-4eSOT-Rruhab42pjdXeWc%A%Sa`Lm+!-E^iX^Ci==JEOHxO?lUYh-G9 z8%)V~P5Jg&hr>Y2ecW1xl0ZtLeaN2)kY zu4zFVK*r_|6Iaj5rcfh9f_8ox9{$rUoiCv&$tRaUA??&WOQuh~2>*JO@pju4b$#Sp z^eW>*nIb2YcWuw8o;{|5WjAu{B`lZ+V-vrJw!gnv4*udzyIw82n!##{sI+Qw7VPYfG0Wj{ZA_VPiyRLv}vSl@7s| zg%Y_?W511=I5;~({Nu;AWN&_9Z^hom!ZAMsx{QCNPaYw6hGQmX#ld*GRc>PN=268{ zrrz0esAj%!f=c%-N07lG>|eir7nxTJDIaY07hq(zm^&@V?Zk&w*48~9=9%fttwoOO z-T7&Vh*Igz9XkC?EyNFV+uhk=RmtzK0}@Heuldp1)6XFO16;bibn|WCD{(<@{rb}_ z5;(C z?JY0IL!;ZD?Y{s#eJGLWxvXl|&%EL9zZpLWhA<}0kqJBCsH-);lIW>f*415ju4QZ| z#2x22x5g7VKzkq1`j>VFmjD?=#OHd-K2OGYil?EuW+^;ut-s)0{AU41*fuzR!a(s{ zuZg|INc;EyVxr~oJ+{2eEhJrxgNKiM&x+^V(O>)O!q`e`TgiG44^G#xR@W+xzd9io9d!ekSc}x!~ zK-i%-KacSS%a^VXhRWwSFJ@*hW&zktO8OWR3I$s^&a)u+4PNFWD_%5n(TjMyWpGT;z5LfW9SAMx*YU#ksu;#Iq@QIf662}k*g&R8x0l_k z?q|R-oTDbaE77ubm6e-x7|~hioGqz$6I+mIynGQ2Tr`YlG$~Ul6JNH~0VTDa(JeGvI+417ZT$~M1n`WC1GpkjvI=f z0p(IzZfg{HGLM5mC1Pb}aaydyxyj5;QYWZ|dN@1!n*l#8$PxX?AQ=}Hl?(`*ce&?C zpM>SJUfOPxo3Ar_6HyeHV=|5SrCOyPq#5C>t7Bl6aX`aE{0Q|QMZ&f{KVu7 z?We@xECIbpL*O~?=>uLTKYwx+Y6!>zZIGm1G@L~j2iX7XKQ%|ZzgE4uU$2}eBqRyh zYKue52hDb-yI)O)SjZCj+>G{dS7C4%h*{0Etbmme7IAq!E1DlW2kyTY1r)};X$SL{ zEyA^W9q2Z|7`Zwz*kt0`02g_aHV$@Gz;LkVuuC5T)X8*wM!yK`wSmrhmhRtMuS8NT zUHHyW+a9ufZh5Jrb;Vb?T7Q+xQd|!|&e_~dGqWgpEGVeRlhR)!rtHCc63_h?YHE`8 z;wZbg|5QelL;`;PI|^qyGAer-cTY}{!X)?6Q~ElOh-7fhE45eB88&{w5{CRFFV^ps$sdV+_@r_ zzu}4kdxlLM3a?Ub3I4)>y7K1k&0l#hRL`c>={cGd}II>@T2!<(s#HJ(%bUR+|J#}5jeI+2s{R3<^0WRn;`z2&igJX#2jeMB;#*591Xt^`hDE0w1qcrGXmE~3lk63Hnu84Lp7Ws zU3{dS)|H@kw8{4bNbZ;G0y&ZDMLJ(jut9y{>ni=|H?SNx!t03pVZ^sn^OH;#NMt2L zf-Z1DRFFw)lG0cN|D;Mxx~=5Oi!(W|o$u>?bNjb+eNX(`7x(ey|0lvWSfvvkTAis>n+hD2K)$s*UmW!Uo22j z#36{PZq?4zP5|cigdkZp%RZ3eO>z|R>{Wqm$>9+FP~ZY;GCY`IIcc$u4*1juT=VnR zHC(AFkx^*vX?Y|73!|b)z>W7fav@$=@6e(evgt`*s(XXdmcjL+w;EL!gdvbVqZ#V! zFm5iw2wUWiXg{h+^(Hv0TDG^s5c65rL#V{P4sX6%3fw1^61}mpE zT;)UuH(7c`Q`^e%o8P&sWJO{!_AbZ0>w8n%(!=-!b>-pziGl2OA%;esLOVB{z$zpE zaIqivr8^?+c@5e&ms@u-A^zkh?^xhe5P!;&%`5l_Tjg|EHnIX5obTuR2InaKVfVov2T4gu zRb4LPOjWl>j3C5Fj`cz@U1g&WVgxCS9#*3V>S%}en?V8rUtu+?qr3>70$63j(gAr( zr3Nl~@-s=YRScB1yZuR~U_}xJQbgA{1suQn%qjD@+=BAbkGMF_a#jR^_^Jy@pT+P8MDEBZ z2)$PTi4ry-G%^NWgRt>ptn*K7+tKN-!Z8aYlE%?JZg9KTEyoQ zbZd7W1RNuDa;6;f7G?fxYL-9(A2Y772Kky?1YN0 z7$FC}-?X^}&w!(%lbuU9)v}TRR%fS|aZy>vAv6u_f~rSb?1%0^$y;s>emTT=?)%)A zUyj;XzI%DdEKG|U^d+P@c{m(<661aUoj>6+KtSslG*-48zWuiT7~4ssRqCwwk3Vy@ z%gIi?`f~5v#I*%I;2ExNpwV?uhISS4DOv4tH$yGfXj+;!{~QclXXEi zI~C^1Mkm;+4;KrQ-?bUuwv4$>52uxW#2RTheUy4|yC}_O7MU5N3d(#I322YF9RP=| z#EN>227S9R9a8V`U`aRjd3Q%6Vb4g=dqs;8w|Mooo8jc$%ABZf4IpalC=AjzfGkGb z`?K^ws$ba~)!pZP(ZKt1w^s4E)5rY;vJMLRwg1f}0khwi`i9PGs(-qY|5qG8 zOoee4)Adlbrs=9!KMlNS2#p|h>mTw-NjYsfe07=B2U_-+Y}3~$m=pbM7Dp8m2FzRk zw8>;oFeVQHiC zwmK~U2IEAer7&6MeFRK^b%jM--!9v41YA7ce<|x^;pA)RHSg;!P!kX#kETPL+h#c- zQ^2sKA^=P={5ILg4tF#nP$b+H5NjYOB~kNuJ+`~(ih;OAPj{-v-3sEvy82@z1D9S( zeTCS!2AqJ@0am_4aobWm$uib0^ z;7$);s+P~q%n%lMj8IfvHvE4eq-4A#4lo4xeBJD6K;~aOnXUhv(RelhFr8DkgDp-z z6%i{C+1DCg`XO=*1RkdFH=eKe0MRIL0c92@*CgXDsBHJ@XN%^E05`fg{L4{%cwHez z`vnyr<=N>%lQj-&9T?HTb25U#e03zQgu5RN#i$K-;$eL!6Lj-!k~(e-)yE_S3NXg* zLuu%@o2kTM^e&9}_}CuJQ1>^&lu?nz%xOd5_SP(u$iV>htMQ>Dt3BxMt#nE0_)Dqa z%$y8ag@+KT(ye?_RQ?*9i&O8zjkEX7j_xl5^s5i8CPu*E@w*vCfjReup<0*Gq2?UJ z)m`p8dNC3vh8w+IBL7h;j0w#T0FbMgw-4p*kTD(=ylO_g3AW?<@l8qf%W`awfr;z} zSdZxJfnQ`SDBLoYk9Ch^b><+p3K&%YscbB4Y_`NAqW_GU4;-k7SR?x{)YKV5J~+y! z0WcEtv32TI+Cik$9u1mj8;i0jvo@2KiYH&AG4bjtK`-~OYb0f0688pxox<95RFdm6 zY3mtL3bO7WhJ>mpBr;_FZ__Q$z!9P11y-LZWjud5Io_j|E9Osooju=2-)gG)`#ReP zo9IVOC0`Bto+t{Z8Urs2v9kI|^wV&KG<5C;2YEA$Z89C)zY}@g7#~Jxq_I^&(q^pX zG0;j5^KC_?o#6dJLxOl8SnER|$U(rB&?9=_qwV(Og$LQ!s;5(<6I~%j%41)Hqmq6{ zL%dFvM~>b$vg;^Q9MQv!4I^(+pCj4HWZQ=u>L|r7jaUl4tGkIryA+~&##^IME=bP) z)vO8`gTZuoK5s4}OZQE_5+JI}_Q_GqGF{Cp1viVT{I8T>n8*v)*r_YY65{fy=?Y>@6b zjmXYlBdfJfsEu_a5mO%*D2ErG;$iGdA7{ca3mM}>0098O6nToP@s6BJ1*GMP0(^%u zBb84>?yLaNVil$W0(g6U7jK{aZ(Rb)j*dVIVG{S}%l~)}UovhZ95)x(=Ow;rOa%(s zV@dq6uc3IWT&?X!p6|dkfd5N!jqH*9@w=WO8W(Oqtv)U7ylEFE)A{?8D_M0ek2E&3 z?{^ucNxT2ZO~OYR1qAG@`fJSsfe>}z)l4R(rNFsk7Q{3!)CAcX(_cwE>}-9WX*}`` zue&^iN)Ga_t4nkP`-LkhMLVWcWucpitazaXPg>rG$>6Yyjoj4=G5!6{f z?#!D|_S{?d7_z5>ps?9Jp+p%C)i^8Gh60XRJ+2PPx2%vtuR0gVhn(n(Tb*9C@$!O!*jdW11koaoJW71MtftG@!V5K7=WTKrGW4okq~N;&9A0Sq$SrtF6^1u`A&t= zErNPx{WLWv8IN)#K;=n%rh=O96xo_FZ~XgBt46G1)k-l&Q|p(s49~-g)kUK3$ zFA&*z;HmLZa;*jQe_>E!%sMi5YwKMtA$$_z20_q~-wCOx6d42jDJ@q>-20(842ml# z=?h3M45)J?@m#dWR|%76A?wM=Ky*IK=XU=Hnk?9E@uO!Tnc<&=|LA*ODZVHB&3k`& zd1Uw9CH_RNeqzxAo|W+#re`v}wDbi2H3om8$>dHyFuvJ-@_c*AJied7fKiFjCyLL3 zg*b%*VUcA)8l=%$;9IRCz*Q->5;Roa78nI1DcP5&TS6>LZe<+0#LfqDkxMmN?Y{BT zb56Z)wp>N1Vxnb;8s6YQGN@ODEj?;8pHf!J0~J(fha5&=ep+_BQr8NO?YG0Jqj(e% z_g_e(o%qDTwgP!i`afHjl=z1qSFVzrZM@mE<+n=xGgim)(nXQ~I#0b-^MIqQV{FM- zRCBF_UQnLZrypT>a01v6uYufb*Ud+BFDR`w_Z zCTrorZls~uEq-E`_65xg!jWQkO&)@RG=^p;POmV6uM~1+I*cTUm#@~q!w>B zADaN2CX90)sXnEpLv2e-4 zsnw%SYnpzVI=Ahg7`L`are?`ooAN^1Yodib|1u5=V0)7r!>?=pfyfUHhw(Qz99$h- zpGMfhNgZn9glEU;oBsd^sFomAL)AZ!S@9QAU+2B2hJm2r`UdntAVdZfZbZW2Arpzl zh_P3V4q&bpvA+-Uoa_h*ioERk_TFd|#u&oRKbAT-4EmbFPeF$LCyS_p{L)!@>|IMFTN`OpLld z=jZz5?Z#M$RKmXg*(uZCMMqP2{B<}i#6d|I|5!7>Fm)fs*Wk8Q?D1=0%-&9TP#dh! zQfbRr1yNralYB2*&ImBIQcaP$2DJh6KIWXs?^gUc+=y`Tr1$ObRIHJwj>`mNLJY+F zK+d!f5BINSDt6`p3-gj)%s|b@*s=VPz)>IG$3*S zmC;9QkTBbn|044x%k&<0?knw*#vVfv#ZZuW#xGHv1QI{`qo362daC+8gS!#uW%s%h zcg*?N>P-!T=<$Y5g4}Wkf*?@&*VW4k1^s2|*Gq*#4uPEcN2V?UeAp46nxP?G`6}1h z=_VbYJz<#h_>;eXPCn0WlN=^bHtj?(;+MC*oBr96+@YC`_*w%xV2vR!iL~o` zh;5n9fF@I+vv4tC*@T|a0akdU^WetiKesZPh^vHAfeIKge>Pb&ZGL)lpARS-XTPaI zCwde#o+tYtZNd*jGlU3R-0CcirsFD%dQllg^f;Hsk7j5_19T1yWmX_*SY5$U4J2-a z;M%C?mk{NN2f6B7HN7yRYnKFyJYSkvTE4OJ=|^odeaDdG0*zeYSKF?r^?6`LHo`Wp_&q{<~E8GV~JEvBDx+bvLi7MiY{f96Go_g-!H;PmF zqUiRIt!uld`VoAcoGaVp_d&O3e_nsAe~D-0jMXHwQ0En5AK^7oplWVn&enSVMXU$x zJhCOXsB%~)rxg~O04owy@K1=qsoTQ3xaB8 zB*F#KE+fmL4R)$F;r*Ia1rkPy%%@vh=&Uqoq;wOx&%=M?&$CM!{tfrj`pt`IQ(iha z|07ItfxN_OmV@(a!xkH#ZTdrFNME6bv}X5Si3d}l9NQ*`?eSw|V(2cr{lF5A3x`~8 zIireMgwH1e<*Sh2`yTyvpR#HIjVk95GB^Edc7|U|(d$?`x50yCiAy*Qd#~Zn24z^` zSEyN($PV8VL`dx=!(3c^!ZQ1dqE8e8HTOK7E6)e{zu-t{_dsRl&(j&?)!{6Q`ia+G zRflB_ZdNVUSadV5>J(ipV~V|oOt_9$@i4y`w8sA!rY;mXOzhV3juUcG{Fqs;%|uh0 zav>KoaUTqC)hy6|>uBZ7|6^(*+jHt~!-eO#nl)w48%O+{56X6qj>U);QrGX{h2FfM zZ436Zxm|=LoLVl zz7?xc$Y5l)(8XTSkv`?-gJW>jc7kcs;Dr>3Q~P;5c2J4 zr7H?WpZa;Uj(G{Vdpsp=N#ls&e6hG;NlT^PEy=cemwM4CP7ng^+&X;5e9CFv;X2`O zK;{ryU`F}O@l1yaiN-JZgipwMTP_EM!aUZ@Sg)vH-1_HiOR~#w=ZU1R9eV+P2_h&Pf0R6Xr4E~ zZP~&r5c2O(vZt5E)tA>Dg?mppu}5uX{<6DFQRPreM!d13@*__od6GTfawo&0N32QK zxs11}$FIK~mY3hA9HlCAeldqPe_}kbD%Zlhc0beG5RrPU7@NQ1+N_I_c_0nNo_?N0TTP+FVl#=zj_8R>XrBqUIu8LG(il3PW*C-IY3+Z>yDcPY zh#=*UO30UC(A0&vSVTUyi2bF(c!yu(E}8MVlU` zeTy0`(>pz8eaZG=0s&KA(_sus{2{0|xL^uHxdJ6`d8nR;k{EY@<4Xmd&3Qx?9_+=) z$B$LzWTO<5(6mY?=``f?9wT;^CelMhZI7X>aD=Yni0hCXIZNUvZx|ZWi;j8LW(z>Y zT&*jU`eJzBP}b%+y;Tr5Dedo4=h#!)(sZ}tFXfzN9p6{haONfaw4_wLnT&?(?LJ39 zZC9X;Wsy$M}|RMXlk3-~jjR@k)e~i#=F=A3=SFB6iswL^Uo#X7Y>y znWog?636={Kq~yj0PVi`xVPtQZ1K}R-fNZJ1kP;nzvkaLcgt>cqNvVHeMP-+;a+Fv zL#ttKRxW04?oq#VmWs=^V@!Omdrra2&fx3sTI1CAs@LTw#6#>ZYQ;-%XnM|zi-^NE zjHmx{g&`T=gg~mL%)UmvO8==r(?c>AVW|A-GY#q=S8*fiVG2hi+>VW8oj^S+mq4ey z);H}(9w@b*pRPu$A9Zo$HcRyGzto(G*AA!SOWQWB_(lzE3ZuW;EA8%zJ2Hoz&DoLr z!cFfhrH&IU(+XBQ0z5bCOpx>F`=NUVY|lLa_weMs$uvCIpsg&Nl0|GC;8vpsnayz}&lq{DWns+yQ*IlXilrUMNW z-#nW&j^^}j28E38S&92l$8L^I6T;zt>7*jtUcDhyHtM3?G0K2V;88DvnmZ^&f?|EU zhbg^+Gf`gEu06ZBxRs?*m-4Sp=e?X#LB=A_Nt zT{6hl2c6i_SxG)P?AW}*pj^fLcQV|eo4wn?MuRBs(e8XQDOiH??`+%@w^jNqwMdm; z9U7$!jJ$nH1bJnqi17o8M=KFNV=vhL$a7y_by3OBX(*-?F3}D4=$aDy~$YRBA_H9`uAUX;H=zpiCa{7c!eq^Q8nB0gI&8{{#fFEX`&RY5EL-_`LFacj zm*p#H$skKowt(^EN$0?r?=?F1!_ANLU51^ok3fQAF2cJ8(l}lxa_D@@BaUmWhW*}e zuCjV#w9}#a25fVp{Eh?Pxs6Jq)v>f=CVflr>&36VPHqwhAN~K-O7_=f;_~Bo5;RS` z2v|uT&cc3^(Bue4gF7l$wRM6imE%^3~t0OKB&IkR;zEi7(b67+q{zYL}4X_ zde!_z)7P@Jw44QyxUPOc9}U@2dZbpfSI?}F_47uh|PS*jSXMZ-sASR-dRpt|l># zl!t)#Sv-7e>*;lY^p(w&5Bn<{=hY@B{lP!?muQe*;6~!DNck6oQ+8-|yMyekL^Kyza{r0ZXL@dI2PxNxP&mgZlY;@*%w{kfTCDja;G3 z3Vr8i$=QFk;5|}=%(zvx(6WXv2Zi{kZOH_fit|71zkW$o6mO;{YeGgF!8q=%Y_fr# z9i+{r8)Fn%;r~z1NvV*S7i(PW1YsoU7v?i|JRV*W%uFB=4C zSLgZnIpDqgfz+4ETC62H93gk z868BiqIUdxFBPOh1O^`O-m<;iE-~v#kDGa=ku7S9?viT$XQE4&*JJMb!jo!SLB#F` z>?RHzg8pl`5cK%9vJ);M6oVx$1l(u81VknNHjC;pO^Uhd{+e&p&VelHwg7v*7Ut4i z6OZlL1D&G9HuR{xaJpVK+q2vg+Ck=O`D5RppFTmQ|HbyK+1TKD&eB@$txzjnwU-ye zK|YNRoVFL7uxZ=~L^dmP2Cqf&!yZ}BWhLS=>j>VR%I41|!lxV=(=)YVR-YZ?>_Bc> zjI;Zx@9Ng>y=@h7oIbW|>kw8d9_*R~qvAU?g+UF- zsGqNvX$2639+=`jeoy>b(;uDLuu8yll_$2!ZC~8HGP*lynG*BhDN%QhOctlg z_;+V}P0^drR5+Av{_n;m#s55JsAj+KFX{T~GwM?fO`~Rs&*6x^GUUnso>Fb1!(4bF z;(-v~3y!K^{F+#~1caIHq-AzNNW^$In)SuCp?D z8(WTF-FY}l)hxz=_FggZe=BFrPp$RX)XkM$t@7zR+GYC6I6tPv1 zmWd;=HYBEIsrw&<#q{2x665R-i%km%L5yy zFhv8Xl|xqKUgJ9&lzSg<*_gaC8CkI=)JDD0QTeSRhHCW4V^d@?f1<{lDfcGr>O$gxG~&#-rvP|@mxEo$vAbkxnI%#mXJFElN%4gAlszZc#Gw+Y`gE@3M>O7FZv+@ zy%X-UxT?2RwFU+1L3!ew^Sd8iM=qj?Ur@=LfBUHLD0nX0RhFW1u+XyasS)CY!Vp$UW5XG{*9#+yfU5^lMO3oI*s%p&i*iZ)(8$}+9{^CeTr z%aRs(nSXMLm|AIm{^d=4>#mS1#G%t69<5}K`@ATWzjBL($8#R3DRuumgQr=EAzC_s4 zE}8VcE%~TKsBI*Jo(H^PBL8>H-nm39LD%XH3dhh!$WGkb;I}|slBwI}*R9wz*Fa_a zCdW}vFw=_~brI%?nl~&vLYT6sMpL(-bBn%n>Fs>4(i-7B)t^63`SZ*(C43lSclFJSTAzN!H{zNosID9OYBA%+!?7j*2OIK39ag0A_&$UXWe&@I z-bwzj(I=~;<8F(J_dXb2ibH>4yr&z_F86=f{o+&r4O8_)b_%>Fcp!L zXlM5Cuf#08?~33|<*nPi82=;u=T~;pUkU#Q>KzEgtwx*6sb|lw>%}C&6K7$vE+*&A&aK2NM>%DFcI8wM z5@O6n@7Yr-QIaQFDWT5|tY7YrkS=vm3FoQb;@NMlukIvF3=!f9@YpG)JNZQSjPh90 z#|qR#P#rD#dxHFo#)DqtTM~4{T1)txxa@sAoslkt987~HrXrbUJ`oOfw1?wAy6CEw zyB>K+ixMS6pYLxDyl;?1Pqd{-ov?3CW$jVJH#*2IY>NYXDL^lo_Zu9=$%ntn_!N|h z{}`50LZ*C;1W3-7o1DmS3KawKS)iNqdDvt$$INg1O(S>dl&*+H4KHzhB~X+VcXD-{j{MQuN>(coD;A zvvC_9a_q?dP~L(bGahn6tU)MRSdW>~v;RN+z{#UBib)skl@JdC_)?aC`Jz_NEcE{X Do7!>n literal 0 HcmV?d00001 diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrange.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrange.java new file mode 100644 index 000000000..0eba71d02 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrange.java @@ -0,0 +1,245 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.templates.api.DocumentTemplate; +import com.demcha.compose.document.templates.cv.components.SectionLookup; +import com.demcha.compose.document.templates.cv.data.CvDocument; +import com.demcha.compose.document.templates.cv.data.CvSection; +import com.demcha.compose.document.templates.cv.data.EntriesSection; +import com.demcha.compose.document.templates.cv.data.ParagraphSection; +import com.demcha.compose.document.templates.cv.data.SkillsSection; + +import java.util.List; +import java.util.Objects; + +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MAIN_CELL_WEIGHT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PAGE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.SIDEBAR_CELL_WEIGHT; + +/** + * Slate Orange — a one-page CV built as a full-bleed slate band over a + * two-column body: an orange monogram tile beside the name, the role line and + * the specialism strip, with the contact lines across an orange hairline; + * then a narrow column of marked competencies, trophy-marked achievements, + * rated languages and closing facts, beside a wide column carrying the + * profile, the roles held on a rail, and a credentials footer. + * + *

Why the fills are page backgrounds

+ * + *

The slate band, the orange tile, the hairline between the two body + * columns and the fainter one between the credential columns are page + * backgrounds rather than section fills or line nodes. A fill on a section is + * bounded by its content and would stop short of the paper edge; a page + * background takes its geometry from the canvas and reaches all four edges + * however much content happens to sit on it.

+ * + *

Why every horizontal pair inside a column is a table

+ * + *

A row cannot nest inside a row cell, and both body columns are cells of + * the body row — so every pair inside one that a row would otherwise carry is + * a table with fixed column widths: mark and label, language and rating, role + * and dates, the two credential columns. Where a column needs several stacked + * lines inside one cell, that cell holds a single-column table of its own, + * because a cell holds one node.

+ * + *

The experience rail is the left border of each entry rather than a + * drawn line, so it stretches to whatever height the entry turns out to have + * instead of being a length computed against today's text.

+ * + *

One page, and what happens past it

+ * + *

The experience block is held together, and the body's two columns are a + * single row — a row is atomic, so a CV taller than the sheet raises + * {@code AtomicNodeTooLargeException}, naming the node and the height it + * needed. The preset draws no cap of its own, because a CV that quietly loses + * a role is worse than one that refuses to compose. {@link TimelineMinimal} + * is the preset in this package that splits its own columns across pages.

+ * + *

How a document reaches its berth

+ * + *

The bands are fixed, so the preset assigns each section a berth by title + * rather than reading {@link + * com.demcha.compose.document.templates.cv.data.Slot}. It has seven:

+ * + *
    + *
  • the specialisms, a {@link ParagraphSection} of one specialism per + * line, drawn as the strip under the role. Only its body is drawn: the + * title is how the document names the berth;
  • + *
  • competencies, achievements and the closing facts, + * {@link EntriesSection}s, and languages, a {@link SkillsSection} — the + * narrow column;
  • + *
  • the profile, a {@link ParagraphSection}, and experience, an + * {@link EntriesSection} whose bodies are one highlight per line — the + * wide column;
  • + *
  • education and certifications, {@link EntriesSection}s — the + * credentials footer.
  • + *
+ * + *

A section whose title matches no berth is not drawn, and a berth with no + * section takes its heading and rule with it.

+ * + *

The marks, the ratings and the links

+ * + *

A competency, an achievement and a closing fact each take the mark its + * entry names in {@code CvEntry.icon()}, from this preset's own vocabulary, + * and an unknown token is reported as a data error naming the set. An entry + * with no token is drawn without a mark — except an achievement, which falls + * back to the trophy the design gives them all.

+ * + *

A language draws both channels of its skill: the discs from + * {@code CvSkill.level()} and the words beside them from + * {@code CvSkill.note()}. A skill with no level draws no discs, and one with + * no note leaves that column empty rather than inventing a wording.

+ * + *

The phone, the email and each link are reachable from the PDF, with the + * {@code tel:} and {@code mailto:} targets built from the values — so a + * number written without a country code gets a national dial target, which is + * what the document said. A link is + * drawn as its own label with the address behind it, so the contact column's + * width does not depend on how long a profile happens to be called. A role + * and a degree become links when their entry carries + * {@code CvEntry.link()}.

+ * + *

Fonts

+ * + *

The sheet is set in Fira Sans Condensed, with Asap Condensed for the + * name and the headings. The templates artifact carries neither — register + * them on the session, or the engine substitutes and the measured geometry + * here no longer matches the type sitting in it. Both faces are condensed on + * purpose: the design's measure is narrow enough that a normal-width face + * turns single-line bullets into two.

+ * + *

Usage:

+ *
{@code
+ * DocumentTemplate template = SlateOrange.create();
+ * template.compose(session, cv);
+ * }
+ * + * @since 2.2.3 + */ +public final class SlateOrange { + + /** Stable identifier of this preset. */ + public static final String ID = "slate-orange"; + + /** Human-readable name of this preset. */ + public static final String DISPLAY_NAME = "Slate Orange"; + + private static final List SPECIALISM_KEYS = + List.of("specialisms", "specialities", "specialties", "focus"); + private static final List COMPETENCY_KEYS = + List.of("competencies", "competency", "skills", "expertise"); + private static final List ACHIEVEMENT_KEYS = + List.of("achievements", "achievement", "awards", "highlights"); + private static final List LANGUAGE_KEYS = + List.of("languages", "language"); + private static final List FACT_KEYS = + List.of("additional", "details", "other"); + private static final List PROFILE_KEYS = + List.of("profile", "summary", "about"); + private static final List EXPERIENCE_KEYS = + List.of("experience", "employment", "work history", "career"); + private static final List EDUCATION_KEYS = + List.of("education", "qualifications"); + private static final List CERTIFICATION_KEYS = + List.of("certifications", "certification", "training", "licences", "licenses"); + + private SlateOrange() { + } + + /** + * Creates the template. + * + * @return a template composing a {@link CvDocument} + */ + public static DocumentTemplate create() { + return new Template(); + } + + private record Template() implements DocumentTemplate { + + @Override + public String id() { + return ID; + } + + @Override + public String displayName() { + return DISPLAY_NAME; + } + + @Override + public void compose(DocumentSession document, CvDocument doc) { + Objects.requireNonNull(document, "document"); + Objects.requireNonNull(doc, "doc"); + List sections = doc.sections(); + + // The specialisms are claimed before the profile: their own keys + // are narrow, but the profile's are broad enough to take a strip + // titled loosely. + ParagraphSection specialisms = + berth(sections, ParagraphSection.class, SPECIALISM_KEYS); + ParagraphSection profile = + berthExcept(sections, ParagraphSection.class, PROFILE_KEYS, specialisms); + EntriesSection competencies = + berth(sections, EntriesSection.class, COMPETENCY_KEYS); + EntriesSection achievements = + berthExcept(sections, EntriesSection.class, ACHIEVEMENT_KEYS, competencies); + SkillsSection languages = berth(sections, SkillsSection.class, LANGUAGE_KEYS); + EntriesSection facts = berth(sections, EntriesSection.class, FACT_KEYS); + EntriesSection experience = berth(sections, EntriesSection.class, EXPERIENCE_KEYS); + EntriesSection education = berth(sections, EntriesSection.class, EDUCATION_KEYS); + EntriesSection certifications = + berth(sections, EntriesSection.class, CERTIFICATION_KEYS); + + // The sheet is a fixed composition drawn to the paper edge, so the + // preset sets the page and takes the margin off: every column pads + // itself, and a session margin would move the fills off the fills. + document.pageSize(PAGE).margin(DocumentInsets.zero()); + SlateOrangeMasthead.renderChrome(document); + + document.pageFlow(page -> { + page.name("SlateOrangeCv"); + page.spacing(0); + SlateOrangeMasthead.render(page, doc.identity(), specialisms); + page.addRow("Body", row -> { + row.spacing(0); + row.weights(SIDEBAR_CELL_WEIGHT, MAIN_CELL_WEIGHT); + row.addSection("Sidebar", side -> SlateOrangeAside.compose(side, + competencies, achievements, languages, facts)); + row.addSection("MainColumn", main -> SlateOrangeMain.compose(main, + profile, experience, education, certifications)); + }); + }); + } + + /** + * The first section of the wanted shape whose title names this berth, + * or {@code null} when the document fills no such berth. + */ + private static T berth(List sections, + Class type, + List keys) { + return berthExcept(sections, type, keys, null); + } + + /** The same, skipping a section another berth has already claimed. */ + private static T berthExcept(List sections, + Class type, + List keys, + CvSection taken) { + for (CvSection section : sections) { + if (!type.isInstance(section) || section == taken) { + continue; + } + for (String key : keys) { + if (SectionLookup.titleContains(section.title(), key)) { + return type.cast(section); + } + } + } + return null; + } + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeAside.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeAside.java new file mode 100644 index 000000000..22606cb8e --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeAside.java @@ -0,0 +1,267 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.dsl.ParagraphBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.node.DocumentNode; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentTextStyle; +import com.demcha.compose.document.table.DocumentTableCell; +import com.demcha.compose.document.table.DocumentTableColumn; +import com.demcha.compose.document.table.DocumentTableTextAnchor; +import com.demcha.compose.document.templates.cv.data.CvEntry; +import com.demcha.compose.document.templates.cv.data.CvSkill; +import com.demcha.compose.document.templates.cv.data.EntriesSection; +import com.demcha.compose.document.templates.cv.data.SkillGroup; +import com.demcha.compose.document.templates.cv.data.SkillsSection; + +import java.util.ArrayList; +import java.util.List; + +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACHIEVEMENT_BODY_LEADING; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACHIEVEMENT_BODY_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACHIEVEMENT_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACHIEVEMENT_TITLE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACHIEVEMENTS_TOP_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ADDITIONAL_ICON_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ADDITIONAL_PITCH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ADDITIONAL_TOP_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_TOP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.COMPETENCY_PITCH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HALF_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ICON_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.INK; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LANGUAGE_LEVEL_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LANGUAGE_NAME_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LANGUAGE_PITCH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LANGUAGE_RATING_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LANGUAGE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LANGUAGES_TOP_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LEVEL_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LINE_FACTOR; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MUTED; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PAGE_MARGIN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RATING_DOT_DIAMETER; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RATING_EMPTY; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_TO_SIDEBAR_BODY; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.SIDEBAR_TABLE_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.cellStyle; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.gap; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.leading; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.style; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.heading; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.iconCell; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.iconTable; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.spacer; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.text; + +/** + * The narrow column: the marked competencies, the achievements, the rated + * languages and the closing facts. + */ +final class SlateOrangeAside { + + /** The mark every achievement takes when its entry names none. */ + private static final String DEFAULT_ACHIEVEMENT_MARK = SlateOrangeIcons.ACHIEVEMENT; + + /** How many discs a rating is drawn out of. */ + private static final int RATING_SCALE = 5; + + private SlateOrangeAside() { + } + + static void compose(SectionBuilder side, EntriesSection competencies, + EntriesSection achievements, SkillsSection languages, + EntriesSection facts) { + side.spacing(0); + side.padding((float) BODY_TOP, (float) HALF_GAP, (float) PAGE_MARGIN, + (float) PAGE_MARGIN); + if (hasEntries(competencies)) { + renderCompetencies(side, competencies); + } + if (hasEntries(achievements)) { + renderAchievements(side, achievements); + } + if (hasSkills(languages)) { + renderLanguages(side, languages); + } + if (hasEntries(facts)) { + renderFacts(side, facts); + } + } + + /** The competencies — one mark-and-label row each, on a fixed mark column. */ + private static void renderCompetencies(SectionBuilder side, EntriesSection section) { + side.addSection("Competencies", block -> { + block.spacing(0); + heading(block, "Competencies", section.title()); + iconTable(block, "CompetencyTable", "Competency", section.entries(), + COMPETENCY_PITCH, ICON_COLUMN); + }); + } + + /** The closing facts — the same mark column at a wider row pitch. */ + private static void renderFacts(SectionBuilder side, EntriesSection section) { + side.addSection("Additional", block -> { + block.spacing(0); + block.margin((float) ADDITIONAL_TOP_GAP, 0f, 0f, 0f); + heading(block, "Additional", section.title()); + iconTable(block, "AdditionalTable", "Additional", section.entries(), + ADDITIONAL_PITCH, ADDITIONAL_ICON_COLUMN); + }); + } + + // -- achievements ------------------------------------------------------ + + /** + * The achievements — a trophy in its own column beside a bold title over + * its body. + * + *

Two table rows per achievement rather than one: the title and the + * body are separate lines that must both start at the label column, and a + * cell holds one node. The body's row leaves the mark column empty, which + * is what makes the body hang on the title's left edge rather than wrap + * back under the trophy.

+ */ + private static void renderAchievements(SectionBuilder side, EntriesSection section) { + side.addSection("Achievements", block -> { + block.spacing(0); + block.margin((float) ACHIEVEMENTS_TOP_GAP, 0f, 0f, 0f); + heading(block, "Achievements", section.title()); + List entries = section.entries(); + block.addTable(table -> { + table.name("AchievementTable"); + table.margin(new DocumentInsets(RULE_TO_SIDEBAR_BODY, 0, 0, 0)); + table.width(SIDEBAR_TABLE_WIDTH); + table.columns( + DocumentTableColumn.fixed(ICON_COLUMN), + DocumentTableColumn.fixed(SIDEBAR_TABLE_WIDTH - ICON_COLUMN)); + table.defaultCellStyle(cellStyle(DocumentInsets.zero(), + DocumentTableTextAnchor.TOP_LEFT)); + for (int index = 0; index < entries.size(); index++) { + CvEntry entry = entries.get(index); + boolean last = index == entries.size() - 1; + String mark = entry.icon().isBlank() + ? DEFAULT_ACHIEVEMENT_MARK + : entry.icon(); + table.rowCells( + DocumentTableCell.node(iconCell("AchievementIcon_" + index, mark, + ACHIEVEMENT_TITLE_SIZE)), + DocumentTableCell.node(text("AchievementTitle_" + index, + entry.title(), + style(BODY_FONT, ACHIEVEMENT_TITLE_SIZE, INK, true)))); + table.rowCells( + DocumentTableCell.node(spacer("AchievementGutter_" + index)), + DocumentTableCell.node(new ParagraphBuilder() + .name("AchievementBody_" + index) + .text(entry.body()) + .lineSpacing(leading(ACHIEVEMENT_BODY_LEADING, + ACHIEVEMENT_BODY_SIZE)) + .textStyle(style(BODY_FONT, ACHIEVEMENT_BODY_SIZE, INK, false)) + .build())); + if (!last) { + // The gap belongs to the row, not to the paragraph in + // it: a margin on a node inside a table cell is the + // cell's business, and the cell ignores it. + table.rowStyle(2 * index + 1, cellStyle( + new DocumentInsets(0, 0, ACHIEVEMENT_GAP, 0), + DocumentTableTextAnchor.TOP_LEFT)); + } + } + }); + }); + } + + // -- languages --------------------------------------------------------- + + /** + * The languages — the name, the level as the document words it, and the + * rating as five discs, on one line. + * + *

This is the block that wants both channels of a rated skill: the + * discs come from {@code CvSkill.level()} and the words beside them from + * {@code CvSkill.note()}. A skill with no level draws no discs, and one + * with no note leaves that column empty rather than inventing a + * wording.

+ */ + private static void renderLanguages(SectionBuilder side, SkillsSection languages) { + List entries = new ArrayList<>(); + for (SkillGroup group : languages.groups()) { + entries.addAll(group.entries()); + } + side.addSection("Languages", block -> { + block.spacing(0); + block.margin((float) LANGUAGES_TOP_GAP, 0f, 0f, 0f); + heading(block, "Languages", languages.title()); + block.addTable(table -> { + table.name("LanguageTable"); + table.margin(new DocumentInsets(RULE_TO_SIDEBAR_BODY, 0, 0, 0)); + table.width(SIDEBAR_TABLE_WIDTH); + table.columns( + DocumentTableColumn.fixed(LANGUAGE_NAME_COLUMN), + DocumentTableColumn.fixed(LANGUAGE_LEVEL_COLUMN), + DocumentTableColumn.fixed(LANGUAGE_RATING_COLUMN)); + table.defaultCellStyle(cellStyle( + new DocumentInsets(0, 0, + gap(LANGUAGE_PITCH, LANGUAGE_SIZE * LINE_FACTOR), 0), + DocumentTableTextAnchor.CENTER_LEFT)); + for (int index = 0; index < entries.size(); index++) { + CvSkill skill = entries.get(index); + table.rowCells( + DocumentTableCell.node(text("LanguageName_" + index, skill.name(), + style(BODY_FONT, LANGUAGE_SIZE, INK, false))), + DocumentTableCell.node(skill.note().isBlank() + ? spacer("LanguageLevel_" + index) + : text("LanguageLevel_" + index, skill.note(), + style(BODY_FONT, LEVEL_SIZE, MUTED, false))), + DocumentTableCell.node(rating("LanguageRating_" + index, skill))); + } + table.rowStyle(entries.size() - 1, + cellStyle(DocumentInsets.zero(), DocumentTableTextAnchor.CENTER_LEFT)); + }); + }); + } + + /** + * One language's rating, as inline shape runs rather than a bullet glyph, + * so it cannot fall victim to whatever a fallback font does or does not + * ship. + * + *

The paragraph is styled although it carries no words: a paragraph + * takes its line box from its type whether or not a glyph uses it, and the + * default box would set the whole row's pitch.

+ */ + private static DocumentNode rating(String name, CvSkill skill) { + ParagraphBuilder paragraph = new ParagraphBuilder(); + paragraph.name(name); + paragraph.lineSpacing(0); + DocumentTextStyle gapStyle = style(BODY_FONT, LANGUAGE_SIZE, INK, false); + paragraph.textStyle(gapStyle); + if (skill.level().isEmpty()) { + return paragraph.build(); + } + int filled = (int) Math.round(skill.level().getAsDouble() * RATING_SCALE); + for (int disc = 0; disc < RATING_SCALE; disc++) { + paragraph.dot(RATING_DOT_DIAMETER, disc < filled ? ACCENT : RATING_EMPTY); + if (disc < RATING_SCALE - 1) { + // Two spaces, not one: the design sets the discs nearly twice + // their own diameter apart, and one space at this size is half + // of that. + paragraph.inlineText(" ", gapStyle); + } + } + return paragraph.build(); + } + + // -- presence ---------------------------------------------------------- + + private static boolean hasEntries(EntriesSection section) { + return section != null && !section.entries().isEmpty(); + } + + private static boolean hasSkills(SkillsSection section) { + return section != null + && section.groups().stream().anyMatch(group -> !group.entries().isEmpty()); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeIcons.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeIcons.java new file mode 100644 index 000000000..373a39701 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeIcons.java @@ -0,0 +1,114 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.svg.SvgIcon; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Classpath loader for the Slate Orange CV marks: the four contact glyphs, + * the ten competency marks, the trophy the achievements share, and the three + * marks the closing block draws. + * + *

They ship inside the templates artifact under + * {@code templates/cv/slate-orange/icons/} as SVG, so they scale with the box + * they are drawn into rather than being resampled. Parsed icons are cached + * per token, so a sheet that repeats a mark reads each file once per JVM.

+ * + *

{@link #ENTRY_TOKENS} is the vocabulary a document names through + * {@code CvEntry.icon()}. It is scoped to this preset — another preset + * packages its own set — and an entry with no token is drawn without a mark. + * Each mark carries the width it is drawn at: an icon's box is not its glyph, + * and the sizes are per-glyph rather than one shared number.

+ */ +final class SlateOrangeIcons { + + static final String PHONE = "phone"; + static final String EMAIL = "email"; + static final String LINKEDIN = "linkedin"; + static final String LOCATION = "location"; + static final String ACHIEVEMENT = "achievement"; + + private static final String ICON_ROOT = "/templates/cv/slate-orange/icons/"; + + /** The width each mark is drawn at, as the asset resolver chose it. */ + private static final Map SIZES = Map.ofEntries( + Map.entry(PHONE, 10.2), + Map.entry(EMAIL, 10.2), + Map.entry(LINKEDIN, 10.2), + Map.entry(LOCATION, 10.2), + Map.entry("customer-service", 12.4), + Map.entry("operations", 12.4), + Map.entry("calendar", 12.4), + Map.entry("reporting", 12.4), + Map.entry("communication", 12.4), + Map.entry("problem-solving", 12.4), + Map.entry("sales", 12.4), + Map.entry("office-suite", 12.4), + Map.entry("crm", 12.4), + Map.entry("time-management", 12.4), + Map.entry(ACHIEVEMENT, 13.0), + Map.entry("availability", 11.8), + Map.entry("relocation", 11.8), + Map.entry("remote-work", 11.8)); + + /** The marks a document may name on a competency or a closing fact. */ + static final Set ENTRY_TOKENS = Set.of( + "customer-service", "operations", "calendar", "reporting", "communication", + "problem-solving", "sales", "office-suite", "crm", "time-management", + ACHIEVEMENT, "availability", "relocation", "remote-work"); + + private static final Map CACHE = new ConcurrentHashMap<>(); + + private SlateOrangeIcons() { + } + + /** + * The width one mark is drawn at. + * + * @param token one of the packaged tokens + * @return the drawn width in points + * @throws IllegalArgumentException when the token names no packaged mark, + * listing the ones a document may choose — an icon token is data, + * so a wrong one is a data error + */ + static double size(String token) { + Double size = SIZES.get(token); + if (size == null) { + throw new IllegalArgumentException( + "Unknown slate orange CV icon token '" + token + + "'. This preset packages " + ENTRY_TOKENS.stream().sorted().toList() + + " for an entry mark."); + } + return size; + } + + /** + * Reads one mark. + * + * @param token one of the packaged tokens + * @return the parsed icon + */ + static SvgIcon icon(String token) { + size(token); + return CACHE.computeIfAbsent(token, SlateOrangeIcons::read); + } + + private static SvgIcon read(String token) { + String resourcePath = ICON_ROOT + token + ".svg"; + try (InputStream input = SlateOrangeIcons.class.getResourceAsStream(resourcePath)) { + if (input == null) { + throw new IllegalStateException("Missing slate orange CV icon: " + resourcePath); + } + return SvgIcon.parse(new String(input.readAllBytes(), StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new UncheckedIOException( + "Failed to read slate orange CV icon: " + resourcePath, e); + } + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMain.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMain.java new file mode 100644 index 000000000..e0754e7e6 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMain.java @@ -0,0 +1,398 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.dsl.ListBuilder; +import com.demcha.compose.document.dsl.ParagraphBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.dsl.TableBuilder; +import com.demcha.compose.document.node.DocumentLinkOptions; +import com.demcha.compose.document.node.DocumentNode; +import com.demcha.compose.document.node.LayerAlign; +import com.demcha.compose.document.node.ListMarker; +import com.demcha.compose.document.node.TextAlign; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.table.DocumentTableCell; +import com.demcha.compose.document.table.DocumentTableColumn; +import com.demcha.compose.document.table.DocumentTableStyle; +import com.demcha.compose.document.table.DocumentTableTextAnchor; +import com.demcha.compose.document.templates.cv.data.CvEntry; +import com.demcha.compose.document.templates.cv.data.EntriesSection; +import com.demcha.compose.document.templates.cv.data.ParagraphSection; + +import java.util.ArrayList; +import java.util.List; + +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_TOP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_GUTTER; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_HEADING_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_HEADING_TO_RULE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_LEFT_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_LINE_PITCH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_RIGHT_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_RULE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_RULE_TO_BODY; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_TABLE_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.DEGREE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.DISPLAY_FONT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.EDUCATION_LINE_PITCH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.EDUCATION_LINE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.EMPLOYER_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.EMPLOYER_TO_HIGHLIGHTS; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ENTRY_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ENTRY_INDENT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ENTRY_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.EXPERIENCE_TO_RULE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HALF_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HIGHLIGHT_LEADING; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HIGHLIGHT_PITCH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HIGHLIGHT_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.INK; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LINE_FACTOR; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MARKER_DIAMETER; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.NO_BORDER; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PAGE_MARGIN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PERIOD_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PERIOD_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PROFILE_LEADING; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PROFILE_TO_EXPERIENCE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ROLE_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ROLE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ROLE_TO_EMPLOYER; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_TO_CREDENTIALS; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_TO_MAIN_BODY; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.TABLE_SLACK; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.cellStyle; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.gap; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.italic; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.leading; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.style; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.heading; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.spacer; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.text; + +/** + * The wide column: the profile, the roles on a rail, and the credentials + * footer. + */ +final class SlateOrangeMain { + + private SlateOrangeMain() { + } + + static void compose(SectionBuilder main, ParagraphSection profile, + EntriesSection experience, EntriesSection education, + EntriesSection certifications) { + main.spacing(0); + main.padding((float) BODY_TOP, (float) PAGE_MARGIN, (float) PAGE_MARGIN, + (float) HALF_GAP); + if (profile != null && !profile.body().isBlank()) { + renderProfile(main, profile); + } + if (hasEntries(experience)) { + renderExperience(main, experience); + } + if (hasEntries(education) || hasEntries(certifications)) { + renderCredentials(main, education, certifications); + } + } + + /** The profile — one paragraph at the design's measured leading. */ + private static void renderProfile(SectionBuilder main, ParagraphSection profile) { + main.addSection("Profile", block -> { + block.spacing(0); + heading(block, "Profile", profile.title()); + block.addParagraph(p -> p + .name("ProfileBody") + .text(profile.body().replace(String.valueOf((char) 10), " ")) + .lineSpacing(leading(PROFILE_LEADING, BODY_SIZE)) + .textStyle(style(BODY_FONT, BODY_SIZE, INK, false)) + .margin((float) RULE_TO_MAIN_BODY, 0f, 0f, 0f)); + }); + } + + // -- experience -------------------------------------------------------- + + /** + * The roles held, on one rail. + * + *

The rail is the left border of each entry's own section, so it + * stretches to whatever height that entry turns out to have and + * consecutive entries butt together into one unbroken line. The last entry + * does not carry it: the design's rail stops at the final marker rather + * than running past the final bullet, and the entry list is what decides + * which entry that is.

+ * + *

The marker is a disc positioned on the rail by a layer stack, nudged + * left by the entry's own indent plus half the disc so its centre lands on + * the border rather than beside it. Both terms are geometry the sheet + * already holds, not offsets tuned by eye.

+ */ + private static void renderExperience(SectionBuilder main, EntriesSection experience) { + main.addSection("Experience", block -> { + block.spacing(0); + block.margin((float) PROFILE_TO_EXPERIENCE, 0f, 0f, 0f); + block.keepTogether(); + heading(block, "Experience", experience.title()); + block.addSection("ExperienceEntries", host -> { + host.spacing(0); + host.margin((float) RULE_TO_MAIN_BODY, 0f, 0f, 0f); + List entries = experience.entries(); + for (int i = 0; i < entries.size(); i++) { + CvEntry entry = entries.get(i); + boolean last = i == entries.size() - 1; + int index = i; + host.addSection("ExperienceEntry_" + index, body -> { + body.spacing(0); + if (!last) { + body.accentLeft(RULE, RULE_THICKNESS); + } + body.padding(0f, 0f, last ? 0f : (float) ENTRY_GAP, + (float) ENTRY_INDENT); + renderEntry(body, entry, index); + }); + } + }); + }); + } + + /** One entry: the role and its dates, the employer line, then the bullets. */ + private static void renderEntry(SectionBuilder body, CvEntry entry, int index) { + body.addLayerStack(stack -> stack + .name("RoleLine_" + index) + .layer(roleLine(entry, index), LayerAlign.TOP_LEFT, 0) + .position(marker(index), + -(ENTRY_INDENT + MARKER_DIAMETER / 2.0), 0.0, + LayerAlign.TOP_LEFT, 1)); + body.addParagraph(p -> p + .name("Employer_" + index) + .text(entry.subtitle()) + .lineSpacing(0) + .textStyle(italic(BODY_FONT, EMPLOYER_SIZE, INK)) + .margin((float) ROLE_TO_EMPLOYER, 0f, (float) EMPLOYER_TO_HIGHLIGHTS, 0f)); + List highlights = lines(entry.body()); + if (highlights.isEmpty()) { + return; + } + body.addList(list -> list + .name("Highlights_" + index) + .items(highlights) + .marker(ListMarker.bullet()) + .textStyle(style(BODY_FONT, HIGHLIGHT_SIZE, INK, false)) + .itemSpacing(gap(HIGHLIGHT_PITCH, HIGHLIGHT_SIZE * LINE_FACTOR)) + .lineSpacing(leading(HIGHLIGHT_LEADING, HIGHLIGHT_SIZE))); + } + + /** The role and its dates, the dates flush right on the same line. */ + private static DocumentNode roleLine(CvEntry entry, int index) { + ParagraphBuilder role = new ParagraphBuilder() + .name("Role_" + index) + .text(entry.title()) + .lineSpacing(0) + .textStyle(style(BODY_FONT, ROLE_SIZE, INK, true)); + if (!entry.link().isBlank()) { + role.link(new DocumentLinkOptions(entry.link())); + } + return new TableBuilder() + .name("RoleTable_" + index) + .width(ENTRY_WIDTH) + .columns( + DocumentTableColumn.fixed(ROLE_COLUMN), + DocumentTableColumn.fixed(PERIOD_COLUMN)) + .defaultCellStyle(cellStyle(DocumentInsets.zero(), + DocumentTableTextAnchor.BOTTOM_LEFT)) + .rowCells( + DocumentTableCell.node(role.build()), + DocumentTableCell.node(new ParagraphBuilder() + .name("Period_" + index) + .text(entry.date()) + .align(TextAlign.RIGHT) + .lineSpacing(0) + .textStyle(style(BODY_FONT, PERIOD_SIZE, INK, false)) + .build())) + .build(); + } + + /** The disc that caps the rail beside a role line. */ + private static DocumentNode marker(int index) { + ParagraphBuilder paragraph = new ParagraphBuilder(); + paragraph.name("Marker_" + index); + paragraph.lineSpacing(0); + paragraph.textStyle(style(BODY_FONT, MARKER_DIAMETER, ACCENT, false)); + paragraph.dot(MARKER_DIAMETER, ACCENT); + return paragraph.build(); + } + + // -- credentials ------------------------------------------------------- + + /** + * The credentials footer: a rule across the column, then education and + * certifications side by side. + * + *

One table, three rows. The first is the two headings; the second is + * their orange rules, drawn as cells filled to half a point of height, + * because a cell's stroke is a box with no per-edge control and a line + * node in a cell is not drawn at all. The third holds each column's + * content: a single-column table on the left, because a cell holds one + * node and a degree is three stacked lines, and the certifications list on + * the right, which is one list node and needs no wrapper.

+ */ + private static void renderCredentials(SectionBuilder main, EntriesSection education, + EntriesSection certifications) { + main.addSection("Credentials", block -> { + block.spacing(0); + block.margin((float) EXPERIENCE_TO_RULE, 0f, 0f, 0f); + block.addLine(line -> line + .name("CredentialsRule") + .fill() + .thickness(RULE_THICKNESS) + .color(RULE)); + block.addTable(table -> { + table.name("CredentialTable"); + table.margin(new DocumentInsets(RULE_TO_CREDENTIALS, 0, 0, 0)); + table.width(CREDENTIAL_TABLE_WIDTH); + table.columns( + DocumentTableColumn.fixed(CREDENTIAL_LEFT_COLUMN), + DocumentTableColumn.fixed(CREDENTIAL_GUTTER), + DocumentTableColumn.fixed(CREDENTIAL_RIGHT_COLUMN)); + table.defaultCellStyle(cellStyle(DocumentInsets.zero(), + DocumentTableTextAnchor.TOP_LEFT)); + table.rowCells( + DocumentTableCell.node(text("EducationHeading", + education == null ? "" : education.title(), + style(DISPLAY_FONT, CREDENTIAL_HEADING_SIZE, INK, true))), + DocumentTableCell.node(spacer("CredentialGutterHeading")), + DocumentTableCell.node(text("CertificationsHeading", + certifications == null ? "" : certifications.title(), + style(DISPLAY_FONT, CREDENTIAL_HEADING_SIZE, INK, true)))); + table.rowCells( + credentialRule("EducationHeadingRule"), + DocumentTableCell.node(spacer("CredentialGutterRule")), + credentialRule("CertificationsHeadingRule")); + table.rowCells( + DocumentTableCell.node(educationLines(education)), + DocumentTableCell.node(spacer("CredentialGutterBody")), + DocumentTableCell.node(certificationList(certifications))); + table.rowStyle(0, cellStyle( + new DocumentInsets(0, 0, CREDENTIAL_HEADING_TO_RULE, 0), + DocumentTableTextAnchor.TOP_LEFT)); + table.rowStyle(2, cellStyle( + new DocumentInsets(CREDENTIAL_RULE_TO_BODY, 0, 0, 0), + DocumentTableTextAnchor.TOP_LEFT)); + }); + }); + } + + /** A heading rule, as a cell filled to a hairline of height. */ + private static DocumentTableCell credentialRule(String name) { + return DocumentTableCell + .node(new ParagraphBuilder() + .name(name) + .text(" ") + .lineSpacing(0) + .textStyle(style(BODY_FONT, CREDENTIAL_RULE_SIZE, ACCENT, false)) + .build()) + .withStyle(DocumentTableStyle.builder() + .padding(DocumentInsets.zero()) + .fillColor(ACCENT) + .stroke(NO_BORDER) + .build()); + } + + /** + * Each degree as three stacked lines: the award, the institution and + * whatever the entry says about when. + */ + private static DocumentNode educationLines(EntriesSection education) { + double width = CREDENTIAL_LEFT_COLUMN - TABLE_SLACK; + TableBuilder table = new TableBuilder() + .name("EducationLines") + .width(width) + .columns(DocumentTableColumn.fixed(width)) + .defaultCellStyle(cellStyle( + new DocumentInsets(0, 0, + gap(EDUCATION_LINE_PITCH, EDUCATION_LINE_SIZE * LINE_FACTOR), 0), + DocumentTableTextAnchor.TOP_LEFT)); + if (education == null) { + return table.rowCells(DocumentTableCell.node(spacer("EducationEmpty"))).build(); + } + List entries = education.entries(); + for (int index = 0; index < entries.size(); index++) { + CvEntry entry = entries.get(index); + ParagraphBuilder degree = new ParagraphBuilder() + .name("Degree_" + index) + .text(entry.title()) + .lineSpacing(0) + .textStyle(style(BODY_FONT, DEGREE_SIZE, INK, true)); + if (!entry.link().isBlank()) { + degree.link(new DocumentLinkOptions(entry.link())); + } + table.rowCells(DocumentTableCell.node(degree.build())); + table.rowCells(DocumentTableCell.node(new ParagraphBuilder() + .name("Institution_" + index) + .text(entry.subtitle()) + .lineSpacing(0) + .textStyle(italic(BODY_FONT, EDUCATION_LINE_SIZE, INK)) + .build())); + table.rowCells(DocumentTableCell.node(text("EducationDetail_" + index, + detail(entry), style(BODY_FONT, EDUCATION_LINE_SIZE, INK, false)))); + } + return table.build(); + } + + /** + * The line under an institution: what the entry says about where and when, + * joined the way the design joins them. + */ + private static String detail(CvEntry entry) { + StringBuilder detail = new StringBuilder(); + if (!entry.place().isBlank()) { + detail.append(entry.place()); + } + if (!entry.date().isBlank()) { + detail.append(detail.isEmpty() ? "" : " " + (char) 0x2022 + " ").append(entry.date()); + } + return detail.toString(); + } + + /** The certifications, as one bulleted list. */ + private static DocumentNode certificationList(EntriesSection certifications) { + List items = new ArrayList<>(); + if (certifications != null) { + for (CvEntry entry : certifications.entries()) { + items.add(entry.title()); + } + } + if (items.isEmpty()) { + return spacer("CertificationsEmpty"); + } + return new ListBuilder() + .name("CertificationItems") + .items(items) + .marker(ListMarker.bullet()) + .textStyle(style(BODY_FONT, CREDENTIAL_SIZE, INK, false)) + .itemSpacing(gap(CREDENTIAL_LINE_PITCH, CREDENTIAL_SIZE * LINE_FACTOR)) + .build(); + } + + // -- shared ------------------------------------------------------------ + + /** A body, one entry per line the document wrote. */ + private static List lines(String body) { + List out = new ArrayList<>(); + for (String line : body.split(String.valueOf((char) 10))) { + if (!line.isBlank()) { + out.add(line.strip()); + } + } + return out; + } + + private static boolean hasEntries(EntriesSection section) { + return section != null && !section.entries().isEmpty(); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMasthead.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMasthead.java new file mode 100644 index 000000000..84395f8f9 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeMasthead.java @@ -0,0 +1,304 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.api.DocumentSession; +import com.demcha.compose.document.api.PageBackgroundFill; +import com.demcha.compose.document.dsl.LineBuilder; +import com.demcha.compose.document.dsl.PageFlowBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.node.DocumentLinkOptions; +import com.demcha.compose.document.node.HorizontalAlign; +import com.demcha.compose.document.node.TextAlign; +import com.demcha.compose.document.style.DocumentRowColumn; +import com.demcha.compose.document.style.DocumentTextStyle; +import com.demcha.compose.document.templates.core.identity.Contact; +import com.demcha.compose.document.templates.core.identity.Link; +import com.demcha.compose.document.templates.cv.data.CvIdentity; +import com.demcha.compose.document.templates.cv.data.ParagraphSection; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_TOP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CONTACT_PAD_LEFT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CONTACT_PITCH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CONTACT_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CONTACT_TOP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIALS_DIVIDER_HEIGHT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIALS_DIVIDER_X; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIALS_DIVIDER_Y; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.DISPLAY_FONT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HAIRLINE_BOTTOM; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HAIRLINE_HEIGHT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HAIRLINE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HAIRLINE_TOP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HALF_GAP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.IDENTITY_TOP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.IDENTITY_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.INITIALS_TO_RULE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LINE_FACTOR; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MASTHEAD_HEIGHT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MASTHEAD_INK; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MASTHEAD_MUTED; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MONOGRAM_RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MONOGRAM_RULE_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MONOGRAM_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.MONOGRAM_TOP; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.NAME_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.NAME_TO_ROLE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PAGE_HEIGHT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PAGE_MARGIN; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.PAGE_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ROLE_LINE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ROLE_TO_TAGLINE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_FAINT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.SIDEBAR_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.SLATE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.TAGLINE_SEPARATOR; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.TAGLINE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.TILE_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.gap; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.style; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeWidgets.inlineIcon; + +/** + * The page chrome and the band above the body: the monogram tile, the + * identity strip, the orange hairline and the contact column. + */ +final class SlateOrangeMasthead { + + private SlateOrangeMasthead() { + } + + /** One line of the contact column: a mark, a value and where it points. */ + private record Channel(String token, String value, String href) { + } + + /** + * The four fills whose geometry is a fact about the page rather than about + * any content: the slate band, the orange tile over its left end, the + * hairline dividing the two body columns, and the fainter one dividing the + * two credential columns. + * + *

They are page backgrounds rather than section fills or lines: a fill + * on a section is bounded by its content and would stop short of the paper + * edge, while a page background takes its geometry from the canvas and + * reaches all four. Order matters — the tile is listed after the band so + * it paints over it.

+ */ + static void renderChrome(DocumentSession document) { + document.pageBackgrounds(List.of( + PageBackgroundFill.topBandPoints(MASTHEAD_HEIGHT, PAGE_HEIGHT, SLATE), + new PageBackgroundFill(0.0, 0.0, + TILE_WIDTH / PAGE_WIDTH, MASTHEAD_HEIGHT / PAGE_HEIGHT, ACCENT), + new PageBackgroundFill( + (PAGE_MARGIN + SIDEBAR_WIDTH + HALF_GAP) / PAGE_WIDTH, + (MASTHEAD_HEIGHT + BODY_TOP) / PAGE_HEIGHT, + RULE_THICKNESS / PAGE_WIDTH, + (PAGE_HEIGHT - MASTHEAD_HEIGHT - BODY_TOP - PAGE_MARGIN) / PAGE_HEIGHT, + RULE), + new PageBackgroundFill( + CREDENTIALS_DIVIDER_X, CREDENTIALS_DIVIDER_Y, + RULE_THICKNESS / PAGE_WIDTH, CREDENTIALS_DIVIDER_HEIGHT, + RULE_FAINT))); + } + + /** + * The band's content, as four cells of one top-level row. + * + *

The row's height is set by the hairline cell rather than by whichever + * text block happens to be tallest: that cell's padding and its line add + * up to the band's height exactly, so the body below starts where the + * slate fill ends however the type is later adjusted.

+ */ + static void render(PageFlowBuilder page, CvIdentity identity, ParagraphSection specialisms) { + page.addRow("Masthead", row -> { + row.spacing(0); + row.columns( + DocumentRowColumn.fixed(TILE_WIDTH), + DocumentRowColumn.fixed(IDENTITY_WIDTH), + DocumentRowColumn.fixed(HAIRLINE_THICKNESS), + // The remainder, not a fourth measured width: four fixed + // columns summing to the page leave the engine nothing to + // round with, and it refuses the row by a third of a point. + DocumentRowColumn.weight(1.0)); + row.addSection("Monogram", tile -> renderTile(tile, identity)); + row.addSection("Identity", block -> renderIdentity(block, identity, specialisms)); + row.addSection("MastheadHairline", SlateOrangeMasthead::renderHairline); + row.addSection("Contact", block -> renderContact(block, identity)); + }); + } + + // -- the tile ---------------------------------------------------------- + + /** + * The initials and the short rule under them, centred in the tile. + * + *

Both are centred on the cell rather than positioned at a measured x, + * so they follow the same constant the tile's fill uses. The initials come + * from the name itself: a document states its name once, and a second + * place to keep true is a second place to be wrong.

+ */ + private static void renderTile(SectionBuilder tile, CvIdentity identity) { + tile.spacing(0); + tile.padding((float) MONOGRAM_TOP, 0f, 0f, 0f); + tile.addParagraph(p -> p + .name("Initials") + .text(initials(identity)) + .align(TextAlign.CENTER) + .lineSpacing(0) + .textStyle(style(DISPLAY_FONT, MONOGRAM_SIZE, MASTHEAD_INK, true)) + .margin(0f, 0f, (float) INITIALS_TO_RULE, 0f)); + tile.addAligned(HorizontalAlign.CENTER, new LineBuilder() + .name("MonogramRule") + .horizontal(MONOGRAM_RULE_WIDTH) + .thickness(MONOGRAM_RULE_THICKNESS) + .color(MASTHEAD_INK) + .build()); + } + + private static String initials(CvIdentity identity) { + StringBuilder out = new StringBuilder(2); + appendInitial(out, identity.name().first()); + appendInitial(out, identity.name().last()); + return out.toString(); + } + + private static void appendInitial(StringBuilder out, String part) { + if (!part.isBlank()) { + out.append(Character.toUpperCase(part.charAt(0))); + } + } + + // -- the identity strip ------------------------------------------------ + + /** Name, role line and specialism strip, stacked on one left edge. */ + private static void renderIdentity(SectionBuilder block, CvIdentity identity, + ParagraphSection specialisms) { + block.spacing(0); + block.padding((float) IDENTITY_TOP, 0f, 0f, (float) PAGE_MARGIN); + block.addParagraph(p -> p + .name("Name") + .text(identity.name().full().toUpperCase(Locale.ROOT)) + .lineSpacing(0) + .textStyle(style(DISPLAY_FONT, NAME_SIZE, MASTHEAD_INK, true)) + .margin(0f, 0f, (float) NAME_TO_ROLE, 0f)); + block.addParagraph(p -> p + .name("RoleLine") + .text(identity.jobTitle().toUpperCase(Locale.ROOT)) + .lineSpacing(0) + .textStyle(style(DISPLAY_FONT, ROLE_LINE_SIZE, ACCENT, true)) + .margin(0f, 0f, (float) ROLE_TO_TAGLINE, 0f)); + if (specialisms == null || specialisms.body().isBlank()) { + return; + } + block.addParagraph(p -> p + .name("Tagline") + .text(String.join(TAGLINE_SEPARATOR, lines(specialisms.body()))) + .lineSpacing(0) + .textStyle(style(DISPLAY_FONT, TAGLINE_SIZE, MASTHEAD_MUTED, false))); + } + + /** The specialisms, one per line the document wrote. */ + private static List lines(String body) { + List out = new ArrayList<>(); + for (String line : body.split(String.valueOf((char) 10))) { + if (!line.isBlank()) { + out.add(line.strip().toUpperCase(Locale.ROOT)); + } + } + return out; + } + + // -- the hairline ------------------------------------------------------ + + /** + * The vertical accent between the two halves of the band. It is a cell of + * the row, so its horizontal position comes from the row's own column + * widths rather than from a measured x — and its padding is what gives the + * row its height. + */ + private static void renderHairline(SectionBuilder cell) { + cell.spacing(0); + cell.padding((float) HAIRLINE_TOP, 0f, (float) HAIRLINE_BOTTOM, 0f); + cell.addLine(line -> line + .name("MastheadHairlineRule") + .vertical(HAIRLINE_HEIGHT) + .thickness(HAIRLINE_THICKNESS) + .color(ACCENT)); + } + + // -- the contact column ------------------------------------------------ + + /** + * The contact lines. + * + *

Each is one paragraph rather than a table: the mark is an inline run + * measured into the line box, so it shares a baseline with its value by + * construction, and nothing here has to line up with a column. Where the + * value points somewhere the run becomes an inline link, so the target + * reaches the PDF as a real annotation rather than as text that merely + * looks like one.

+ * + *

A link shows its own label and carries the address behind it, so the + * column's width does not depend on how long a profile happens to be + * called.

+ */ + private static void renderContact(SectionBuilder block, CvIdentity identity) { + block.spacing(0); + block.padding((float) CONTACT_TOP, 0f, 0f, (float) CONTACT_PAD_LEFT); + DocumentTextStyle valueStyle = style(BODY_FONT, CONTACT_SIZE, MASTHEAD_INK, false); + List channels = channels(identity); + for (int i = 0; i < channels.size(); i++) { + Channel channel = channels.get(i); + boolean last = i == channels.size() - 1; + int index = i; + block.addParagraph(p -> { + p.name("Contact_" + index + "_" + channel.token()); + p.lineSpacing(0); + inlineIcon(p, channel.token()); + p.inlineText(" ", valueStyle); + if (channel.href() == null || channel.href().isBlank()) { + p.inlineText(channel.value(), valueStyle); + } else { + p.inlineText(channel.value(), valueStyle, + new DocumentLinkOptions(channel.href())); + } + p.margin(0f, 0f, + last ? 0f : (float) gap(CONTACT_PITCH, CONTACT_SIZE * LINE_FACTOR), 0f); + }); + } + } + + /** The column's order: how to call, how to write, the links, then where. */ + private static List channels(CvIdentity identity) { + Contact contact = identity.contact(); + List channels = new ArrayList<>(); + channels.add(new Channel(SlateOrangeIcons.PHONE, contact.phone(), + telUri(contact.phone()))); + channels.add(new Channel(SlateOrangeIcons.EMAIL, contact.email(), + "mailto:" + contact.email())); + for (Link link : identity.links()) { + channels.add(new Channel(SlateOrangeIcons.LINKEDIN, link.label(), link.url())); + } + channels.add(new Channel(SlateOrangeIcons.LOCATION, contact.address(), null)); + return channels; + } + + /** + * The dial target for a phone number: its digits, keeping a leading + * {@code +} so an international number stays international, and dropping a + * parenthesised trunk prefix the way a caller dialling from abroad does. + */ + private static String telUri(String phone) { + String dialled = phone.replaceAll("\\(0+\\)", ""); + String digits = dialled.replaceAll("[^0-9]", ""); + return digits.isEmpty() + ? null + : "tel:" + (phone.trim().startsWith("+") ? "+" : "") + digits; + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeStyles.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeStyles.java new file mode 100644 index 000000000..0ab50afd2 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeStyles.java @@ -0,0 +1,342 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.api.DocumentPageSize; +import com.demcha.compose.document.style.DocumentColor; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentStroke; +import com.demcha.compose.document.style.DocumentTextDecoration; +import com.demcha.compose.document.style.DocumentTextStyle; +import com.demcha.compose.document.table.DocumentTableStyle; +import com.demcha.compose.document.table.DocumentTableTextAnchor; +import com.demcha.compose.font.FontName; + +/** + * The measured geometry, palette and type scale of the Slate Orange CV. + * + *

Everything horizontal derives from four numbers

+ * + *

{@link #PAGE_WIDTH}, {@link #PAGE_MARGIN}, {@link #SIDEBAR_WEIGHT} and + * {@link #COLUMN_GAP}: the page-background bands, the body row's weights and + * every table's column widths read the same four, so a fill and the content + * sitting on it cannot drift apart. Only genuinely independent marks — a rule + * thickness, a marker diameter — are written as points.

+ * + *

Vertical pitches are measured, then converted

+ * + *

The engine's line box is {@link #LINE_FACTOR} times the type size and + * {@code lineSpacing} adds points on top of it, so a measured pitch minus the + * line it has to clear is the gap that produces it — {@link #gap} and + * {@link #leading} are that conversion. A CSS-style multiple would be + * silently wrong.

+ */ +final class SlateOrangeStyles { + + private SlateOrangeStyles() { + } + + // -- type -------------------------------------------------------------- + + /** The condensed display face: name, monogram and every section heading. */ + static final FontName DISPLAY_FONT = FontName.ASAP_CONDENSED; + + /** + * The body face: everything the display face does not set. + * + *

Condensed, and chosen by measurement rather than by eye. Against the + * design on three separate strings — a summary line, an experience bullet + * and a competency label — this face averages within one per cent, where + * the face its letterforms most resemble runs a tenth to a quarter too + * wide on all three. That is the difference between a bullet on one line + * and a bullet on two.

+ */ + static final FontName BODY_FONT = FontName.FIRA_SANS_CONDENSED; + + static final double MONOGRAM_SIZE = 50.0; + static final double NAME_SIZE = 40.5; + static final double ROLE_LINE_SIZE = 16.5; + static final double TAGLINE_SIZE = 10.5; + static final double CONTACT_SIZE = 9.6; + static final double HEADING_SIZE = 12.5; + + /** + * The body size, set from the design's line WIDTH rather than its ink + * height, because the two disagree here: matched on height the summary ran + * to six lines where the design has five and every line broke on a + * different word. Matching the width sets the type a few per cent small + * and puts every break back where the design has it. + */ + static final double BODY_SIZE = 9.4; + + /** + * The sidebar label size, set the same way and then backed off a quarter + * point: the longest additional-information label needed all but four + * points of its column and the engine broke it anyway. One size has to + * hold both sidebar blocks, because the design sets both at one size. + */ + static final double LABEL_SIZE = 8.65; + + static final double ACHIEVEMENT_TITLE_SIZE = 9.4; + static final double ACHIEVEMENT_BODY_SIZE = 8.3; + static final double LANGUAGE_SIZE = 8.8; + static final double LEVEL_SIZE = 6.2; + static final double ROLE_SIZE = 10.35; + static final double EMPLOYER_SIZE = 9.1; + static final double PERIOD_SIZE = 8.1; + static final double HIGHLIGHT_SIZE = 9.05; + static final double DEGREE_SIZE = 8.7; + static final double EDUCATION_LINE_SIZE = 8.6; + static final double CREDENTIAL_SIZE = 7.25; + + /** + * The credential headings, which the design sets smaller than the ones + * above them. Not an oversight to be tidied into {@link #HEADING_SIZE}: + * the two credential columns are a footer rather than a third and fourth + * section of the page, and the design's caps measure smaller to say so. + */ + static final double CREDENTIAL_HEADING_SIZE = 10.0; + + /** The engine's line box as a multiple of the type size. */ + static final double LINE_FACTOR = 1.2; + + // -- palette ----------------------------------------------------------- + + static final DocumentColor SLATE = DocumentColor.rgb(34, 46, 56); + static final DocumentColor ACCENT = DocumentColor.rgb(194, 96, 72); + static final DocumentColor INK = DocumentColor.rgb(46, 57, 68); + static final DocumentColor MASTHEAD_INK = DocumentColor.WHITE; + static final DocumentColor MASTHEAD_MUTED = DocumentColor.rgb(216, 220, 224); + static final DocumentColor MUTED = DocumentColor.rgb(138, 144, 153); + static final DocumentColor RULE = DocumentColor.rgb(200, 200, 202); + static final DocumentColor RULE_FAINT = DocumentColor.rgb(227, 227, 227); + static final DocumentColor RATING_EMPTY = DocumentColor.rgb(202, 205, 207); + + // -- the page ---------------------------------------------------------- + + static final double PAGE_WIDTH = 595.276; + static final double PAGE_HEIGHT = 841.89; + static final DocumentPageSize PAGE = DocumentPageSize.A4; + static final double PAGE_MARGIN = 22.0; + static final double CONTENT_WIDTH = PAGE_WIDTH - 2.0 * PAGE_MARGIN; + + static final double MASTHEAD_HEIGHT = 136.6; + static final double TILE_WIDTH = 85.8; + static final double COLUMN_GAP = 45.7; + static final double SIDEBAR_WEIGHT = 0.31514; + static final double MAIN_WEIGHT = 1.0 - SIDEBAR_WEIGHT; + static final double COLUMNS_WIDTH = CONTENT_WIDTH - COLUMN_GAP; + static final double SIDEBAR_WIDTH = COLUMNS_WIDTH * SIDEBAR_WEIGHT; + static final double MAIN_WIDTH = COLUMNS_WIDTH * MAIN_WEIGHT; + + /** + * The body row carries no padding and no spacing of its own: each column + * pads itself and half the gap goes to each side, so the page margin and + * the gap live inside the cells and the cell weights are what is left once + * they are added back on. + */ + static final double HALF_GAP = COLUMN_GAP / 2.0; + static final double SIDEBAR_CELL = SIDEBAR_WIDTH + PAGE_MARGIN + HALF_GAP; + static final double MAIN_CELL = MAIN_WIDTH + PAGE_MARGIN + HALF_GAP; + static final double SIDEBAR_CELL_WEIGHT = SIDEBAR_CELL / PAGE_WIDTH; + static final double MAIN_CELL_WEIGHT = MAIN_CELL / PAGE_WIDTH; + + // -- rules and marks --------------------------------------------------- + + static final double RULE_THICKNESS = 0.6; + static final double HAIRLINE_THICKNESS = 1.2; + static final double MONOGRAM_RULE_THICKNESS = 1.7; + static final double MARKER_DIAMETER = 5.6; + static final double RATING_DOT_DIAMETER = 5.6; + + /** + * A hundredth of a point of slack under every table. The engine compares a + * table's declared width against its container's to the last bit, and a + * sum of derived doubles lands a ten-thousandth of a point over — enough + * to be refused. Taking it off the last column leaves every other column + * exactly where the measurement put it. + */ + static final double TABLE_SLACK = 0.01; + + /** + * No cell borders. + * + *

A table draws its rules per cell from that cell's own style, and the + * default style has one. The tables here are a layout mechanism rather + * than a grid the reader should see, so every cell states the absence + * explicitly: a zero-width, fully transparent stroke.

+ */ + static final DocumentStroke NO_BORDER = + DocumentStroke.of(DocumentColor.rgba(0, 0, 0, 0), 0.0); + + // -- the masthead ------------------------------------------------------ + + static final double HAIRLINE_X = 383.7; + static final double IDENTITY_WIDTH = HAIRLINE_X - TILE_WIDTH; + static final double HAIRLINE_TOP = 34.4; + static final double HAIRLINE_HEIGHT = 79.0; + static final double HAIRLINE_BOTTOM = MASTHEAD_HEIGHT - HAIRLINE_TOP - HAIRLINE_HEIGHT; + static final double MONOGRAM_TOP = 35.8; + static final double MONOGRAM_RULE_WIDTH = 37.2; + static final double INITIALS_TO_RULE = 1.7; + static final double IDENTITY_TOP = 27.4; + static final double NAME_TO_ROLE = 1.5; + static final double ROLE_TO_TAGLINE = 7.5; + static final double CONTACT_TOP = 36.8; + static final double CONTACT_PAD_LEFT = 21.4; + static final double CONTACT_PITCH = 21.1; + + /** + * The specialism strip's separator. + * + *

Nine spaces a side rather than two: the design tracks that whole + * line, a text style carries no letter-spacing, and padding the separator + * recovers the width without putting spaces inside a word — which is what + * the extracted text would then say the document contains.

+ */ + static final String TAGLINE_SEPARATOR = " • "; + + // -- the rhythm between blocks ----------------------------------------- + + static final double BODY_TOP = 18.5; + static final double HEADING_TO_RULE = 3.5; + static final double RULE_TO_SIDEBAR_BODY = 9.5; + static final double RULE_TO_MAIN_BODY = 13.0; + + /** + * The three gaps between sidebar blocks are three separate measurements + * off the design, not one constant applied three times. Deriving them from + * each other would be inventing a rhythm the design does not have. + */ + static final double ACHIEVEMENTS_TOP_GAP = 23.6; + static final double LANGUAGES_TOP_GAP = 17.3; + static final double ADDITIONAL_TOP_GAP = 23.9; + + static final double ICON_COLUMN = 24.8; + + /** + * The closing block's icon column, which the design makes narrower than + * the competencies'. Worth its own constant rather than rounding to the + * shared one: the longest label in that block cleared the shared column by + * less than the rounding and broke onto a second line. + */ + static final double ADDITIONAL_ICON_COLUMN = 22.9; + + static final double SIDEBAR_TABLE_WIDTH = SIDEBAR_WIDTH - TABLE_SLACK; + static final double COMPETENCY_PITCH = 23.15; + static final double ACHIEVEMENT_BODY_LEADING = 11.3; + + /** + * Half the gap the design shows between achievements, because the trophy's + * own line box is taller than the title beside it and a table row is as + * tall as its tallest cell — the mark has already paid for the rest. + */ + static final double ACHIEVEMENT_GAP = 3.5; + + static final double LANGUAGE_PITCH = 16.4; + static final double ADDITIONAL_PITCH = 25.1; + static final double LANGUAGE_NAME_COLUMN = SIDEBAR_WIDTH * 0.230; + static final double LANGUAGE_LEVEL_COLUMN = SIDEBAR_WIDTH * 0.407; + static final double LANGUAGE_RATING_COLUMN = + SIDEBAR_TABLE_WIDTH - LANGUAGE_NAME_COLUMN - LANGUAGE_LEVEL_COLUMN; + + static final double PROFILE_LEADING = 13.83; + static final double PROFILE_TO_EXPERIENCE = 23.0; + static final double ENTRY_INDENT = 13.0; + static final double ENTRY_WIDTH = MAIN_WIDTH - ENTRY_INDENT - TABLE_SLACK; + + /** + * The design's three inter-entry gaps differ, and this is the one value + * that has to serve all three. It sits at the low end of that range rather + * than the middle: the body row is atomic and the page has about a point + * of slack, so a gap that split the difference would cost a second page. + */ + static final double ENTRY_GAP = 18.4; + + static final double ROLE_TO_EMPLOYER = 2.0; + static final double EMPLOYER_TO_HIGHLIGHTS = 6.6; + static final double HIGHLIGHT_PITCH = 14.96; + static final double HIGHLIGHT_LEADING = 12.99; + static final double PERIOD_COLUMN = ENTRY_WIDTH * 0.30; + static final double ROLE_COLUMN = ENTRY_WIDTH - PERIOD_COLUMN; + + static final double EXPERIENCE_TO_RULE = 12.0; + static final double RULE_TO_CREDENTIALS = 12.1; + static final double CREDENTIAL_LEFT_COLUMN = MAIN_WIDTH * 0.400; + static final double CREDENTIAL_GUTTER = MAIN_WIDTH * 0.0585; + static final double CREDENTIAL_TABLE_WIDTH = MAIN_WIDTH - TABLE_SLACK; + static final double CREDENTIAL_RIGHT_COLUMN = + CREDENTIAL_TABLE_WIDTH - CREDENTIAL_LEFT_COLUMN - CREDENTIAL_GUTTER; + + /** + * The credential headings sit closer to their rules than the headings + * above them do. A table row's padding is not a paragraph's margin — it + * has no line box to clear — so the same visual gap is a smaller number + * here. + */ + static final double CREDENTIAL_HEADING_TO_RULE = 2.5; + static final double CREDENTIAL_RULE_TO_BODY = 6.5; + static final double EDUCATION_LINE_PITCH = 12.4; + static final double CREDENTIAL_LINE_PITCH = 11.9; + + /** A heading rule inside a credential column, as a filled hairline row. */ + static final double CREDENTIAL_RULE_SIZE = 0.5; + + /** + * The credentials divider is the one mark whose extent is measured rather + * than derived: a table cell's stroke is a box with no per-edge control, + * so the divider cannot be the right column's own border and is a page + * background like the three above it. + */ + static final double CREDENTIALS_DIVIDER_X = 0.61422; + static final double CREDENTIALS_DIVIDER_Y = 0.89671; + static final double CREDENTIALS_DIVIDER_HEIGHT = 0.07713; + + // -- helpers ----------------------------------------------------------- + + static DocumentTextStyle style(FontName font, double size, DocumentColor color, + boolean bold) { + return DocumentTextStyle.builder() + .fontName(font) + .size(size) + .color(color) + .decoration(bold ? DocumentTextDecoration.BOLD : DocumentTextDecoration.DEFAULT) + .build(); + } + + static DocumentTextStyle italic(FontName font, double size, DocumentColor color) { + return DocumentTextStyle.builder() + .fontName(font) + .size(size) + .color(color) + .decoration(DocumentTextDecoration.ITALIC) + .build(); + } + + /** A cell's padding and how its content sits in it. */ + static DocumentTableStyle cellStyle(DocumentInsets padding, + DocumentTableTextAnchor anchor) { + return DocumentTableStyle.builder() + .padding(padding) + .textAnchor(anchor) + .stroke(NO_BORDER) + .build(); + } + + /** A measured pitch, minus the content it has to clear, is the gap that produces it. */ + static double gap(double pitch, double contentHeight) { + return Math.max(0.0, pitch - contentHeight); + } + + /** + * A measured leading, as the additive value {@code lineSpacing} actually + * is: the line box is {@link #LINE_FACTOR} times the type size and the + * setting adds points on top of it. + */ + static double leading(double measuredLeading, double size) { + return Math.max(0.0, measuredLeading - LINE_FACTOR * size); + } + + /** A node name built from a heading, with the spacing taken out of it. */ + static String compact(String value) { + return value == null ? "" : value.replaceAll("[^A-Za-z0-9]", ""); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeWidgets.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeWidgets.java new file mode 100644 index 000000000..c44000072 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/SlateOrangeWidgets.java @@ -0,0 +1,162 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.dsl.ParagraphBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.node.DocumentNode; +import com.demcha.compose.document.node.InlineImageAlignment; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentTextStyle; +import com.demcha.compose.document.table.DocumentTableCell; +import com.demcha.compose.document.table.DocumentTableColumn; +import com.demcha.compose.document.table.DocumentTableTextAnchor; +import com.demcha.compose.document.templates.cv.data.CvEntry; + +import java.util.List; + +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.CREDENTIAL_RULE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.DISPLAY_FONT; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HEADING_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.HEADING_TO_RULE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.INK; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LABEL_SIZE; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.LINE_FACTOR; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.RULE_TO_SIDEBAR_BODY; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.SIDEBAR_TABLE_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.cellStyle; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.compact; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.gap; +import static com.demcha.compose.document.templates.cv.presets.SlateOrangeStyles.style; + +/** + * The idioms this sheet repeats: the heading over its rule, a mark as a + * cell's node, a line of text as a cell's node, the empty cell, and the + * mark-and-label table both sidebar blocks are built from. + */ +final class SlateOrangeWidgets { + + private SlateOrangeWidgets() { + } + + /** + * A caps heading over its orange rule. + * + *

The rule is filled rather than given a width, so it spans whichever + * column the heading is in — one method serves the sidebar and the main + * column alike. The credential columns cannot use it, because they live + * inside table cells where a line node is not drawn; their rules are + * filled cells instead.

+ */ + static void heading(SectionBuilder block, String name, String text) { + block.addParagraph(p -> p + .name(name + "Heading") + .text(text) + .lineSpacing(0) + .textStyle(style(DISPLAY_FONT, HEADING_SIZE, INK, true)) + .margin(0f, 0f, (float) HEADING_TO_RULE, 0f)); + block.addLine(line -> line + .name(name + "HeadingRule") + .fill() + .thickness(RULE_THICKNESS) + .color(ACCENT)); + } + + /** One line of text as a cell's single node. */ + static DocumentNode text(String name, String value, DocumentTextStyle textStyle) { + return new ParagraphBuilder() + .name(name) + .text(value) + .lineSpacing(0) + .textStyle(textStyle) + .build(); + } + + /** An empty cell that still has to be a paragraph, because a cell holds a node. */ + static DocumentNode spacer(String name) { + return new ParagraphBuilder() + .name(name) + .text(" ") + .lineSpacing(0) + .textStyle(style(BODY_FONT, CREDENTIAL_RULE_SIZE, INK, false)) + .build(); + } + + /** Places a mark inline, on the baseline of the paragraph it opens. */ + static void inlineIcon(ParagraphBuilder paragraph, String token) { + paragraph.inlineSvgIcon(SlateOrangeIcons.icon(token), SlateOrangeIcons.size(token), + InlineImageAlignment.CENTER); + } + + /** + * A mark on its own, as a cell's single node. + * + *

Styled at the size of the label beside it although it carries no + * text: the default line box would set the row's pitch instead of the mark + * doing so. An inline run is measured into that box, so a mark taller than + * the label would be drawn clipped to it — whichever is larger wins.

+ */ + static DocumentNode iconCell(String name, String token, double labelSize) { + double boxSize = Math.max(labelSize, SlateOrangeIcons.size(token) / LINE_FACTOR); + ParagraphBuilder paragraph = new ParagraphBuilder(); + paragraph.name(name); + paragraph.lineSpacing(0); + paragraph.textStyle(style(BODY_FONT, boxSize, INK, false)); + inlineIcon(paragraph, token); + return paragraph.build(); + } + + /** + * The shape both mark-and-label blocks share: a fixed mark column beside a + * label column, one table row per entry. + * + *

The pitch is the table's own row padding, so adding an eleventh entry + * changes nothing about the spacing — the alternative, a bottom margin + * repeated on every label, is the same fact stated ten times. It is a gap + * BETWEEN rows, so the last row does not carry it: there it would become a + * gap between this block and the next, which the next block already + * owns.

+ */ + static void iconTable(SectionBuilder block, String tableName, String rowName, + List entries, double pitch, double iconColumn) { + block.addTable(table -> { + table.name(tableName); + table.margin(new DocumentInsets(RULE_TO_SIDEBAR_BODY, 0, 0, 0)); + table.width(SIDEBAR_TABLE_WIDTH); + table.columns( + DocumentTableColumn.fixed(iconColumn), + DocumentTableColumn.fixed(SIDEBAR_TABLE_WIDTH - iconColumn)); + table.defaultCellStyle(cellStyle( + new DocumentInsets(0, 0, gap(pitch, rowHeight(entries)), 0), + DocumentTableTextAnchor.CENTER_LEFT)); + for (int index = 0; index < entries.size(); index++) { + CvEntry entry = entries.get(index); + table.rowCells( + DocumentTableCell.node(entry.icon().isBlank() + ? spacer(rowName + "Icon_" + index) + : iconCell(rowName + "Icon_" + index, entry.icon(), LABEL_SIZE)), + DocumentTableCell.node(text(rowName + "Label_" + index, entry.title(), + style(BODY_FONT, LABEL_SIZE, INK, false)))); + } + table.rowStyle(entries.size() - 1, + cellStyle(DocumentInsets.zero(), DocumentTableTextAnchor.CENTER_LEFT)); + }); + } + + /** A row is as tall as the tallest mark in the block or its label's line box. */ + private static double rowHeight(List entries) { + double tallest = LABEL_SIZE * LINE_FACTOR; + for (CvEntry entry : entries) { + if (!entry.icon().isBlank()) { + tallest = Math.max(tallest, SlateOrangeIcons.size(entry.icon())); + } + } + return tallest; + } + + /** A node name built from a heading, with the spacing taken out of it. */ + static String nameOf(String value) { + return compact(value); + } +} diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/achievement.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/achievement.svg new file mode 100644 index 000000000..c66f37eb8 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/achievement.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/availability.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/availability.svg new file mode 100644 index 000000000..4f051b9b1 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/availability.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/calendar.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/calendar.svg new file mode 100644 index 000000000..2d7a77e2f --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/communication.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/communication.svg new file mode 100644 index 000000000..dba396bdb --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/communication.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/crm.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/crm.svg new file mode 100644 index 000000000..cb1adeac7 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/crm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/customer-service.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/customer-service.svg new file mode 100644 index 000000000..a5f199ad3 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/customer-service.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/email.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/email.svg new file mode 100644 index 000000000..cec0bf4aa --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/linkedin.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/linkedin.svg new file mode 100644 index 000000000..c8b287ae2 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/linkedin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/location.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/location.svg new file mode 100644 index 000000000..d7ac490e4 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/office-suite.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/office-suite.svg new file mode 100644 index 000000000..eaf930ab5 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/office-suite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/operations.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/operations.svg new file mode 100644 index 000000000..435b26489 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/operations.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/phone.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/phone.svg new file mode 100644 index 000000000..4628e2568 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/problem-solving.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/problem-solving.svg new file mode 100644 index 000000000..a430a1b79 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/problem-solving.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/relocation.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/relocation.svg new file mode 100644 index 000000000..e5d78cbeb --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/relocation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/remote-work.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/remote-work.svg new file mode 100644 index 000000000..157c50180 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/remote-work.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/reporting.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/reporting.svg new file mode 100644 index 000000000..1e0f0ce1d --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/reporting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/sales.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/sales.svg new file mode 100644 index 000000000..cc4c5a563 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/sales.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/slate-orange/icons/time-management.svg b/templates/src/main/resources/templates/cv/slate-orange/icons/time-management.svg new file mode 100644 index 000000000..4f051b9b1 --- /dev/null +++ b/templates/src/main/resources/templates/cv/slate-orange/icons/time-management.svg @@ -0,0 +1 @@ + \ No newline at end of file