From 2617b6ea3bb0b69d38c8ee6951b7dbc39cbc149f Mon Sep 17 00:00:00 2001 From: DemchaAV Date: Mon, 31 Aug 2026 19:04:21 +0100 Subject: [PATCH] feat(templates): add the Violet Grid banded CV preset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A one-page sheet with no page-level grid at all: a two-tone name beside the contact list, three opening lines, a six-up grid of marked skills divided by dotted rules, a strip of tools on inline discs, the roles held on a dated timeline whose dates sit outside the rail, the projects behind tinted tiles, education and languages side by side, and a tinted band closing on a quotation. Every split is local to one band, and none of the four knows about the others — which is why every horizontal arrangement is either a top-level row or a table and none of them nests: a row cannot sit inside a row's cell. Three marks are relationships rather than lengths. A section rule starts where its heading ends because it is a weighted column taking what an auto column leaves; the timeline rail is the left border of every entry but the last, so consecutive entries butt into one line that stops at the final marker; and a project's hairline is its copy's left border, so it is exactly as tall as the copy. None has to be re-measured when the content changes. Unlike its ported siblings this sheet flows: each experience entry is held together, so a longer CV runs onto a second page rather than cutting a role in half. 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 1,882 of 2,173,720 pixels. Guarded by a smoke test, an exact layout snapshot and a pixel-parity gate; the examples showcase gains `cv-violet-grid-v2`. --- CHANGELOG.md | 28 + assets/readme/examples/cv-violet-grid-v2.pdf | Bin 0 -> 45165 bytes .../demcha/examples/GenerateAllExamples.java | 2 + .../examples/support/ShowcaseMetadata.java | 1 + .../support/VioletGridSampleData.java | 224 + .../templates/cv/v2/VioletGridExample.java | 51 + .../cv/presets/VioletGridFixtures.java | 222 + .../presets/VioletGridLayoutSnapshotTest.java | 32 + .../cv/presets/VioletGridSmokeTest.java | 266 ++ .../presets/VioletGridVisualParityTest.java | 41 + .../cv-v2/violet_grid_layout.json | 4217 +++++++++++++++++ .../cv-v2-layered/violet_grid-page-0.png | Bin 0 -> 139076 bytes .../templates/cv/presets/VioletGrid.java | 229 + .../templates/cv/presets/VioletGridBody.java | 342 ++ .../cv/presets/VioletGridClosing.java | 466 ++ .../templates/cv/presets/VioletGridIcons.java | 112 + .../cv/presets/VioletGridMasthead.java | 214 + .../cv/presets/VioletGridStyles.java | 421 ++ .../cv/presets/VioletGridWidgets.java | 147 + .../cv/violet-grid/icons/design-systems.svg | 1 + .../templates/cv/violet-grid/icons/email.svg | 1 + .../cv/violet-grid/icons/graduation.svg | 1 + .../icons/information-architecture.svg | 1 + .../cv/violet-grid/icons/linkedin.svg | 1 + .../cv/violet-grid/icons/location.svg | 1 + .../templates/cv/violet-grid/icons/phone.svg | 1 + .../cv/violet-grid/icons/project-health.svg | 1 + .../cv/violet-grid/icons/project-wallet.svg | 1 + .../cv/violet-grid/icons/prototyping.svg | 1 + .../templates/cv/violet-grid/icons/quote.svg | 1 + .../violet-grid/icons/usability-testing.svg | 1 + .../cv/violet-grid/icons/ux-research.svg | 1 + .../cv/violet-grid/icons/website.svg | 1 + .../cv/violet-grid/icons/wireframing.svg | 1 + 34 files changed, 7030 insertions(+) create mode 100644 assets/readme/examples/cv-violet-grid-v2.pdf create mode 100644 examples/src/main/java/com/demcha/examples/support/VioletGridSampleData.java create mode 100644 examples/src/main/java/com/demcha/examples/templates/cv/v2/VioletGridExample.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridFixtures.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridLayoutSnapshotTest.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridSmokeTest.java create mode 100644 qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridVisualParityTest.java create mode 100644 qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/violet_grid_layout.json create mode 100644 qa/src/test/resources/visual-baselines/cv-v2-layered/violet_grid-page-0.png create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGrid.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridBody.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridClosing.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridIcons.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridMasthead.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridStyles.java create mode 100644 templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridWidgets.java create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/design-systems.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/email.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/graduation.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/information-architecture.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/linkedin.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/location.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/phone.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/project-health.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/project-wallet.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/prototyping.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/quote.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/usability-testing.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/ux-research.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/website.svg create mode 100644 templates/src/main/resources/templates/cv/violet-grid/icons/wireframing.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 32a558537..26aee1bef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -97,6 +97,34 @@ follow semantic versioning; release dates are ISO 8601. ### Templates +- **A banded single-column CV preset: `VioletGrid`.** A one-page sheet with no page-level + grid at all: a two-tone name beside the contact list, three opening lines, a six-up + grid of marked skills divided by dotted rules, a strip of tools on inline discs, the + roles held on a dated timeline whose dates sit outside the rail, the projects behind + tinted tiles, education and languages side by side, and a tinted band closing on a + quotation. Ships as `cv.presets.VioletGrid` on the existing `CvDocument` model, + porting the rendered layout of a published standalone template; like `SlateOrange` it + reads a rated language's wording from `CvSkill.note`. Every split is local to one + band — the masthead splits where the contact marks begin, the timeline into dates, + rail and content, a project into tile and copy, the credentials into two halves — and + none of the four knows about the others, which is why every horizontal arrangement is + either a top-level row or a table and none of them nests. Three marks are + relationships rather than lengths: a section rule starts where its heading ends + because it is a weighted column taking what an auto column leaves; the timeline rail + is the left border of every entry but the last, so consecutive entries butt into one + line; and a project's hairline is its copy's left border, so it is exactly as tall as + the copy. Seven berths reach their sections by title, including a quotation berth + whose body is drawn and whose title is not. Unlike its ported siblings this sheet + flows: each experience entry is held together, so a longer CV runs onto a second page + rather than cutting a role in half. 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 1 882 of 2 173 720 pixels. Guarded by a smoke test (including the + unknown-mark data error, a skill with no mark, the two-tone name, the quotation's + title staying off the sheet, the link targets on every kind of title, an identity with + no links, a document with nothing but an identity, and the run onto a second page), an + exact layout snapshot and a pixel-parity gate; the examples showcase gains + `cv-violet-grid-v2`. + - **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 diff --git a/assets/readme/examples/cv-violet-grid-v2.pdf b/assets/readme/examples/cv-violet-grid-v2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..eb94465c65ee4028c35f3d3c3274b9a27e91ceea GIT binary patch literal 45165 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 tags, String codeUrl 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"); + cv("cv-violet-grid-v2", "VioletGridExample", "Violet Grid", "Single-column sheet in bands: a two-tone name beside the contact list, a six-up grid of marked skills on dotted rules, a tools strip, a dated timeline, tinted project tiles and a closing quotation.", "single-column", "grid", "violet"); // ===== 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/VioletGridSampleData.java b/examples/src/main/java/com/demcha/examples/support/VioletGridSampleData.java new file mode 100644 index 000000000..3266599a1 --- /dev/null +++ b/examples/src/main/java/com/demcha/examples/support/VioletGridSampleData.java @@ -0,0 +1,224 @@ +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 Violet Grid CV example. + * + *

The sample is the preset's reference content: a one-page CV with five + * contact lines including two links, three opening lines, six marked skills, + * eleven tools, three roles, two projects, a degree, three rated languages + * and the closing quotation.

+ * + *

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

+ */ +public final class VioletGridSampleData { + + /** The break a body stacks its lines on. */ + private static final String NEWLINE = String.valueOf((char) 10); + + private VioletGridSampleData() { + } + + /** The single-page reference CV. */ + public static CvDocument sample() { + List placements = new ArrayList<>(); + placements.add(new CvDocument.Placement(Slot.MAIN, summary())); + placements.add(new CvDocument.Placement(Slot.MAIN, skills())); + placements.add(new CvDocument.Placement(Slot.MAIN, tools())); + placements.add(new CvDocument.Placement(Slot.MAIN, experience())); + placements.add(new CvDocument.Placement(Slot.MAIN, projects())); + placements.add(new CvDocument.Placement(Slot.FOOTER, education())); + placements.add(new CvDocument.Placement(Slot.FOOTER, languages())); + placements.add(new CvDocument.Placement(Slot.FOOTER, quote())); + return new CvDocument(identity(), placements); + } + + private static CvIdentity identity() { + return new CvIdentity( + CvName.of("SOFIA", "MARTINEZ"), + "UX / UI DESIGNER", + new Contact("+1 (415) 555-7842", + "sofia.martinez.design@gmail.com", + "San Francisco, CA, USA"), + List.of( + new Link("sofiamartinez.design", "https://sofiamartinez.design"), + new Link("LinkedIn", "https://www.linkedin.com/in/sofia-martinez-ux")), + Optional.empty()); + } + + /** The opening lines, set as written rather than wrapped. */ + private static ParagraphSection summary() { + return new ParagraphSection("SUMMARY", String.join(NEWLINE, + "User-centered designer with 5+ years of experience " + + "crafting intuitive digital experiences for web and " + + "mobile products.", + "I combine research, design thinking, and visual design " + + "to solve complex problems and deliver accessible, " + + "elegant solutions.", + "Passionate about collaborating with cross-functional " + + "teams to create products that delight users and drive " + + "business impact.")); + } + + /** The six-up grid: a mark, a label and a description each. */ + private static EntriesSection skills() { + return new EntriesSection("DESIGN SKILLS", List.of( + CvEntry.builder("UX RESEARCH") + .icon("ux-research") + .body("User interviews, surveys, personas, journey maps, " + + "competitive analysis") + .build(), + CvEntry.builder("INFORMATION ARCHITECTURE") + .icon("information-architecture") + .body("Sitemaps, user flows, card sorting, content strategy") + .build(), + CvEntry.builder("WIREFRAMING") + .icon("wireframing") + .body("Low to high-fidelity wireframes, layout design, " + + "interaction flows") + .build(), + CvEntry.builder("PROTOTYPING") + .icon("prototyping") + .body("Interactive prototypes, microinteractions, transitions") + .build(), + CvEntry.builder("USABILITY TESTING") + .icon("usability-testing") + .body("Test planning, usability tests, heuristic evaluation, " + + "insights & iteration") + .build(), + CvEntry.builder("DESIGN SYSTEMS") + .icon("design-systems") + .body("Component libraries, design tokens, pattern " + + "documentation") + .build())); + } + + /** The tools strip — names without levels. */ + private static SkillsSection tools() { + List entries = new ArrayList<>(); + for (String name : new String[] { + "Figma", "FigJam", "Adobe XD", "Sketch", "Miro", "Notion", "Jira", "Slack", "Maze", "Hotjar", "Airtable"}) { + entries.add(CvSkill.of(name)); + } + return new SkillsSection("TOOLS", + List.of(new SkillGroup("TOOLS", entries))); + } + + /** The roles held, each a headline over its bullets. */ + private static EntriesSection experience() { + return new EntriesSection("EXPERIENCE", List.of( + CvEntry.builder("Senior UX/UI Designer") + .subtitle("NovaFin (FinTech Startup)") + .place("San Francisco, CA") + .date("2022 - Present") + .body(String.join(NEWLINE, + "Led end-to-end design for a personal finance platform, " + + "from discovery to launch, improving task success rate by " + + "32%.", + "Conducted user research, built personas and journey " + + "maps, and translated insights into clear product " + + "opportunities.", + "Designed wireframes, prototypes, and high-fidelity " + + "interfaces for web and mobile using Figma.", + "Established and maintained a scalable design system, " + + "increasing design consistency and development speed.", + "Collaborated with product managers, engineers, and data " + + "analysts in an agile environment.")) + .build(), + CvEntry.builder("UX Designer") + .subtitle("BrightHealth (HealthTech)") + .place("San Francisco, CA") + .date("2020 - 2022") + .body(String.join(NEWLINE, + "Redesigned patient portal experience, reducing support " + + "tickets by 28% and improving user satisfaction.", + "Planned and facilitated usability tests and synthesized " + + "findings to drive iterative improvements.", + "Partnered with engineers to ensure feasible solutions " + + "and pixel-perfect implementation.", + "Created reusable components and style guides to support " + + "a cohesive cross-platform experience.")) + .build(), + CvEntry.builder("Junior UX/UI Designer") + .subtitle("Lumen Digital Agency") + .place("Austin, TX") + .date("2018 - 2020") + .body(String.join(NEWLINE, + "Supported discovery workshops, user flows, and " + + "wireframes for clients across e-commerce and SaaS.", + "Designed responsive websites and landing pages following " + + "best practices in accessibility and usability.", + "Collaborated with copywriters and developers to deliver " + + "high-quality, user-centered solutions.")) + .build())); + } + + /** The projects, each behind its tinted tile. */ + private static EntriesSection projects() { + return new EntriesSection("SELECTED PROJECTS", List.of( + CvEntry.builder("NovaFin Mobile App") + .subtitle("Personal Finance Management") + .date("2023") + .icon("project-wallet") + .body("Led UX/UI design for budgeting, goal tracking, and " + + "insights features. Conducted user interviews and " + + "usability tests that informed a simplified navigation " + + "and data visualization. Resulted in 32% improvement in " + + "task success rate and 22% increase in weekly active " + + "users.") + .build(), + CvEntry.builder("BrightHealth Patient Portal") + .subtitle("Healthcare Platform Redesign") + .date("2021") + .icon("project-health") + .body("Redesigned key patient flows including appointment " + + "scheduling, test results, and messaging. Created a new " + + "design system and component library used across web and " + + "mobile. Reduced support tickets by 28%.") + .build())); + } + + /** The degree, with the place and the years on its third line. */ + private static EntriesSection education() { + return new EntriesSection("EDUCATION", List.of( + CvEntry.builder("Bachelor of Fine Arts in Graphic Design") + .subtitle("California College of the Arts") + .place("San Francisco, CA") + .date("2014 - 2018") + .icon("graduation") + .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", 1.0, "Native"), + CvSkill.of("Portuguese", 0.6, "Conversational"))))); + } + + /** The closing line. Its title names the berth and is not drawn. */ + private static ParagraphSection quote() { + return new ParagraphSection("QUOTE", + "I design with empathy, iterate with purpose, and " + + "collaborate to build products people love."); + } +} diff --git a/examples/src/main/java/com/demcha/examples/templates/cv/v2/VioletGridExample.java b/examples/src/main/java/com/demcha/examples/templates/cv/v2/VioletGridExample.java new file mode 100644 index 000000000..646ab9a06 --- /dev/null +++ b/examples/src/main/java/com/demcha/examples/templates/cv/v2/VioletGridExample.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.VioletGrid; +import com.demcha.examples.support.ExampleOutputPaths; +import com.demcha.examples.support.VioletGridSampleData; + +import java.nio.file.Path; + +/** + * Renders the layered {@code cv.v2} Violet Grid preset against the design + * sample. + * + *

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

+ * + *

The preset owns its page geometry — every length is a share of the + * design's own grid — so the session starts unconfigured.

+ */ +public final class VioletGridExample { + + private VioletGridExample() { + } + + /** + * @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-violet-grid-v2.pdf"); + CvDocument doc = VioletGridSampleData.sample(); + DocumentTemplate template = VioletGrid.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/VioletGridFixtures.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridFixtures.java new file mode 100644 index 000000000..88876cecc --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridFixtures.java @@ -0,0 +1,222 @@ +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 VioletGrid} 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 VioletGridFixtures { + + /** The break a body stacks its lines on. */ + private static final String NEWLINE = String.valueOf((char) 10); + + private VioletGridFixtures() { + } + + /** + * The canonical one-page CV — five contact lines including two links, + * three opening lines, six marked skills, eleven tools, three roles, two + * projects, a degree, three rated languages and the closing quotation. + */ + static CvDocument canonicalCv() { + List placements = new ArrayList<>(); + placements.add(new CvDocument.Placement(Slot.MAIN, summary())); + placements.add(new CvDocument.Placement(Slot.MAIN, skills())); + placements.add(new CvDocument.Placement(Slot.MAIN, tools())); + placements.add(new CvDocument.Placement(Slot.MAIN, experience())); + placements.add(new CvDocument.Placement(Slot.MAIN, projects())); + placements.add(new CvDocument.Placement(Slot.FOOTER, education())); + placements.add(new CvDocument.Placement(Slot.FOOTER, languages())); + placements.add(new CvDocument.Placement(Slot.FOOTER, quote())); + return new CvDocument(identity(), placements); + } + + static CvIdentity identity() { + return new CvIdentity( + CvName.of("SOFIA", "MARTINEZ"), + "UX / UI DESIGNER", + new Contact("+1 (415) 555-7842", + "sofia.martinez.design@gmail.com", + "San Francisco, CA, USA"), + List.of( + new Link("sofiamartinez.design", "https://sofiamartinez.design"), + new Link("LinkedIn", "https://www.linkedin.com/in/sofia-martinez-ux")), + Optional.empty()); + } + + /** The opening lines, set as written rather than wrapped. */ + static ParagraphSection summary() { + return new ParagraphSection("SUMMARY", String.join(NEWLINE, + "User-centered designer with 5+ years of experience " + + "crafting intuitive digital experiences for web and " + + "mobile products.", + "I combine research, design thinking, and visual design " + + "to solve complex problems and deliver accessible, " + + "elegant solutions.", + "Passionate about collaborating with cross-functional " + + "teams to create products that delight users and drive " + + "business impact.")); + } + + /** The six-up grid: a mark, a label and a description each. */ + static EntriesSection skills() { + return new EntriesSection("DESIGN SKILLS", List.of( + CvEntry.builder("UX RESEARCH") + .icon("ux-research") + .body("User interviews, surveys, personas, journey maps, " + + "competitive analysis") + .build(), + CvEntry.builder("INFORMATION ARCHITECTURE") + .icon("information-architecture") + .body("Sitemaps, user flows, card sorting, content strategy") + .build(), + CvEntry.builder("WIREFRAMING") + .icon("wireframing") + .body("Low to high-fidelity wireframes, layout design, " + + "interaction flows") + .build(), + CvEntry.builder("PROTOTYPING") + .icon("prototyping") + .body("Interactive prototypes, microinteractions, transitions") + .build(), + CvEntry.builder("USABILITY TESTING") + .icon("usability-testing") + .body("Test planning, usability tests, heuristic evaluation, " + + "insights & iteration") + .build(), + CvEntry.builder("DESIGN SYSTEMS") + .icon("design-systems") + .body("Component libraries, design tokens, pattern " + + "documentation") + .build())); + } + + /** The tools strip — names without levels. */ + static SkillsSection tools() { + List entries = new ArrayList<>(); + for (String name : new String[] { + "Figma", "FigJam", "Adobe XD", "Sketch", "Miro", "Notion", "Jira", "Slack", "Maze", "Hotjar", "Airtable"}) { + entries.add(CvSkill.of(name)); + } + return new SkillsSection("TOOLS", + List.of(new SkillGroup("TOOLS", entries))); + } + + /** The roles held, each a headline over its bullets. */ + static EntriesSection experience() { + return new EntriesSection("EXPERIENCE", List.of( + CvEntry.builder("Senior UX/UI Designer") + .subtitle("NovaFin (FinTech Startup)") + .place("San Francisco, CA") + .date("2022 - Present") + .body(String.join(NEWLINE, + "Led end-to-end design for a personal finance platform, " + + "from discovery to launch, improving task success rate by " + + "32%.", + "Conducted user research, built personas and journey " + + "maps, and translated insights into clear product " + + "opportunities.", + "Designed wireframes, prototypes, and high-fidelity " + + "interfaces for web and mobile using Figma.", + "Established and maintained a scalable design system, " + + "increasing design consistency and development speed.", + "Collaborated with product managers, engineers, and data " + + "analysts in an agile environment.")) + .build(), + CvEntry.builder("UX Designer") + .subtitle("BrightHealth (HealthTech)") + .place("San Francisco, CA") + .date("2020 - 2022") + .body(String.join(NEWLINE, + "Redesigned patient portal experience, reducing support " + + "tickets by 28% and improving user satisfaction.", + "Planned and facilitated usability tests and synthesized " + + "findings to drive iterative improvements.", + "Partnered with engineers to ensure feasible solutions " + + "and pixel-perfect implementation.", + "Created reusable components and style guides to support " + + "a cohesive cross-platform experience.")) + .build(), + CvEntry.builder("Junior UX/UI Designer") + .subtitle("Lumen Digital Agency") + .place("Austin, TX") + .date("2018 - 2020") + .body(String.join(NEWLINE, + "Supported discovery workshops, user flows, and " + + "wireframes for clients across e-commerce and SaaS.", + "Designed responsive websites and landing pages following " + + "best practices in accessibility and usability.", + "Collaborated with copywriters and developers to deliver " + + "high-quality, user-centered solutions.")) + .build())); + } + + /** The projects, each behind its tinted tile. */ + static EntriesSection projects() { + return new EntriesSection("SELECTED PROJECTS", List.of( + CvEntry.builder("NovaFin Mobile App") + .subtitle("Personal Finance Management") + .date("2023") + .icon("project-wallet") + .body("Led UX/UI design for budgeting, goal tracking, and " + + "insights features. Conducted user interviews and " + + "usability tests that informed a simplified navigation " + + "and data visualization. Resulted in 32% improvement in " + + "task success rate and 22% increase in weekly active " + + "users.") + .build(), + CvEntry.builder("BrightHealth Patient Portal") + .subtitle("Healthcare Platform Redesign") + .date("2021") + .icon("project-health") + .body("Redesigned key patient flows including appointment " + + "scheduling, test results, and messaging. Created a new " + + "design system and component library used across web and " + + "mobile. Reduced support tickets by 28%.") + .build())); + } + + /** The degree, with the place and the years on its third line. */ + static EntriesSection education() { + return new EntriesSection("EDUCATION", List.of( + CvEntry.builder("Bachelor of Fine Arts in Graphic Design") + .subtitle("California College of the Arts") + .place("San Francisco, CA") + .date("2014 - 2018") + .icon("graduation") + .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", 1.0, "Native"), + CvSkill.of("Portuguese", 0.6, "Conversational"))))); + } + + /** The closing line. Its title names the berth and is not drawn. */ + static ParagraphSection quote() { + return new ParagraphSection("QUOTE", + "I design with empathy, iterate with purpose, and " + + "collaborate to build products people love."); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridLayoutSnapshotTest.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridLayoutSnapshotTest.java new file mode 100644 index 000000000..c47638b85 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridLayoutSnapshotTest.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 VioletGrid} — 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 VioletGridLayoutSnapshotTest { + + @Test + void canonicalCvMatchesLayoutSnapshot() throws Exception { + try (DocumentSession session = GraphCompose.document().create()) { + VioletGrid.create().compose(session, VioletGridFixtures.canonicalCv()); + assertThat(session.layoutSnapshot().totalPages()).isEqualTo(1); + TemplateTestSupport.assertCanonicalSnapshot( + session, "violet_grid_layout", "cv-v2"); + } + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridSmokeTest.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridSmokeTest.java new file mode 100644 index 000000000..f6a36a2cd --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridSmokeTest.java @@ -0,0 +1,266 @@ +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.EntriesSection; +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.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Smoke test for {@link VioletGrid} — proves the preset renders a + * {@link CvDocument} end-to-end with its packaged marks, sets the two-tone + * name from the structured one, draws only the quotation's body, reports an + * unknown mark as a data error, 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 VioletGridSmokeTest { + + 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()) { + VioletGrid.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); + } + } + + /** + * The text with its spaces removed. The name and every heading are + * letter-spaced with real space runs, so what is being asserted is the + * wording, not the tracking. + */ + private static String compact(String text) { + return text.replaceAll("(?U)\\s", ""); + } + + 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 : VioletGridFixtures.canonicalCv().placements()) { + if (placement.section().title().equals(replacedTitle)) { + placements.add(new CvDocument.Placement(slot, replacement)); + } else { + placements.add(placement); + } + } + return new CvDocument(VioletGridFixtures.identity(), placements); + } + + @Test + void exposesStableIdentity() { + DocumentTemplate template = VioletGrid.create(); + assertThat(template.id()).isEqualTo(VioletGrid.ID); + assertThat(template.displayName()).isEqualTo(VioletGrid.DISPLAY_NAME); + } + + @Test + void rendersCanonicalCvWithPackagedMarks() throws Exception { + render(VioletGridFixtures.canonicalCv()); + } + + @Test + void canonicalRenderCarriesEveryBandsText() throws Exception { + String text = textOf(render(VioletGridFixtures.canonicalCv())); + assertThat(text) + .contains("sofia.martinez.design@gmail.com") + .contains("User-centered designer") + .contains("Figma") + .contains("NovaFin (FinTech Startup)") + .contains("NovaFin Mobile App") + .contains("Bachelor of Fine Arts in Graphic Design") + .contains("Conversational") + .contains("I design with empathy"); + assertThat(compact(text)) + .contains("SOFIAMARTINEZ") + .contains("UX/UIDESIGNER") + .contains("DESIGNSKILLS") + .doesNotContain("QUOTE"); + } + + @Test + void theNameIsSetFromTheStructuredNameInTwoTones() throws Exception { + // Both names are runs of one paragraph, so the gap between them is a + // real word space; the two tones are what the design asks for. + String text = textOf(render(VioletGridFixtures.canonicalCv())); + assertThat(text.lines().map(String::strip).toList()) + .anyMatch(line -> line.contains("SOFIA") && line.contains("MARTINEZ")); + } + + @Test + void contactChannelsAndLinksAreClickable() throws Exception { + List targets = linkTargets(render(VioletGridFixtures.canonicalCv())); + assertThat(targets) + .contains("mailto:sofia.martinez.design@gmail.com") + .contains("tel:+14155557842") + .contains("https://sofiamartinez.design") + .contains("https://www.linkedin.com/in/sofia-martinez-ux"); + } + + @Test + void aLinkShowsItsLabelAndHidesItsAddress() throws Exception { + // The column draws the label, so its width is the same whatever the + // profile behind it is called; the address is reachable, not written. + byte[] pdfBytes = render(VioletGridFixtures.canonicalCv()); + assertThat(textOf(pdfBytes)) + .contains("LinkedIn") + .doesNotContain("linkedin.com/in/sofia-martinez-ux"); + assertThat(linkTargets(pdfBytes)) + .contains("https://www.linkedin.com/in/sofia-martinez-ux"); + } + + @Test + void aRoleAProjectAndADegreeBecomeLinksWhenTheirEntryCarriesOne() throws Exception { + List placements = new ArrayList<>(); + for (CvDocument.Placement placement : VioletGridFixtures.canonicalCv().placements()) { + placements.add(switch (placement.section().title()) { + case "EXPERIENCE" -> new CvDocument.Placement(Slot.MAIN, + new EntriesSection("EXPERIENCE", List.of( + CvEntry.builder("Senior UX/UI Designer") + .subtitle("NovaFin") + .place("San Francisco, CA") + .date("2022") + .link("https://example.test/novafin") + .body("Led end-to-end design.") + .build()))); + case "SELECTED PROJECTS" -> new CvDocument.Placement(Slot.MAIN, + new EntriesSection("SELECTED PROJECTS", List.of( + CvEntry.builder("NovaFin Mobile App") + .subtitle("Personal Finance") + .date("2023") + .icon("project-wallet") + .link("https://example.test/app") + .body("Led UX/UI design.") + .build()))); + case "EDUCATION" -> new CvDocument.Placement(Slot.FOOTER, + new EntriesSection("EDUCATION", List.of( + CvEntry.builder("Bachelor of Fine Arts") + .subtitle("California College of the Arts") + .place("San Francisco, CA") + .date("2014 - 2018") + .icon("graduation") + .link("https://example.test/cca") + .build()))); + default -> placement; + }); + } + + List targets = linkTargets( + render(new CvDocument(VioletGridFixtures.identity(), placements))); + assertThat(targets) + .contains("https://example.test/novafin") + .contains("https://example.test/app") + .contains("https://example.test/cca"); + } + + @Test + void anUnknownMarkIsReportedAsADataError() { + EntriesSection wrong = new EntriesSection("DESIGN SKILLS", List.of( + CvEntry.builder("Telepathy").icon("telescope").body("Reading minds.").build())); + + assertThatThrownBy(() -> render(withSection(Slot.MAIN, wrong, "DESIGN SKILLS"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("telescope") + .hasMessageContaining("wireframing"); + } + + @Test + void aSkillWithoutAMarkIsDrawnWithoutOne() throws Exception { + EntriesSection unmarked = new EntriesSection("DESIGN SKILLS", List.of( + CvEntry.builder("UX RESEARCH").body("User interviews and surveys.").build())); + + String text = textOf(render(withSection(Slot.MAIN, unmarked, "DESIGN SKILLS"))); + // The description wraps inside its narrow column, so a fragment + // of one line is what is asserted. + assertThat(text).contains("User interviews and"); + } + + @Test + void aDocumentWithNothingButAnIdentityStillRenders() throws Exception { + // Every berth empty: the name, the discipline line and its rule, and + // nothing else on the sheet. + render(new CvDocument(VioletGridFixtures.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 aLongerCvRunsOntoASecondPageRatherThanLosingARole() throws Exception { + // The page is a stack of bands, so more content than the design holds + // runs over; each entry is held together, so a role is never cut in two. + List many = new ArrayList<>(); + for (int index = 0; index < 8; index++) { + many.add(CvEntry.builder("Senior UX/UI Designer " + index) + .subtitle("NovaFin") + .place("San Francisco, CA") + .date("2022") + .body("Led end-to-end design for a personal finance platform.") + .build()); + } + + try (DocumentSession session = GraphCompose.document().create()) { + VioletGrid.create().compose(session, withSection(Slot.MAIN, + new EntriesSection("EXPERIENCE", many), "EXPERIENCE")); + assertThat(session.layoutSnapshot().totalPages()).isGreaterThan(1); + } + String text = textOf(render(withSection(Slot.MAIN, + new EntriesSection("EXPERIENCE", many), "EXPERIENCE"))); + assertThat(text).contains("Senior UX/UI Designer 7"); + } +} diff --git a/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridVisualParityTest.java b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridVisualParityTest.java new file mode 100644 index 000000000..9645814b1 --- /dev/null +++ b/qa/src/test/java/com/demcha/compose/document/templates/cv/presets/VioletGridVisualParityTest.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 VioletGrid} — 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 VioletGridVisualParityTest { + + 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()) { + VioletGrid.create().compose(document, VioletGridFixtures.canonicalCv()); + pdfBytes = document.toPdfBytes(); + } + + PdfVisualRegression.standard() + .baselineRoot(BASELINE_ROOT) + .perPixelTolerance(PER_PIXEL_TOLERANCE) + .mismatchedPixelBudget(PIXEL_DIFF_BUDGET) + .assertMatchesBaseline("violet_grid", pdfBytes); + } +} diff --git a/qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/violet_grid_layout.json b/qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/violet_grid_layout.json new file mode 100644 index 000000000..34cb04f2c --- /dev/null +++ b/qa/src/test/resources/layout-snapshots/canonical-templates/cv-v2/violet_grid_layout.json @@ -0,0 +1,4217 @@ +{ + "formatVersion" : "2.0", + "canvas" : { + "pageWidth" : 595.276, + "pageHeight" : 841.89, + "innerWidth" : 535.466, + "innerHeight" : 818.192, + "margin" : { + "top" : 13.542, + "right" : 29.905, + "bottom" : 10.156, + "left" : 29.905 + } + }, + "totalPages" : 1, + "nodes" : [ { + "path" : "VioletGridCv[0]", + "entityName" : "VioletGridCv", + "entityKind" : "ContainerNode", + "parentPath" : null, + "childIndex" : 0, + "depth" : 1, + "layer" : 1, + "computedX" : 29.905, + "computedY" : 10.348, + "placementX" : 29.905, + "placementY" : 10.348, + "placementWidth" : 535.466, + "placementHeight" : 818.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 818.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" : "VioletGridCv[0]/Header[0]", + "entityName" : "Header", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 0, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 734.92, + "placementX" : 29.905, + "placementY" : 734.92, + "placementWidth" : 535.466, + "placementHeight" : 93.428, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 93.428, + "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" : "VioletGridCv[0]/Header[0]/Identity[0]", + "entityName" : "Identity", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Header[0]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 739.279, + "placementX" : 29.905, + "placementY" : 739.279, + "placementWidth" : 284.374, + "placementHeight" : 89.069, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 284.374, + "contentHeight" : 89.069, + "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" : "VioletGridCv[0]/Header[0]/Identity[0]/Name[0]", + "entityName" : "Name", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Identity[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 775.002, + "placementX" : 29.905, + "placementY" : 775.002, + "placementWidth" : 284.374, + "placementHeight" : 53.346, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 284.374, + "contentHeight" : 53.346, + "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" : "VioletGridCv[0]/Header[0]/Identity[0]/Discipline[1]", + "entityName" : "Discipline", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Identity[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 754.683, + "placementX" : 29.905, + "placementY" : 754.683, + "placementWidth" : 157.277, + "placementHeight" : 20.319, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 157.277, + "contentHeight" : 20.319, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 13.147, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Header[0]/Identity[0]/IdentityRule[2]", + "entityName" : "IdentityRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Identity[0]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 739.279, + "placementX" : 29.905, + "placementY" : 739.279, + "placementWidth" : 39.497, + "placementHeight" : 2.257, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 39.497, + "contentHeight" : 2.257, + "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" : "VioletGridCv[0]/Header[0]/Contact[1]", + "entityName" : "Contact", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Header[0]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 398.355, + "computedY" : 734.92, + "placementX" : 398.355, + "placementY" : 734.92, + "placementWidth" : 152.21, + "placementHeight" : 93.428, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 152.21, + "contentHeight" : 93.428, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 4.514, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Header[0]/Contact[1]/Contact_0_email[0]", + "entityName" : "Contact_0_email", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Contact[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 398.355, + "computedY" : 812.334, + "placementX" : 398.355, + "placementY" : 812.334, + "placementWidth" : 152.21, + "placementHeight" : 11.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 152.21, + "contentHeight" : 11.5, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 7.854, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Header[0]/Contact[1]/Contact_1_phone[1]", + "entityName" : "Contact_1_phone", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Contact[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 398.355, + "computedY" : 792.98, + "placementX" : 398.355, + "placementY" : 792.98, + "placementWidth" : 97.746, + "placementHeight" : 11.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 97.746, + "contentHeight" : 11.5, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 7.854, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Header[0]/Contact[1]/Contact_2_location[2]", + "entityName" : "Contact_2_location", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Contact[1]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 398.355, + "computedY" : 773.627, + "placementX" : 398.355, + "placementY" : 773.627, + "placementWidth" : 114.927, + "placementHeight" : 11.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 114.927, + "contentHeight" : 11.5, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 7.854, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Header[0]/Contact[1]/Contact_3_website[3]", + "entityName" : "Contact_3_website", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Contact[1]", + "childIndex" : 3, + "depth" : 4, + "layer" : 4, + "computedX" : 398.355, + "computedY" : 754.273, + "placementX" : 398.355, + "placementY" : 754.273, + "placementWidth" : 103.158, + "placementHeight" : 11.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 103.158, + "contentHeight" : 11.5, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 7.854, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Header[0]/Contact[1]/Contact_4_linkedin[4]", + "entityName" : "Contact_4_linkedin", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Header[0]/Contact[1]", + "childIndex" : 4, + "depth" : 4, + "layer" : 4, + "computedX" : 398.355, + "computedY" : 734.92, + "placementX" : 398.355, + "placementY" : 734.92, + "placementWidth" : 56.382, + "placementHeight" : 11.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 56.382, + "contentHeight" : 11.5, + "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" : "VioletGridCv[0]/SummaryLine_0[1]", + "entityName" : "SummaryLine_0", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 1, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 709.078, + "placementX" : 29.905, + "placementY" : 709.078, + "placementWidth" : 482.062, + "placementHeight" : 11.172, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 482.062, + "contentHeight" : 11.172, + "margin" : { + "top" : 14.67, + "right" : 0.0, + "bottom" : 1.241, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SummaryLine_1[2]", + "entityName" : "SummaryLine_1", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 2, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 696.664, + "placementX" : 29.905, + "placementY" : 696.664, + "placementWidth" : 495.804, + "placementHeight" : 11.172, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 495.804, + "contentHeight" : 11.172, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 1.241, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SummaryLine_2[3]", + "entityName" : "SummaryLine_2", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 3, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 684.251, + "placementX" : 29.905, + "placementY" : 684.251, + "placementWidth" : 501.018, + "placementHeight" : 11.172, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 501.018, + "contentHeight" : 11.172, + "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" : "VioletGridCv[0]/SkillsHeading[4]", + "entityName" : "SkillsHeading", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 4, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 650.396, + "placementX" : 29.905, + "placementY" : 650.396, + "placementWidth" : 535.466, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 14.783, + "margin" : { + "top" : 19.071, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillsHeading[4]/SkillsHeadingText[0]", + "entityName" : "SkillsHeadingText", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillsHeading[4]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 650.396, + "placementX" : 29.905, + "placementY" : 650.396, + "placementWidth" : 76.844, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 76.844, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/SkillsHeading[4]/SkillsHeadingText[0]/SkillsHeadingLabel[0]", + "entityName" : "SkillsHeadingLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillsHeading[4]/SkillsHeadingText[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 650.396, + "placementX" : 29.905, + "placementY" : 650.396, + "placementWidth" : 76.844, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 76.844, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/SkillsHeading[4]/SkillsHeadingRule[1]", + "entityName" : "SkillsHeadingRule", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillsHeading[4]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 106.749, + "computedY" : 656.562, + "placementX" : 106.749, + "placementY" : 656.562, + "placementWidth" : 458.622, + "placementHeight" : 8.617, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 458.622, + "contentHeight" : 8.617, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 7.617, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.285 + } + }, { + "path" : "VioletGridCv[0]/SkillsHeading[4]/SkillsHeadingRule[1]/SkillsHeadingRuleLine[0]", + "entityName" : "SkillsHeadingRuleLine", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/SkillsHeading[4]/SkillsHeadingRule[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 118.034, + "computedY" : 656.562, + "placementX" : 118.034, + "placementY" : 656.562, + "placementWidth" : 447.337, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 447.337, + "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" : "VioletGridCv[0]/SkillGrid[5]", + "entityName" : "SkillGrid", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 5, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 562.656, + "placementX" : 29.905, + "placementY" : 562.656, + "placementWidth" : 535.466, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 76.737, + "margin" : { + "top" : 11.003, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]", + "entityName" : "Skill_0", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 569.965, + "placementX" : 29.905, + "placementY" : 569.965, + "placementWidth" : 88.304, + "placementHeight" : 69.429, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 88.304, + "contentHeight" : 69.429, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 6.207, + "bottom" : 0.0, + "left" : 6.207 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 36.112, + "computedY" : 618.893, + "placementX" : 36.112, + "placementY" : 618.893, + "placementWidth" : 75.891, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]/Align[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 63.807, + "computedY" : 618.893, + "placementX" : 63.807, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 63.807, + "computedY" : 618.893, + "placementX" : 63.807, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]/SkillLabel_0[1]", + "entityName" : "SkillLabel_0", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 36.112, + "computedY" : 601.283, + "placementX" : 36.112, + "placementY" : 601.283, + "placementWidth" : 75.891, + "placementHeight" : 7.793, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 7.793, + "margin" : { + "top" : 9.818, + "right" : 0.0, + "bottom" : 3.385, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]/SkillDescription_0[2]", + "entityName" : "SkillDescription_0", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_0[0]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 36.112, + "computedY" : 569.965, + "placementX" : 36.112, + "placementY" : 569.965, + "placementWidth" : 75.891, + "placementHeight" : 27.933, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 27.933, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 1.695, + "bottom" : 0.0, + "left" : 1.695 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_0[1]", + "entityName" : "SkillDivider_0", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 118.209, + "computedY" : 562.656, + "placementX" : 118.209, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_0[1]/SkillDividerRule[0]", + "entityName" : "SkillDividerRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_0[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 118.209, + "computedY" : 562.656, + "placementX" : 118.209, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]", + "entityName" : "Skill_1", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 2, + "depth" : 3, + "layer" : 3, + "computedX" : 119.337, + "computedY" : 580.121, + "placementX" : 119.337, + "placementY" : 580.121, + "placementWidth" : 88.304, + "placementHeight" : 59.272, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 88.304, + "contentHeight" : 59.272, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 6.207, + "bottom" : 0.0, + "left" : 6.207 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 125.544, + "computedY" : 618.893, + "placementX" : 125.544, + "placementY" : 618.893, + "placementWidth" : 75.891, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]/Align[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 153.239, + "computedY" : 618.893, + "placementX" : 153.239, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 153.239, + "computedY" : 618.893, + "placementX" : 153.239, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]/SkillLabel_1[1]", + "entityName" : "SkillLabel_1", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 125.544, + "computedY" : 601.283, + "placementX" : 125.544, + "placementY" : 601.283, + "placementWidth" : 75.891, + "placementHeight" : 7.793, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 7.793, + "margin" : { + "top" : 9.818, + "right" : 0.0, + "bottom" : 3.385, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]/SkillDescription_1[2]", + "entityName" : "SkillDescription_1", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_1[2]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 125.544, + "computedY" : 580.121, + "placementX" : 125.544, + "placementY" : 580.121, + "placementWidth" : 75.891, + "placementHeight" : 17.776, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 17.776, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 1.695, + "bottom" : 0.0, + "left" : 1.695 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_1[3]", + "entityName" : "SkillDivider_1", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 3, + "depth" : 3, + "layer" : 3, + "computedX" : 207.641, + "computedY" : 562.656, + "placementX" : 207.641, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_1[3]/SkillDividerRule[0]", + "entityName" : "SkillDividerRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_1[3]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 207.641, + "computedY" : 562.656, + "placementX" : 207.641, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]", + "entityName" : "Skill_2", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 4, + "depth" : 3, + "layer" : 3, + "computedX" : 208.77, + "computedY" : 569.965, + "placementX" : 208.77, + "placementY" : 569.965, + "placementWidth" : 88.304, + "placementHeight" : 69.429, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 88.304, + "contentHeight" : 69.429, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 6.207, + "bottom" : 0.0, + "left" : 6.207 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 214.976, + "computedY" : 618.893, + "placementX" : 214.976, + "placementY" : 618.893, + "placementWidth" : 75.891, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]/Align[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 242.672, + "computedY" : 618.893, + "placementX" : 242.672, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 242.672, + "computedY" : 618.893, + "placementX" : 242.672, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]/SkillLabel_2[1]", + "entityName" : "SkillLabel_2", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 214.976, + "computedY" : 601.283, + "placementX" : 214.976, + "placementY" : 601.283, + "placementWidth" : 75.891, + "placementHeight" : 7.793, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 7.793, + "margin" : { + "top" : 9.818, + "right" : 0.0, + "bottom" : 3.385, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]/SkillDescription_2[2]", + "entityName" : "SkillDescription_2", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_2[4]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 214.976, + "computedY" : 569.965, + "placementX" : 214.976, + "placementY" : 569.965, + "placementWidth" : 75.891, + "placementHeight" : 27.933, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 27.933, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 1.695, + "bottom" : 0.0, + "left" : 1.695 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_2[5]", + "entityName" : "SkillDivider_2", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 5, + "depth" : 3, + "layer" : 3, + "computedX" : 297.074, + "computedY" : 562.656, + "placementX" : 297.074, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_2[5]/SkillDividerRule[0]", + "entityName" : "SkillDividerRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_2[5]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 297.074, + "computedY" : 562.656, + "placementX" : 297.074, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]", + "entityName" : "Skill_3", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 6, + "depth" : 3, + "layer" : 3, + "computedX" : 298.202, + "computedY" : 569.965, + "placementX" : 298.202, + "placementY" : 569.965, + "placementWidth" : 88.304, + "placementHeight" : 69.429, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 88.304, + "contentHeight" : 69.429, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 6.207, + "bottom" : 0.0, + "left" : 6.207 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 304.409, + "computedY" : 618.893, + "placementX" : 304.409, + "placementY" : 618.893, + "placementWidth" : 75.891, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]/Align[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 332.104, + "computedY" : 618.893, + "placementX" : 332.104, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 332.104, + "computedY" : 618.893, + "placementX" : 332.104, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]/SkillLabel_3[1]", + "entityName" : "SkillLabel_3", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 304.409, + "computedY" : 601.283, + "placementX" : 304.409, + "placementY" : 601.283, + "placementWidth" : 75.891, + "placementHeight" : 7.793, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 7.793, + "margin" : { + "top" : 9.818, + "right" : 0.0, + "bottom" : 3.385, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]/SkillDescription_3[2]", + "entityName" : "SkillDescription_3", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_3[6]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 304.409, + "computedY" : 569.965, + "placementX" : 304.409, + "placementY" : 569.965, + "placementWidth" : 75.891, + "placementHeight" : 27.933, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 27.933, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 1.695, + "bottom" : 0.0, + "left" : 1.695 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_3[7]", + "entityName" : "SkillDivider_3", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 7, + "depth" : 3, + "layer" : 3, + "computedX" : 386.506, + "computedY" : 562.656, + "placementX" : 386.506, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_3[7]/SkillDividerRule[0]", + "entityName" : "SkillDividerRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_3[7]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 386.506, + "computedY" : 562.656, + "placementX" : 386.506, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]", + "entityName" : "Skill_4", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 8, + "depth" : 3, + "layer" : 3, + "computedX" : 387.634, + "computedY" : 569.965, + "placementX" : 387.634, + "placementY" : 569.965, + "placementWidth" : 88.304, + "placementHeight" : 69.429, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 88.304, + "contentHeight" : 69.429, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 6.207, + "bottom" : 0.0, + "left" : 6.207 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 393.841, + "computedY" : 618.893, + "placementX" : 393.841, + "placementY" : 618.893, + "placementWidth" : 75.891, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]/Align[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 421.536, + "computedY" : 618.893, + "placementX" : 421.536, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 421.536, + "computedY" : 618.893, + "placementX" : 421.536, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]/SkillLabel_4[1]", + "entityName" : "SkillLabel_4", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 393.841, + "computedY" : 601.283, + "placementX" : 393.841, + "placementY" : 601.283, + "placementWidth" : 75.891, + "placementHeight" : 7.793, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 7.793, + "margin" : { + "top" : 9.818, + "right" : 0.0, + "bottom" : 3.385, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]/SkillDescription_4[2]", + "entityName" : "SkillDescription_4", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_4[8]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 393.841, + "computedY" : 569.965, + "placementX" : 393.841, + "placementY" : 569.965, + "placementWidth" : 75.891, + "placementHeight" : 27.933, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 27.933, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 1.695, + "bottom" : 0.0, + "left" : 1.695 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_4[9]", + "entityName" : "SkillDivider_4", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 9, + "depth" : 3, + "layer" : 3, + "computedX" : 475.938, + "computedY" : 562.656, + "placementX" : 475.938, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_4[9]/SkillDividerRule[0]", + "entityName" : "SkillDividerRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/SkillDivider_4[9]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 475.938, + "computedY" : 562.656, + "placementX" : 475.938, + "placementY" : 562.656, + "placementWidth" : 1.128, + "placementHeight" : 76.737, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 1.128, + "contentHeight" : 76.737, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]", + "entityName" : "Skill_5", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]", + "childIndex" : 10, + "depth" : 3, + "layer" : 3, + "computedX" : 477.067, + "computedY" : 569.965, + "placementX" : 477.067, + "placementY" : 569.965, + "placementWidth" : 88.304, + "placementHeight" : 69.429, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 88.304, + "contentHeight" : 69.429, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 6.207, + "bottom" : 0.0, + "left" : 6.207 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]/Align[0]", + "entityName" : null, + "entityKind" : "Align", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 483.274, + "computedY" : 618.893, + "placementX" : 483.274, + "placementY" : 618.893, + "placementWidth" : 75.891, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]/Align[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]/Align[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 510.969, + "computedY" : 618.893, + "placementX" : 510.969, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]/Align[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]/Align[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 510.969, + "computedY" : 618.893, + "placementX" : 510.969, + "placementY" : 618.893, + "placementWidth" : 20.5, + "placementHeight" : 20.5, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 20.5, + "contentHeight" : 20.5, + "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" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]/SkillLabel_5[1]", + "entityName" : "SkillLabel_5", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 483.274, + "computedY" : 601.283, + "placementX" : 483.274, + "placementY" : 601.283, + "placementWidth" : 75.891, + "placementHeight" : 7.793, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 7.793, + "margin" : { + "top" : 9.818, + "right" : 0.0, + "bottom" : 3.385, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]/SkillDescription_5[2]", + "entityName" : "SkillDescription_5", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/SkillGrid[5]/Skill_5[10]", + "childIndex" : 2, + "depth" : 4, + "layer" : 4, + "computedX" : 483.274, + "computedY" : 569.965, + "placementX" : 483.274, + "placementY" : 569.965, + "placementWidth" : 75.891, + "placementHeight" : 27.933, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 75.891, + "contentHeight" : 27.933, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 1.695, + "bottom" : 0.0, + "left" : 1.695 + } + }, { + "path" : "VioletGridCv[0]/ToolsHeading[6]", + "entityName" : "ToolsHeading", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 6, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 532.469, + "placementX" : 29.905, + "placementY" : 532.469, + "placementWidth" : 535.466, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 14.783, + "margin" : { + "top" : 15.404, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/ToolsHeading[6]/ToolsHeadingText[0]", + "entityName" : "ToolsHeadingText", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ToolsHeading[6]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 532.469, + "placementX" : 29.905, + "placementY" : 532.469, + "placementWidth" : 34.064, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 34.064, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/ToolsHeading[6]/ToolsHeadingText[0]/ToolsHeadingLabel[0]", + "entityName" : "ToolsHeadingLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ToolsHeading[6]/ToolsHeadingText[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 532.469, + "placementX" : 29.905, + "placementY" : 532.469, + "placementWidth" : 34.064, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 34.064, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/ToolsHeading[6]/ToolsHeadingRule[1]", + "entityName" : "ToolsHeadingRule", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ToolsHeading[6]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 63.969, + "computedY" : 538.635, + "placementX" : 63.969, + "placementY" : 538.635, + "placementWidth" : 501.402, + "placementHeight" : 8.617, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 501.402, + "contentHeight" : 8.617, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 7.617, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.285 + } + }, { + "path" : "VioletGridCv[0]/ToolsHeading[6]/ToolsHeadingRule[1]/ToolsHeadingRuleLine[0]", + "entityName" : "ToolsHeadingRuleLine", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/ToolsHeading[6]/ToolsHeadingRule[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 75.254, + "computedY" : 538.635, + "placementX" : 75.254, + "placementY" : 538.635, + "placementWidth" : 490.117, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 490.117, + "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" : "VioletGridCv[0]/ToolsLine[7]", + "entityName" : "ToolsLine", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 7, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 512.186, + "placementX" : 29.905, + "placementY" : 512.186, + "placementWidth" : 528.641, + "placementHeight" : 9.732, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 528.641, + "contentHeight" : 9.732, + "margin" : { + "top" : 10.551, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/ExperienceHeading[8]", + "entityName" : "ExperienceHeading", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 8, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 477.259, + "placementX" : 29.905, + "placementY" : 477.259, + "placementWidth" : 535.466, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 14.783, + "margin" : { + "top" : 20.143, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/ExperienceHeading[8]/ExperienceHeadingText[0]", + "entityName" : "ExperienceHeadingText", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ExperienceHeading[8]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 477.259, + "placementX" : 29.905, + "placementY" : 477.259, + "placementWidth" : 63.841, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 63.841, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/ExperienceHeading[8]/ExperienceHeadingText[0]/ExperienceHeadingLabel[0]", + "entityName" : "ExperienceHeadingLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ExperienceHeading[8]/ExperienceHeadingText[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 477.259, + "placementX" : 29.905, + "placementY" : 477.259, + "placementWidth" : 63.841, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 63.841, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/ExperienceHeading[8]/ExperienceHeadingRule[1]", + "entityName" : "ExperienceHeadingRule", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ExperienceHeading[8]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 93.746, + "computedY" : 483.425, + "placementX" : 93.746, + "placementY" : 483.425, + "placementWidth" : 471.625, + "placementHeight" : 8.617, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 471.625, + "contentHeight" : 8.617, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 7.617, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.285 + } + }, { + "path" : "VioletGridCv[0]/ExperienceHeading[8]/ExperienceHeadingRule[1]/ExperienceHeadingRuleLine[0]", + "entityName" : "ExperienceHeadingRuleLine", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/ExperienceHeading[8]/ExperienceHeadingRule[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 105.031, + "computedY" : 483.425, + "placementX" : 105.031, + "placementY" : 483.425, + "placementWidth" : 460.34, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 460.34, + "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" : "VioletGridCv[0]/ExperienceEntries[9]", + "entityName" : "ExperienceEntries", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 9, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 262.073, + "placementX" : 29.905, + "placementY" : 262.073, + "placementWidth" : 535.456, + "placementHeight" : 204.296, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.456, + "contentHeight" : 204.296, + "margin" : { + "top" : 10.89, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 75.891 + } + }, { + "path" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]", + "entityName" : "ExperienceEntry_0", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 105.796, + "computedY" : 382.189, + "placementX" : 105.796, + "placementY" : 382.189, + "placementWidth" : 459.566, + "placementHeight" : 84.18, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 459.566, + "contentHeight" : 84.18, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 13.542, + "left" : 20.031 + } + }, { + "path" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/EntryTitle_0[0]", + "entityName" : "EntryTitle_0", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 125.826, + "computedY" : 455.065, + "placementX" : 125.826, + "placementY" : 455.065, + "placementWidth" : 439.535, + "placementHeight" : 11.304, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 11.304, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/EntryTitle_0[0]/TitleTable_0[0]", + "entityName" : "TitleTable_0", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/EntryTitle_0[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 125.826, + "computedY" : 455.065, + "placementX" : 125.826, + "placementY" : 455.065, + "placementWidth" : 439.535, + "placementHeight" : 11.304, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 11.304, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/EntryTitle_0[0]/Period_0[1]", + "entityName" : "Period_0", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/EntryTitle_0[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 29.905, + "computedY" : 455.515, + "placementX" : 29.905, + "placementY" : 455.515, + "placementWidth" : 57.005, + "placementHeight" : 10.404, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 57.005, + "contentHeight" : 10.404, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/EntryTitle_0[0]/Marker_0[2]", + "entityName" : "Marker_0", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/EntryTitle_0[0]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 101.987, + "computedY" : 456.908, + "placementX" : 101.987, + "placementY" : 456.908, + "placementWidth" : 7.617, + "placementHeight" : 7.617, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 7.617, + "contentHeight" : 7.617, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]/Highlights_0[1]", + "entityName" : "Highlights_0", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_0[0]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 125.826, + "computedY" : 395.731, + "placementX" : 125.826, + "placementY" : 395.731, + "placementWidth" : 439.535, + "placementHeight" : 55.892, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 55.892, + "margin" : { + "top" : 3.442, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]", + "entityName" : "ExperienceEntry_1", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 105.796, + "computedY" : 309.577, + "placementX" : 105.796, + "placementY" : 309.577, + "placementWidth" : 459.566, + "placementHeight" : 72.613, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 459.566, + "contentHeight" : 72.613, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 13.542, + "left" : 20.031 + } + }, { + "path" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/EntryTitle_1[0]", + "entityName" : "EntryTitle_1", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 125.826, + "computedY" : 370.885, + "placementX" : 125.826, + "placementY" : 370.885, + "placementWidth" : 439.535, + "placementHeight" : 11.304, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 11.304, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/EntryTitle_1[0]/TitleTable_1[0]", + "entityName" : "TitleTable_1", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/EntryTitle_1[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 125.826, + "computedY" : 370.885, + "placementX" : 125.826, + "placementY" : 370.885, + "placementWidth" : 439.535, + "placementHeight" : 11.304, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 11.304, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/EntryTitle_1[0]/Period_1[1]", + "entityName" : "Period_1", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/EntryTitle_1[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 29.905, + "computedY" : 371.335, + "placementX" : 29.905, + "placementY" : 371.335, + "placementWidth" : 47.893, + "placementHeight" : 10.404, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 47.893, + "contentHeight" : 10.404, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/EntryTitle_1[0]/Marker_1[2]", + "entityName" : "Marker_1", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/EntryTitle_1[0]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 101.987, + "computedY" : 372.729, + "placementX" : 101.987, + "placementY" : 372.729, + "placementWidth" : 7.617, + "placementHeight" : 7.617, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 7.617, + "contentHeight" : 7.617, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]/Highlights_1[1]", + "entityName" : "Highlights_1", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_1[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 125.826, + "computedY" : 323.119, + "placementX" : 125.826, + "placementY" : 323.119, + "placementWidth" : 439.535, + "placementHeight" : 44.325, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 44.325, + "margin" : { + "top" : 3.442, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]", + "entityName" : "ExperienceEntry_2", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]", + "childIndex" : 2, + "depth" : 3, + "layer" : 3, + "computedX" : 105.796, + "computedY" : 262.073, + "placementX" : 105.796, + "placementY" : 262.073, + "placementWidth" : 459.566, + "placementHeight" : 47.504, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 459.566, + "contentHeight" : 47.504, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 20.031 + } + }, { + "path" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/EntryTitle_2[0]", + "entityName" : "EntryTitle_2", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 125.826, + "computedY" : 298.273, + "placementX" : 125.826, + "placementY" : 298.273, + "placementWidth" : 439.535, + "placementHeight" : 11.304, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 11.304, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/EntryTitle_2[0]/TitleTable_2[0]", + "entityName" : "TitleTable_2", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/EntryTitle_2[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 125.826, + "computedY" : 298.273, + "placementX" : 125.826, + "placementY" : 298.273, + "placementWidth" : 439.535, + "placementHeight" : 11.304, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 11.304, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/EntryTitle_2[0]/Period_2[1]", + "entityName" : "Period_2", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/EntryTitle_2[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 29.905, + "computedY" : 298.723, + "placementX" : 29.905, + "placementY" : 298.723, + "placementWidth" : 47.893, + "placementHeight" : 10.404, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 47.893, + "contentHeight" : 10.404, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/EntryTitle_2[0]/Marker_2[2]", + "entityName" : "Marker_2", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/EntryTitle_2[0]", + "childIndex" : 2, + "depth" : 5, + "layer" : 5, + "computedX" : 101.987, + "computedY" : 300.116, + "placementX" : 101.987, + "placementY" : 300.116, + "placementWidth" : 7.617, + "placementHeight" : 7.617, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 7.617, + "contentHeight" : 7.617, + "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" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]/Highlights_2[1]", + "entityName" : "Highlights_2", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/ExperienceEntries[9]/ExperienceEntry_2[2]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 125.826, + "computedY" : 262.073, + "placementX" : 125.826, + "placementY" : 262.073, + "placementWidth" : 439.535, + "placementHeight" : 32.758, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 439.535, + "contentHeight" : 32.758, + "margin" : { + "top" : 3.442, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/ProjectsHeading[10]", + "entityName" : "ProjectsHeading", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 10, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 231.717, + "placementX" : 29.905, + "placementY" : 231.717, + "placementWidth" : 535.466, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 14.783, + "margin" : { + "top" : 15.573, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/ProjectsHeading[10]/ProjectsHeadingText[0]", + "entityName" : "ProjectsHeadingText", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ProjectsHeading[10]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 231.717, + "placementX" : 29.905, + "placementY" : 231.717, + "placementWidth" : 105.864, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 105.864, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/ProjectsHeading[10]/ProjectsHeadingText[0]/ProjectsHeadingLabel[0]", + "entityName" : "ProjectsHeadingLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/ProjectsHeading[10]/ProjectsHeadingText[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 231.717, + "placementX" : 29.905, + "placementY" : 231.717, + "placementWidth" : 105.864, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 105.864, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/ProjectsHeading[10]/ProjectsHeadingRule[1]", + "entityName" : "ProjectsHeadingRule", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/ProjectsHeading[10]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 135.769, + "computedY" : 237.883, + "placementX" : 135.769, + "placementY" : 237.883, + "placementWidth" : 429.602, + "placementHeight" : 8.617, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 429.602, + "contentHeight" : 8.617, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 7.617, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.285 + } + }, { + "path" : "VioletGridCv[0]/ProjectsHeading[10]/ProjectsHeadingRule[1]/ProjectsHeadingRuleLine[0]", + "entityName" : "ProjectsHeadingRuleLine", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/ProjectsHeading[10]/ProjectsHeadingRule[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 147.054, + "computedY" : 237.883, + "placementX" : 147.054, + "placementY" : 237.883, + "placementWidth" : 418.317, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 418.317, + "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" : "VioletGridCv[0]/Project_0[11]", + "entityName" : "Project_0", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 11, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 177.452, + "placementX" : 29.905, + "placementY" : 177.452, + "placementWidth" : 535.466, + "placementHeight" : 45.745, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 45.745, + "margin" : { + "top" : 8.52, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]", + "entityName" : "ProjectThumb_0", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Project_0[11]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 180.314, + "placementX" : 29.905, + "placementY" : 180.314, + "placementWidth" : 56.989, + "placementHeight" : 42.882, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 56.989, + "contentHeight" : 42.882, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.849 + } + }, { + "path" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]/ProjectTile_0[0]", + "entityName" : "ProjectTile_0", + "entityKind" : "ShapeContainerNode", + "parentPath" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 41.754, + "computedY" : 180.314, + "placementX" : 41.754, + "placementY" : 180.314, + "placementWidth" : 45.139, + "placementHeight" : 42.882, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 45.139, + "contentHeight" : 42.882, + "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" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]/ProjectTile_0[0]/ProjectGlyph_0[0]", + "entityName" : "ProjectGlyph_0", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]/ProjectTile_0[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 50.324, + "computedY" : 187.755, + "placementX" : 50.324, + "placementY" : 187.755, + "placementWidth" : 28.0, + "placementHeight" : 28.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 28.0, + "contentHeight" : 28.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" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]/ProjectTile_0[0]/ProjectGlyph_0[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]/ProjectTile_0[0]/ProjectGlyph_0[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 50.324, + "computedY" : 187.755, + "placementX" : 50.324, + "placementY" : 187.755, + "placementWidth" : 28.0, + "placementHeight" : 28.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 28.0, + "contentHeight" : 28.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" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]/ProjectTile_0[0]/ProjectGlyph_0[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/Project_0[11]/ProjectThumb_0[0]/ProjectTile_0[0]/ProjectGlyph_0[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 50.324, + "computedY" : 187.755, + "placementX" : 50.324, + "placementY" : 187.755, + "placementWidth" : 28.0, + "placementHeight" : 28.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 28.0, + "contentHeight" : 28.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" : "VioletGridCv[0]/Project_0[11]/ProjectCopy_0[1]", + "entityName" : "ProjectCopy_0", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Project_0[11]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 108.052, + "computedY" : 177.452, + "placementX" : 108.052, + "placementY" : 177.452, + "placementWidth" : 457.309, + "placementHeight" : 45.745, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 457.309, + "contentHeight" : 45.745, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 19.466 + } + }, { + "path" : "VioletGridCv[0]/Project_0[11]/ProjectCopy_0[1]/ProjectTitle_0[0]", + "entityName" : "ProjectTitle_0", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/Project_0[11]/ProjectCopy_0[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 127.519, + "computedY" : 211.652, + "placementX" : 127.519, + "placementY" : 211.652, + "placementWidth" : 437.842, + "placementHeight" : 11.544, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 437.842, + "contentHeight" : 11.544, + "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" : "VioletGridCv[0]/Project_0[11]/ProjectCopy_0[1]/ProjectBody_0[1]", + "entityName" : "ProjectBody_0", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Project_0[11]/ProjectCopy_0[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 127.519, + "computedY" : 177.452, + "placementX" : 127.519, + "placementY" : 177.452, + "placementWidth" : 424.042, + "placementHeight" : 32.169, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 424.042, + "contentHeight" : 32.169, + "margin" : { + "top" : 2.031, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Project_1[12]", + "entityName" : "Project_1", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 12, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 124.751, + "placementX" : 29.905, + "placementY" : 124.751, + "placementWidth" : 535.466, + "placementHeight" : 42.882, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 42.882, + "margin" : { + "top" : 9.818, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]", + "entityName" : "ProjectThumb_1", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Project_1[12]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 124.751, + "placementX" : 29.905, + "placementY" : 124.751, + "placementWidth" : 56.989, + "placementHeight" : 42.882, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 56.989, + "contentHeight" : 42.882, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.849 + } + }, { + "path" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]/ProjectTile_1[0]", + "entityName" : "ProjectTile_1", + "entityKind" : "ShapeContainerNode", + "parentPath" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 41.754, + "computedY" : 124.751, + "placementX" : 41.754, + "placementY" : 124.751, + "placementWidth" : 45.139, + "placementHeight" : 42.882, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 45.139, + "contentHeight" : 42.882, + "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" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]/ProjectTile_1[0]/ProjectGlyph_1[0]", + "entityName" : "ProjectGlyph_1", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]/ProjectTile_1[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 50.324, + "computedY" : 132.193, + "placementX" : 50.324, + "placementY" : 132.193, + "placementWidth" : 28.0, + "placementHeight" : 28.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 28.0, + "contentHeight" : 28.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" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]/ProjectTile_1[0]/ProjectGlyph_1[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]/ProjectTile_1[0]/ProjectGlyph_1[0]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 50.324, + "computedY" : 132.193, + "placementX" : 50.324, + "placementY" : 132.193, + "placementWidth" : 28.0, + "placementHeight" : 28.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 28.0, + "contentHeight" : 28.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" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]/ProjectTile_1[0]/ProjectGlyph_1[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/Project_1[12]/ProjectThumb_1[0]/ProjectTile_1[0]/ProjectGlyph_1[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 50.324, + "computedY" : 132.193, + "placementX" : 50.324, + "placementY" : 132.193, + "placementWidth" : 28.0, + "placementHeight" : 28.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 28.0, + "contentHeight" : 28.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" : "VioletGridCv[0]/Project_1[12]/ProjectCopy_1[1]", + "entityName" : "ProjectCopy_1", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/Project_1[12]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 108.052, + "computedY" : 132.892, + "placementX" : 108.052, + "placementY" : 132.892, + "placementWidth" : 457.309, + "placementHeight" : 34.742, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 457.309, + "contentHeight" : 34.742, + "margin" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 19.466 + } + }, { + "path" : "VioletGridCv[0]/Project_1[12]/ProjectCopy_1[1]/ProjectTitle_1[0]", + "entityName" : "ProjectTitle_1", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/Project_1[12]/ProjectCopy_1[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 127.519, + "computedY" : 156.09, + "placementX" : 127.519, + "placementY" : 156.09, + "placementWidth" : 437.842, + "placementHeight" : 11.544, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 437.842, + "contentHeight" : 11.544, + "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" : "VioletGridCv[0]/Project_1[12]/ProjectCopy_1[1]/ProjectBody_1[1]", + "entityName" : "ProjectBody_1", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/Project_1[12]/ProjectCopy_1[1]", + "childIndex" : 1, + "depth" : 4, + "layer" : 4, + "computedX" : 127.519, + "computedY" : 132.892, + "placementX" : 127.519, + "placementY" : 132.892, + "placementWidth" : 424.178, + "placementHeight" : 21.167, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 424.178, + "contentHeight" : 21.167, + "margin" : { + "top" : 2.031, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/CredentialHeadings[13]", + "entityName" : "CredentialHeadings", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 13, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 101.109, + "placementX" : 29.905, + "placementY" : 101.109, + "placementWidth" : 535.466, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 14.783, + "margin" : { + "top" : 8.859, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/CredentialHeadings[13]/EducationHeadingLabel[0]", + "entityName" : "EducationHeadingLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/CredentialHeadings[13]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 101.109, + "placementX" : 29.905, + "placementY" : 101.109, + "placementWidth" : 62.401, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 62.401, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/CredentialHeadings[13]/EducationHeadingRule[1]", + "entityName" : "EducationHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/CredentialHeadings[13]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 103.591, + "computedY" : 107.276, + "placementX" : 103.591, + "placementY" : 107.276, + "placementWidth" : 159.846, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 159.846, + "contentHeight" : 1.0, + "margin" : { + "top" : 7.617, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.285 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/CredentialHeadings[13]/SpacerNode[2]", + "entityName" : null, + "entityKind" : "SpacerNode", + "parentPath" : "VioletGridCv[0]/CredentialHeadings[13]", + "childIndex" : 2, + "depth" : 3, + "layer" : 3, + "computedX" : 274.722, + "computedY" : 115.893, + "placementX" : 274.722, + "placementY" : 115.893, + "placementWidth" : 39.497, + "placementHeight" : 0.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 39.497, + "contentHeight" : 0.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" : "VioletGridCv[0]/CredentialHeadings[13]/LanguagesHeadingLabel[3]", + "entityName" : "LanguagesHeadingLabel", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/CredentialHeadings[13]", + "childIndex" : 3, + "depth" : 3, + "layer" : 3, + "computedX" : 314.219, + "computedY" : 101.109, + "placementX" : 314.219, + "placementY" : 101.109, + "placementWidth" : 63.291, + "placementHeight" : 14.783, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 63.291, + "contentHeight" : 14.783, + "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" : "VioletGridCv[0]/CredentialHeadings[13]/LanguagesHeadingRule[4]", + "entityName" : "LanguagesHeadingRule", + "entityKind" : "LineNode", + "parentPath" : "VioletGridCv[0]/CredentialHeadings[13]", + "childIndex" : 4, + "depth" : 3, + "layer" : 3, + "computedX" : 388.794, + "computedY" : 107.276, + "placementX" : 388.794, + "placementY" : 107.276, + "placementWidth" : 165.292, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 165.292, + "contentHeight" : 1.0, + "margin" : { + "top" : 7.617, + "right" : 0.0, + "bottom" : 0.0, + "left" : 11.285 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/CredentialBodies[14]", + "entityName" : "CredentialBodies", + "entityKind" : "RowNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 14, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 50.973, + "placementX" : 29.905, + "placementY" : 50.973, + "placementWidth" : 535.466, + "placementHeight" : 42.519, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 535.466, + "contentHeight" : 42.519, + "margin" : { + "top" : 7.617, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]", + "entityName" : "Education", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 29.905, + "computedY" : 52.849, + "placementX" : 29.905, + "placementY" : 52.849, + "placementWidth" : 242.614, + "placementHeight" : 40.643, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 242.614, + "contentHeight" : 40.643, + "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" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]", + "entityName" : "EducationBody", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 29.905, + "computedY" : 52.849, + "placementX" : 29.905, + "placementY" : 52.849, + "placementWidth" : 242.614, + "placementHeight" : 40.643, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 242.614, + "contentHeight" : 40.643, + "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" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationLines[0]", + "entityName" : "EducationLines", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]", + "childIndex" : 0, + "depth" : 5, + "layer" : 5, + "computedX" : 81.251, + "computedY" : 52.849, + "placementX" : 81.251, + "placementY" : 52.849, + "placementWidth" : 191.268, + "placementHeight" : 38.33, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 191.268, + "contentHeight" : 38.33, + "margin" : { + "top" : 2.313, + "right" : 0.0, + "bottom" : 0.0, + "left" : 51.346 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationBadge[1]", + "entityName" : "EducationBadge", + "entityKind" : "ShapeContainerNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]", + "childIndex" : 1, + "depth" : 5, + "layer" : 5, + "computedX" : 29.905, + "computedY" : 52.867, + "placementX" : 29.905, + "placementY" : 52.867, + "placementWidth" : 40.625, + "placementHeight" : 40.625, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 40.625, + "contentHeight" : 40.625, + "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" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationBadge[1]/EducationGlyph[0]", + "entityName" : "EducationGlyph", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationBadge[1]", + "childIndex" : 0, + "depth" : 6, + "layer" : 6, + "computedX" : 37.218, + "computedY" : 60.179, + "placementX" : 37.218, + "placementY" : 60.179, + "placementWidth" : 26.0, + "placementHeight" : 26.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 26.0, + "contentHeight" : 26.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" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationBadge[1]/EducationGlyph[0]/SvgIcon[0]", + "entityName" : "SvgIcon", + "entityKind" : "LayerStackNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationBadge[1]/EducationGlyph[0]", + "childIndex" : 0, + "depth" : 7, + "layer" : 7, + "computedX" : 37.218, + "computedY" : 60.179, + "placementX" : 37.218, + "placementY" : 60.179, + "placementWidth" : 26.0, + "placementHeight" : 26.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 26.0, + "contentHeight" : 26.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" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationBadge[1]/EducationGlyph[0]/SvgIcon[0]/SvgLayer0[0]", + "entityName" : "SvgLayer0", + "entityKind" : "Path", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/Education[0]/EducationBody[0]/EducationBadge[1]/EducationGlyph[0]/SvgIcon[0]", + "childIndex" : 0, + "depth" : 8, + "layer" : 8, + "computedX" : 37.218, + "computedY" : 60.179, + "placementX" : 37.218, + "placementY" : 60.179, + "placementWidth" : 26.0, + "placementHeight" : 26.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 26.0, + "contentHeight" : 26.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" : "VioletGridCv[0]/CredentialBodies[14]/CredentialGutter[1]", + "entityName" : "CredentialGutter", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]", + "childIndex" : 1, + "depth" : 3, + "layer" : 3, + "computedX" : 272.529, + "computedY" : 92.492, + "placementX" : 272.529, + "placementY" : 92.492, + "placementWidth" : 39.497, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 39.497, + "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" : "VioletGridCv[0]/CredentialBodies[14]/CredentialGutter[1]/SpacerNode[0]", + "entityName" : null, + "entityKind" : "SpacerNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/CredentialGutter[1]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 272.529, + "computedY" : 92.492, + "placementX" : 272.529, + "placementY" : 92.492, + "placementWidth" : 39.497, + "placementHeight" : 1.0, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 39.497, + "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" : "VioletGridCv[0]/CredentialBodies[14]/Languages[2]", + "entityName" : "Languages", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]", + "childIndex" : 2, + "depth" : 3, + "layer" : 3, + "computedX" : 312.026, + "computedY" : 50.973, + "placementX" : 312.026, + "placementY" : 50.973, + "placementWidth" : 253.325, + "placementHeight" : 42.519, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 253.325, + "contentHeight" : 42.519, + "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" : "VioletGridCv[0]/CredentialBodies[14]/Languages[2]/LanguageTable[0]", + "entityName" : "LanguageTable", + "entityKind" : "TableNode", + "parentPath" : "VioletGridCv[0]/CredentialBodies[14]/Languages[2]", + "childIndex" : 0, + "depth" : 4, + "layer" : 4, + "computedX" : 312.026, + "computedY" : 50.973, + "placementX" : 312.026, + "placementY" : 50.973, + "placementWidth" : 253.325, + "placementHeight" : 41.221, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 253.325, + "contentHeight" : 41.221, + "margin" : { + "top" : 1.298, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 0.0, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + } + }, { + "path" : "VioletGridCv[0]/QuoteBand[15]", + "entityName" : "QuoteBand", + "entityKind" : "SectionNode", + "parentPath" : "VioletGridCv[0]", + "childIndex" : 15, + "depth" : 2, + "layer" : 2, + "computedX" : 29.905, + "computedY" : 10.348, + "placementX" : 29.905, + "placementY" : 10.348, + "placementWidth" : 414.689, + "placementHeight" : 27.084, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 414.689, + "contentHeight" : 27.084, + "margin" : { + "top" : 13.542, + "right" : 0.0, + "bottom" : 0.0, + "left" : 0.0 + }, + "padding" : { + "top" : 6.492, + "right" : 22.57, + "bottom" : 6.492, + "left" : 22.57 + } + }, { + "path" : "VioletGridCv[0]/QuoteBand[15]/QuoteLine[0]", + "entityName" : "QuoteLine", + "entityKind" : "ParagraphNode", + "parentPath" : "VioletGridCv[0]/QuoteBand[15]", + "childIndex" : 0, + "depth" : 3, + "layer" : 3, + "computedX" : 52.475, + "computedY" : 16.839, + "placementX" : 52.475, + "placementY" : 16.839, + "placementWidth" : 369.55, + "placementHeight" : 14.1, + "startPage" : 0, + "endPage" : 0, + "contentWidth" : 369.55, + "contentHeight" : 14.1, + "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 + } + } ] +} diff --git a/qa/src/test/resources/visual-baselines/cv-v2-layered/violet_grid-page-0.png b/qa/src/test/resources/visual-baselines/cv-v2-layered/violet_grid-page-0.png new file mode 100644 index 0000000000000000000000000000000000000000..baa9ae30bfd47633d7689c2f47c75fc99cd8113d GIT binary patch literal 139076 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
+ * + *

Unlike a sidebar CV this page has no page-level grid. The masthead splits + * where the contact marks begin, the timeline into dates / rail / content, a + * project into tile / copy, and the credentials into two halves — and none of + * those four splits knows about any of the others. That is why every + * horizontal arrangement here is either a top-level row or a table, and why + * none of them nests: a row cannot sit inside a row's cell.

+ * + *

Three marks that are relationships, not lengths

+ * + *

A section rule starts where its heading ends, so it is a weighted column + * taking what an auto column leaves. The timeline rail is the left border of + * every entry but the last, so consecutive entries butt into one unbroken line + * whose length follows from how many entries there are. A project's hairline + * is the left border of its copy, so it is exactly as tall as the copy. None + * of the three is a measured height, and none has to be re-measured when the + * content changes.

+ * + *

One page, and what happens past it

+ * + *

The page is a stack of bands, so a CV with more content than the design + * holds runs onto a second page rather than losing anything — each experience + * entry is held together, so a role is never cut in half, but the sheet is + * drawn for one page and a longer one will look like a one-page design that + * ran over. {@link TimelineMinimal} is the preset in this package built to + * paginate.

+ * + *

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 summary, a {@link ParagraphSection} of one line per line — set as + * written rather than wrapped, because the design's own breaks leave + * room no greedy wrap would;
  • + *
  • skills, an {@link EntriesSection} whose entries carry a mark, a label + * and a description — the six-up grid;
  • + *
  • tools, a {@link SkillsSection} of unlevelled names — the strip;
  • + *
  • experience and projects, {@link EntriesSection}s;
  • + *
  • education, an {@link EntriesSection} whose first entry is drawn, and + * languages, a {@link SkillsSection} — the closing band;
  • + *
  • the quotation, a {@link ParagraphSection} whose body is the line in + * the tinted band. Only its body is drawn: the title is how the document + * names the berth.
  • + *
+ * + *

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 skill, a project and the degree 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.

+ * + *

A language draws both channels of its skill: the discs from + * {@code CvSkill.level()} and the words beside them from + * {@code CvSkill.note()}.

+ * + *

The email, the phone and each link are reachable from the PDF, with the + * {@code mailto:} and {@code tel:} targets built from the values. 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 an address happens to be, and it takes the + * mark of the network it points at or the globe. A role, a project title and + * the degree become links when their entry carries {@code CvEntry.link()}.

+ * + *

Fonts

+ * + *

The sheet is set in Lato, with Asap Condensed for the name, the headings + * and the skill labels. 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.

+ * + *

Usage:

+ *
{@code
+ * DocumentTemplate template = VioletGrid.create();
+ * template.compose(session, cv);
+ * }
+ * + * @since 2.2.3 + */ +public final class VioletGrid { + + /** Stable identifier of this preset. */ + public static final String ID = "violet-grid"; + + /** Human-readable name of this preset. */ + public static final String DISPLAY_NAME = "Violet Grid"; + + private static final List SUMMARY_KEYS = + List.of("summary", "profile", "about"); + private static final List QUOTE_KEYS = + List.of("quote", "motto", "tagline", "closing"); + private static final List SKILL_KEYS = + List.of("skills", "expertise", "competencies"); + private static final List TOOL_KEYS = + List.of("tools", "stack", "software"); + private static final List LANGUAGE_KEYS = + List.of("languages", "language"); + private static final List EXPERIENCE_KEYS = + List.of("experience", "employment", "work history", "career"); + private static final List PROJECT_KEYS = + List.of("projects", "project", "portfolio", "selected work"); + private static final List EDUCATION_KEYS = + List.of("education", "qualifications"); + + private VioletGrid() { + } + + /** + * 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 quotation is claimed before the summary: its own keys are + // narrow, but the summary's are broad enough to take a closing line + // titled loosely. + ParagraphSection quote = berth(sections, ParagraphSection.class, QUOTE_KEYS); + ParagraphSection summary = + berthExcept(sections, ParagraphSection.class, SUMMARY_KEYS, quote); + EntriesSection skills = berth(sections, EntriesSection.class, SKILL_KEYS); + SkillsSection tools = berth(sections, SkillsSection.class, TOOL_KEYS); + SkillsSection languages = + berthExcept(sections, SkillsSection.class, LANGUAGE_KEYS, tools); + EntriesSection experience = berth(sections, EntriesSection.class, EXPERIENCE_KEYS); + EntriesSection projects = + berthExcept(sections, EntriesSection.class, PROJECT_KEYS, skills); + EntriesSection education = berth(sections, EntriesSection.class, EDUCATION_KEYS); + + // Every length on the sheet is a share of the design's own grid, so + // the preset sets the page and its margins rather than following + // what the caller configured. + document.pageSize(PAGE).margin(new DocumentInsets( + PAGE_MARGIN_TOP, PAGE_MARGIN_X, PAGE_MARGIN_BOTTOM, PAGE_MARGIN_X)); + document.pageFlow(page -> { + page.name("VioletGridCv"); + page.spacing(0); + VioletGridMasthead.render(page, doc.identity(), summary); + VioletGridBody.renderSkills(page, skills); + VioletGridBody.renderTools(page, tools); + VioletGridBody.renderExperience(page, experience); + VioletGridClosing.renderProjects(page, projects); + VioletGridClosing.renderCredentials(page, education, languages); + VioletGridClosing.renderQuote(page, quote); + }); + } + + /** + * 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/VioletGridBody.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridBody.java new file mode 100644 index 000000000..ebe330d8f --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridBody.java @@ -0,0 +1,342 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.dsl.PageFlowBuilder; +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.HorizontalAlign; +import com.demcha.compose.document.node.LayerAlign; +import com.demcha.compose.document.node.TextAlign; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentRowColumn; +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.VioletGridStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BODY; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BULLET_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BULLET_DOT_DIAMETER; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BULLET_PITCH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CONTENT_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DATE_OFFSET; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DISPLAY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.EMPLOYER_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ENTRY_GAP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ENTRY_INDENT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ENTRY_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TO_ENTRIES; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TO_SKILLS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TO_TOOLS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HIGHLIGHT_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ICON_TO_LABEL; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.INK; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LABEL_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LABEL_TO_DESC; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LINE_FACTOR; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LOCATION_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LOCATION_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.MARKER_DIAMETER; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.MARKER_OFFSET; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.MUTED; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PERIOD_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PIPE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RAIL_INDENT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RAIL_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ROLE_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ROLE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RULE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILLS_TO_TOOLS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_COLUMN_INSET; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_DASH_OFF; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_DASH_ON; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_DESC_MEASURE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_DESC_PITCH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_DESC_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_DIVIDER_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SKILL_RAIL_HEIGHT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SUMMARY_TO_SKILLS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TITLE_TO_BULLETS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TOOLS_TO_EXPERIENCE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TOOL_DOT_DIAMETER; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TOOL_GAP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TOOL_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.cellStyle; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.centred; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.gap; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.leading; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.style; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.headingRow; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.lines; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.markerDot; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.text; + +/** + * The middle of the sheet: the six-up skills grid, the tools strip and the + * dated timeline. + */ +final class VioletGridBody { + + private VioletGridBody() { + } + + // -- the skills grid --------------------------------------------------- + + /** + * The skills grid — one row with 2n−1 columns: n equal content columns + * interleaved with n−1 fixed hairline columns. + * + *

Building the separators as cells of the same row as the content is + * what stops them drifting from the boundaries they mark, and dividing by + * the entry count is what lets a seventh skill be a data change.

+ */ + static void renderSkills(PageFlowBuilder page, EntriesSection skills) { + if (skills == null || skills.entries().isEmpty()) { + return; + } + page.add(headingRow("Skills", skills.title(), SUMMARY_TO_SKILLS)); + List entries = skills.entries(); + int count = entries.size(); + double columnWidth = (CONTENT_WIDTH - (count - 1) * SKILL_DIVIDER_THICKNESS) / count; + double innerWidth = columnWidth - 2.0 * SKILL_COLUMN_INSET; + double descriptionInset = Math.max(0.0, (innerWidth - SKILL_DESC_MEASURE) / 2.0); + page.addRow("SkillGrid", row -> { + row.spacing(0); + row.margin(new DocumentInsets(HEADING_TO_SKILLS, 0, 0, 0)); + DocumentRowColumn[] columns = new DocumentRowColumn[2 * count - 1]; + for (int index = 0; index < count; index++) { + columns[2 * index] = DocumentRowColumn.weight(1.0); + if (index < count - 1) { + columns[2 * index + 1] = DocumentRowColumn.fixed(SKILL_DIVIDER_THICKNESS); + } + } + row.columns(columns); + for (int index = 0; index < count; index++) { + CvEntry entry = entries.get(index); + int position = index; + row.addSection("Skill_" + position, + column -> renderSkillColumn(column, entry, position, descriptionInset)); + if (index < count - 1) { + row.addSection("SkillDivider_" + position, VioletGridBody::renderDivider); + } + } + }); + } + + /** One column: the mark, the label and the description, on its own axis. */ + private static void renderSkillColumn(SectionBuilder column, CvEntry entry, int index, + double descriptionInset) { + column.spacing(0); + column.padding(0f, (float) SKILL_COLUMN_INSET, 0f, (float) SKILL_COLUMN_INSET); + if (!entry.icon().isBlank()) { + column.addSvgIcon(VioletGridIcons.icon(entry.icon()), + VioletGridIcons.size(entry.icon()), HorizontalAlign.CENTER); + } + column.addParagraph(p -> p + .name("SkillLabel_" + index) + .text(entry.title()) + .align(TextAlign.CENTER) + .lineSpacing(0) + .textStyle(style(DISPLAY_FONT, LABEL_SIZE, INK, true)) + .margin((float) ICON_TO_LABEL, 0f, (float) LABEL_TO_DESC, 0f)); + column.addParagraph(p -> p + .name("SkillDescription_" + index) + .text(entry.body()) + .align(TextAlign.CENTER) + .lineSpacing(leading(SKILL_DESC_PITCH, SKILL_DESC_SIZE)) + .textStyle(style(BODY_FONT, SKILL_DESC_SIZE, MUTED, false)) + // The description wraps to a narrower measure than the label + // above it, which is why the inset is on this paragraph and not + // on the column. + .padding(0f, (float) descriptionInset, 0f, (float) descriptionInset)); + } + + /** + * The dotted rule between two columns. + * + *

A dashed line is the only primitive that produces a dotted rule. An + * accent border would take its height from the column beside it, which is + * what the height constant has to state by hand instead — the trade the + * design's dotted rule costs.

+ */ + private static void renderDivider(SectionBuilder cell) { + cell.spacing(0); + cell.addLine(line -> line + .name("SkillDividerRule") + .vertical(SKILL_RAIL_HEIGHT) + .thickness(SKILL_DIVIDER_THICKNESS) + .color(RULE) + .dashed(SKILL_DASH_ON, SKILL_DASH_OFF)); + } + + // -- the tools strip --------------------------------------------------- + + /** + * The tools — one paragraph of names and inline discs. + * + *

The discs are inline shape runs rather than a bullet glyph, so they + * cannot fall victim to whatever a fallback font ships, and the line is + * running text rather than a grid — which is what the design's constant gap + * either side of every disc says it is.

+ */ + static void renderTools(PageFlowBuilder page, SkillsSection tools) { + if (tools == null || tools.groups().stream().allMatch(g -> g.entries().isEmpty())) { + return; + } + page.add(headingRow("Tools", tools.title(), SKILLS_TO_TOOLS)); + DocumentTextStyle name = style(BODY_FONT, TOOL_SIZE, BODY, false); + List items = new ArrayList<>(); + for (SkillGroup group : tools.groups()) { + for (CvSkill skill : group.entries()) { + items.add(skill.name()); + } + } + page.addParagraph(p -> { + p.name("ToolsLine"); + p.lineSpacing(0); + p.textStyle(name); + for (int index = 0; index < items.size(); index++) { + if (index > 0) { + p.inlineText(TOOL_GAP, name); + p.dot(TOOL_DOT_DIAMETER, ACCENT); + p.inlineText(TOOL_GAP, name); + } + p.inlineText(items.get(index), name); + } + p.margin((float) HEADING_TO_TOOLS, 0f, 0f, 0f); + }); + } + + // -- the timeline ------------------------------------------------------ + + /** + * The dated timeline. + * + *

The entries host is indented so its LEFT EDGE lands on the rail. That + * is what lets each entry's left border BE the rail: consecutive entries + * butt together into one unbroken line, and it stops at the last marker + * because the last entry does not carry it.

+ */ + static void renderExperience(PageFlowBuilder page, EntriesSection experience) { + if (experience == null || experience.entries().isEmpty()) { + return; + } + page.add(headingRow("Experience", experience.title(), TOOLS_TO_EXPERIENCE)); + List entries = experience.entries(); + page.addSection("ExperienceEntries", host -> { + host.spacing(0); + host.margin((float) HEADING_TO_ENTRIES, 0f, 0f, 0f); + host.padding(0f, 0f, 0f, (float) RAIL_INDENT); + 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); + body.keepTogether(); + if (!last) { + body.accentLeft(RULE, RAIL_THICKNESS); + } + body.padding(0f, 0f, last ? 0f : (float) ENTRY_GAP, (float) ENTRY_INDENT); + renderEntry(body, entry, index); + }); + } + }); + } + + /** + * One entry: the title line with its dates and marker, then the bullets. + * + *

The dates and the disc ride the title line's own layer stack at + * negative offsets, so both are placed relative to the line they belong to + * rather than at a measured y. The title itself is a two-column table — a + * row here would be a row inside a row's cell.

+ */ + private static void renderEntry(SectionBuilder body, CvEntry entry, int index) { + body.addLayerStack(stack -> stack + .name("EntryTitle_" + index) + .layer(titleLine(entry, index), LayerAlign.TOP_LEFT, 0) + .position(text("Period_" + index, entry.date(), + style(BODY_FONT, PERIOD_SIZE, ACCENT, false)), + DATE_OFFSET, centred(PERIOD_SIZE * LINE_FACTOR), + LayerAlign.TOP_LEFT, 1) + .position(markerDot("Marker_" + index, MARKER_DIAMETER, + MARKER_DIAMETER / LINE_FACTOR, ACCENT), + MARKER_OFFSET, centred(MARKER_DIAMETER), LayerAlign.TOP_LEFT, 1)); + List highlights = lines(entry.body()); + if (highlights.isEmpty()) { + return; + } + body.addTable(table -> { + table.name("Highlights_" + index); + table.margin(new DocumentInsets(TITLE_TO_BULLETS, 0, 0, 0)); + table.width(ENTRY_WIDTH); + table.columns( + DocumentTableColumn.fixed(BULLET_COLUMN), + DocumentTableColumn.fixed(ENTRY_WIDTH - BULLET_COLUMN)); + table.defaultCellStyle(cellStyle( + new DocumentInsets(0, 0, + gap(BULLET_PITCH, HIGHLIGHT_SIZE * LINE_FACTOR), 0), + DocumentTableTextAnchor.TOP_LEFT)); + for (int i = 0; i < highlights.size(); i++) { + table.rowCells( + DocumentTableCell.node(markerDot("HighlightDot_" + index + "_" + i, + BULLET_DOT_DIAMETER, HIGHLIGHT_SIZE, ACCENT)), + DocumentTableCell.node(text("Highlight_" + index + "_" + i, + highlights.get(i), + style(BODY_FONT, HIGHLIGHT_SIZE, BODY, false)))); + } + // The pitch is a gap BETWEEN bullets; left on the last one it + // becomes a gap the entry below already owns. + table.rowStyle(highlights.size() - 1, + cellStyle(DocumentInsets.zero(), DocumentTableTextAnchor.TOP_LEFT)); + }); + } + + /** The role, the employer and the location, as one line of three runs. */ + private static DocumentNode titleLine(CvEntry entry, int index) { + DocumentTextStyle role = style(BODY_FONT, ROLE_SIZE, INK, true); + DocumentTextStyle employer = style(BODY_FONT, EMPLOYER_SIZE, MUTED, false); + ParagraphBuilder title = new ParagraphBuilder() + .name("Role_" + index) + .lineSpacing(0) + .textStyle(role) + .inlineText(entry.title(), role); + if (!entry.subtitle().isBlank()) { + title.inlineText(PIPE, employer).inlineText(entry.subtitle(), employer); + } + if (!entry.link().isBlank()) { + title.link(new DocumentLinkOptions(entry.link())); + } + return new TableBuilder() + .name("TitleTable_" + index) + .width(ENTRY_WIDTH) + .columns( + DocumentTableColumn.fixed(ROLE_COLUMN), + DocumentTableColumn.fixed(LOCATION_COLUMN)) + .defaultCellStyle(cellStyle(DocumentInsets.zero(), + DocumentTableTextAnchor.TOP_LEFT)) + .rowCells( + DocumentTableCell.node(title.build()), + DocumentTableCell.node(new ParagraphBuilder() + .name("Location_" + index) + .text(entry.place()) + .align(TextAlign.RIGHT) + .lineSpacing(0) + .textStyle(style(BODY_FONT, LOCATION_SIZE, MUTED, false)) + .build())) + .build(); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridClosing.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridClosing.java new file mode 100644 index 000000000..56dfceb63 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridClosing.java @@ -0,0 +1,466 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.dsl.PageFlowBuilder; +import com.demcha.compose.document.dsl.ParagraphBuilder; +import com.demcha.compose.document.dsl.SectionBuilder; +import com.demcha.compose.document.dsl.ShapeContainerBuilder; +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.TextAlign; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentRowColumn; +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.ParagraphSection; +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.VioletGridStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ACCENT_RULE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BADGE_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BADGE_DIAMETER; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BODY; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CREDENTIALS_TO_QUOTE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CREDENTIAL_GUTTER; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DEGREE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DEGREE_TO_INSTITUTION; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DISPLAY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.EDUCATION_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.EDUCATION_RULE_WEIGHT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.EDUCATION_TEXT_TOP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.EDU_DETAIL_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.EXPERIENCE_TO_PROJECTS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_RULE_OFFSET; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TO_EDUCATION; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TO_PROJECTS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TO_RULE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TRACKING; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.INK; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.INSTITUTION_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.INSTITUTION_TO_DETAIL; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGES_BODY_OFFSET; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGES_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGES_RULE_WEIGHT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGE_LEVEL_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGE_NAME_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGE_PITCH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGE_RATING_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LANGUAGE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LEVEL_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LINE_FACTOR; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.MUTED; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PIPE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECTS_TO_CREDENTIALS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_BODY_PITCH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_BODY_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_COPY_INDENT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_COPY_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_GAP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_SUB_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_TITLE_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_TITLE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_YEAR_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.PROJECT_YEAR_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.QUOTE_GAP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.QUOTE_LINE_BOX; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.QUOTE_PAD_H; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.QUOTE_PAD_V; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.QUOTE_RADIUS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.QUOTE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RATING_DOT_DIAMETER; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RATING_EMPTY; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RATING_GAP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RATING_SCALE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.RULE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TABLE_SLACK; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.THUMB_COLUMN; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.THUMB_HEIGHT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.THUMB_PAD_LEFT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.THUMB_RADIUS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.THUMB_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TINT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.TITLE_TO_BODY; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.cellStyle; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.gap; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.leading; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.style; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.headingRow; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.inlineIcon; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.text; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.tracked; + +/** + * What closes the sheet: the projects, the credentials band and the quote. + */ +final class VioletGridClosing { + + private VioletGridClosing() { + } + + // -- the projects ------------------------------------------------------ + + /** One top-level row per project: the tile, then the copy beside it. */ + static void renderProjects(PageFlowBuilder page, EntriesSection projects) { + if (projects == null || projects.entries().isEmpty()) { + return; + } + page.add(headingRow("Projects", projects.title(), EXPERIENCE_TO_PROJECTS)); + List entries = projects.entries(); + for (int i = 0; i < entries.size(); i++) { + CvEntry entry = entries.get(i); + int index = i; + double top = i == 0 ? HEADING_TO_PROJECTS : PROJECT_GAP; + page.addRow("Project_" + index, row -> { + row.spacing(0); + row.margin(new DocumentInsets(top, 0, 0, 0)); + row.columns( + DocumentRowColumn.fixed(THUMB_COLUMN), + DocumentRowColumn.weight(1.0)); + row.addSection("ProjectThumb_" + index, + cell -> renderThumb(cell, entry, index)); + row.addSection("ProjectCopy_" + index, + cell -> renderProjectCopy(cell, entry, index)); + }); + } + } + + /** + * The tinted tile and the glyph it owns — a shape container rather than a + * fill with a mark beside it: the tile IS the thumbnail, and centring the + * glyph in the container is what keeps the two together when either size + * changes. + */ + private static void renderThumb(SectionBuilder cell, CvEntry entry, int index) { + cell.spacing(0); + cell.padding(0f, 0f, 0f, (float) THUMB_PAD_LEFT); + if (entry.icon().isBlank()) { + return; + } + SectionBuilder glyph = new SectionBuilder(); + glyph.name("ProjectGlyph_" + index); + glyph.addSvgIcon(VioletGridIcons.icon(entry.icon()), VioletGridIcons.size(entry.icon())); + cell.addContainer(tile -> tile + .name("ProjectTile_" + index) + .roundedRect(THUMB_WIDTH, THUMB_HEIGHT, THUMB_RADIUS) + .fillColor(TINT) + .center(glyph.build())); + } + + /** + * The copy beside a thumbnail. The hairline is this section's own left + * border, so it runs the copy's height — which is what the design shows, + * and what a line with a measured height would get wrong the first time + * the copy ran to three lines. + */ + private static void renderProjectCopy(SectionBuilder cell, CvEntry entry, int index) { + DocumentTextStyle title = style(BODY_FONT, PROJECT_TITLE_SIZE, INK, true); + DocumentTextStyle subtitle = style(BODY_FONT, PROJECT_SUB_SIZE, MUTED, false); + cell.spacing(0); + cell.accentLeft(RULE, PROJECT_RULE_THICKNESS); + cell.padding(0f, 0f, 0f, (float) PROJECT_COPY_INDENT); + ParagraphBuilder name = new ParagraphBuilder() + .name("ProjectName_" + index) + .lineSpacing(0) + .textStyle(title) + .inlineText(entry.title(), title); + if (!entry.subtitle().isBlank()) { + name.inlineText(PIPE, subtitle).inlineText(entry.subtitle(), subtitle); + } + if (!entry.link().isBlank()) { + name.link(new DocumentLinkOptions(entry.link())); + } + cell.addTable(table -> table + .name("ProjectTitle_" + index) + .width(PROJECT_COPY_WIDTH) + .columns( + DocumentTableColumn.fixed(PROJECT_TITLE_COLUMN), + DocumentTableColumn.fixed(PROJECT_YEAR_COLUMN)) + .defaultCellStyle(cellStyle(DocumentInsets.zero(), + DocumentTableTextAnchor.TOP_LEFT)) + .rowCells( + DocumentTableCell.node(name.build()), + DocumentTableCell.node(new ParagraphBuilder() + .name("ProjectYear_" + index) + .text(entry.date()) + .align(TextAlign.RIGHT) + .lineSpacing(0) + .textStyle(style(BODY_FONT, PROJECT_YEAR_SIZE, MUTED, false)) + .build()))); + cell.addParagraph(p -> p + .name("ProjectBody_" + index) + .text(entry.body().replace(String.valueOf((char) 10), " ")) + .lineSpacing(leading(PROJECT_BODY_PITCH, PROJECT_BODY_SIZE)) + .textStyle(style(BODY_FONT, PROJECT_BODY_SIZE, BODY, false)) + .margin((float) TITLE_TO_BODY, 0f, 0f, 0f)); + } + + // -- the credentials band ---------------------------------------------- + + /** + * The credentials band: education and languages side by side. + * + *

TWO top-level rows rather than one, and that is not a stylistic + * choice. The obvious shape — one row whose two cells each hold a heading + * and a body — cannot be built: a heading is a text and a rule side by + * side, so a cell holding one would need a nested row, which the layout + * compiler refuses. So the band is flattened: one row carries both headings + * and both rules as direct children, and a second carries the two bodies. + * Nothing is nested, and the two rows share the same column arithmetic, so + * the halves cannot drift apart.

+ */ + static void renderCredentials(PageFlowBuilder page, EntriesSection education, + SkillsSection languages) { + boolean hasEducation = education != null && !education.entries().isEmpty(); + boolean hasLanguages = languages != null + && languages.groups().stream().anyMatch(group -> !group.entries().isEmpty()); + if (!hasEducation && !hasLanguages) { + return; + } + renderCredentialHeadings(page, + hasEducation ? education.title() : "", + hasLanguages ? languages.title() : ""); + page.addRow("CredentialBodies", row -> { + row.spacing(0); + row.margin(new DocumentInsets(HEADING_TO_EDUCATION, 0, 0, 0)); + row.columns( + DocumentRowColumn.fixed(EDUCATION_COLUMN), + DocumentRowColumn.fixed(CREDENTIAL_GUTTER), + DocumentRowColumn.weight(1.0)); + row.addSection("Education", cell -> renderEducation(cell, education)); + row.addSection("CredentialGutter", cell -> cell.spacer(CREDENTIAL_GUTTER, 1.0)); + row.addSection("Languages", cell -> renderLanguages(cell, languages)); + }); + } + + /** + * Both headings and both rules, as children of one row. The two text + * columns take what their words need and the two weighted ones split what + * is left in the ratio the design's rules measure, so each rule still + * begins where its own heading ends. + */ + private static void renderCredentialHeadings(PageFlowBuilder page, String educationTitle, + String languagesTitle) { + page.addRow("CredentialHeadings", row -> { + row.spacing(0); + row.margin(new DocumentInsets(PROJECTS_TO_CREDENTIALS, 0, 0, 0)); + row.columns( + DocumentRowColumn.auto(), + DocumentRowColumn.weight(EDUCATION_RULE_WEIGHT), + DocumentRowColumn.fixed(CREDENTIAL_GUTTER), + DocumentRowColumn.auto(), + DocumentRowColumn.weight(LANGUAGES_RULE_WEIGHT)); + row.add(tracked("EducationHeadingLabel", educationTitle, DISPLAY_FONT, + HEADING_SIZE, ACCENT, true, HEADING_TRACKING).build()); + row.addLine(line -> line + .name("EducationHeadingRule") + .fill() + .thickness(HEADING_RULE_THICKNESS) + .color(ACCENT_RULE) + .margin(new DocumentInsets(HEADING_RULE_OFFSET, 0, 0, HEADING_TO_RULE))); + row.addSpacer(CREDENTIAL_GUTTER); + row.add(tracked("LanguagesHeadingLabel", languagesTitle, DISPLAY_FONT, + HEADING_SIZE, ACCENT, true, HEADING_TRACKING).build()); + row.addLine(line -> line + .name("LanguagesHeadingRule") + .fill() + .thickness(HEADING_RULE_THICKNESS) + .color(ACCENT_RULE) + .margin(new DocumentInsets(HEADING_RULE_OFFSET, 0, 0, HEADING_TO_RULE))); + }); + } + + /** + * The badge beside the degree, the institution and the detail line. + * + *

A layer stack rather than a table: the badge is a shape container and + * the three lines are a stack, and neither survives a table cell here. The + * lines carry a left margin the width of the badge column, so the two + * layers do not overlap and the badge needs no offset.

+ */ + private static void renderEducation(SectionBuilder cell, EntriesSection education) { + cell.spacing(0); + if (education == null || education.entries().isEmpty()) { + return; + } + CvEntry entry = education.entries().get(0); + cell.addLayerStack(stack -> { + stack.name("EducationBody"); + stack.layer(educationLines(entry), LayerAlign.TOP_LEFT, 0); + if (!entry.icon().isBlank()) { + stack.position(badge(entry), 0.0, 0.0, LayerAlign.TOP_LEFT, 1); + } + }); + } + + /** The tinted circle and the glyph it owns. */ + private static DocumentNode badge(CvEntry entry) { + SectionBuilder glyph = new SectionBuilder(); + glyph.name("EducationGlyph"); + glyph.addSvgIcon(VioletGridIcons.icon(entry.icon()), VioletGridIcons.size(entry.icon())); + return new ShapeContainerBuilder() + .name("EducationBadge") + .circle(BADGE_DIAMETER) + .fillColor(TINT) + .center(glyph.build()) + .build(); + } + + /** The degree, the institution and the place-and-years line, as one column. */ + private static DocumentNode educationLines(CvEntry entry) { + DocumentTextStyle place = style(BODY_FONT, EDU_DETAIL_SIZE, MUTED, false); + DocumentTextStyle years = style(BODY_FONT, EDU_DETAIL_SIZE, ACCENT, false); + double width = EDUCATION_COLUMN - BADGE_COLUMN - TABLE_SLACK; + ParagraphBuilder degree = new ParagraphBuilder() + .name("Degree") + .text(entry.title()) + .lineSpacing(0) + .textStyle(style(BODY_FONT, DEGREE_SIZE, INK, true)); + if (!entry.link().isBlank()) { + degree.link(new DocumentLinkOptions(entry.link())); + } + ParagraphBuilder detail = new ParagraphBuilder() + .name("EducationDetail") + .lineSpacing(0) + .textStyle(place) + .inlineText(entry.place(), place); + if (!entry.date().isBlank()) { + detail.inlineText(PIPE, place).inlineText(entry.date(), years); + } + return new TableBuilder() + .name("EducationLines") + .margin(new DocumentInsets(EDUCATION_TEXT_TOP, 0, 0, BADGE_COLUMN)) + .width(width) + .columns(DocumentTableColumn.fixed(width)) + .defaultCellStyle(cellStyle(DocumentInsets.zero(), + DocumentTableTextAnchor.TOP_LEFT)) + .rowCells(DocumentTableCell.node(degree.build()) + .withStyle(cellStyle( + new DocumentInsets(0, 0, DEGREE_TO_INSTITUTION, 0), + DocumentTableTextAnchor.TOP_LEFT))) + .rowCells(DocumentTableCell.node(text("Institution", entry.subtitle(), + style(BODY_FONT, INSTITUTION_SIZE, BODY, false))) + .withStyle(cellStyle( + new DocumentInsets(0, 0, INSTITUTION_TO_DETAIL, 0), + DocumentTableTextAnchor.TOP_LEFT))) + .rowCells(DocumentTableCell.node(detail.build())) + .build(); + } + + /** + * The languages — a name, the level as the document words it, and a + * five-disc rating per row. + * + *

The rating 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 void renderLanguages(SectionBuilder block, SkillsSection languages) { + block.spacing(0); + if (languages == null) { + return; + } + List entries = new ArrayList<>(); + for (SkillGroup group : languages.groups()) { + entries.addAll(group.entries()); + } + if (entries.isEmpty()) { + return; + } + block.addTable(table -> { + table.name("LanguageTable"); + table.margin(new DocumentInsets(LANGUAGES_BODY_OFFSET, 0, 0, 0)); + table.width(LANGUAGES_COLUMN - TABLE_SLACK); + table.columns( + DocumentTableColumn.fixed(LANGUAGE_NAME_COLUMN), + DocumentTableColumn.fixed(LANGUAGE_LEVEL_COLUMN), + DocumentTableColumn.fixed(LANGUAGE_RATING_COLUMN - TABLE_SLACK)); + 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, BODY, false))), + DocumentTableCell.node(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 discs, filled up to its rating and grey after it. */ + private static DocumentNode rating(String name, CvSkill skill) { + DocumentTextStyle box = style(BODY_FONT, LANGUAGE_SIZE, BODY, false); + ParagraphBuilder paragraph = new ParagraphBuilder(); + paragraph.name(name); + paragraph.lineSpacing(0); + paragraph.textStyle(box); + if (skill.level().isEmpty()) { + return paragraph.build(); + } + int filled = (int) Math.round(skill.level().getAsDouble() * RATING_SCALE); + for (int index = 0; index < RATING_SCALE; index++) { + paragraph.dot(RATING_DOT_DIAMETER, index < filled ? ACCENT : RATING_EMPTY); + if (index < RATING_SCALE - 1) { + paragraph.inlineText(RATING_GAP, box); + } + } + return paragraph.build(); + } + + // -- the closing band -------------------------------------------------- + + /** + * The closing band. + * + *

A fill with a corner radius and its own padding rather than a soft + * panel, whose padding is a single uniform value: this band's side padding + * is several times its vertical padding.

+ * + *

The quotation mark is a packaged glyph rather than a typographic one. + * At the size the design draws it a real quotation mark would need about + * forty points of type, and its line box alone would be nearly twice the + * band's height.

+ */ + static void renderQuote(PageFlowBuilder page, ParagraphSection quote) { + if (quote == null || quote.body().isBlank()) { + return; + } + DocumentTextStyle line = style(BODY_FONT, QUOTE_SIZE, BODY, false); + DocumentTextStyle box = style(BODY_FONT, QUOTE_LINE_BOX / LINE_FACTOR, BODY, false); + page.addSection("QuoteBand", band -> { + band.spacing(0); + band.margin((float) CREDENTIALS_TO_QUOTE, 0f, 0f, 0f); + band.fillColor(TINT); + band.cornerRadius(QUOTE_RADIUS); + band.padding((float) QUOTE_PAD_V, (float) QUOTE_PAD_H, + (float) QUOTE_PAD_V, (float) QUOTE_PAD_H); + band.addParagraph(p -> { + p.name("QuoteLine"); + p.lineSpacing(0); + p.textStyle(box); + inlineIcon(p, VioletGridIcons.QUOTE); + p.inlineText(QUOTE_GAP, line); + p.inlineText(quote.body().replace(String.valueOf((char) 10), " "), line); + }); + }); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridIcons.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridIcons.java new file mode 100644 index 000000000..823b328c9 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridIcons.java @@ -0,0 +1,112 @@ +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 Violet Grid CV marks: the five contact glyphs, the + * six skill marks, the two project glyphs, the graduation cap and the + * quotation mark that opens the closing band. + * + *

They ship inside the templates artifact under + * {@code templates/cv/violet-grid/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 each mark carries the width it is drawn at, + * because an icon's box is not its glyph and the sizes are per-kind.

+ */ +final class VioletGridIcons { + + static final String EMAIL = "email"; + static final String PHONE = "phone"; + static final String LOCATION = "location"; + static final String WEBSITE = "website"; + static final String LINKEDIN = "linkedin"; + static final String GRADUATION = "graduation"; + static final String QUOTE = "quote"; + + private static final String ICON_ROOT = "/templates/cv/violet-grid/icons/"; + + /** The width each mark is drawn at, as the asset resolver chose it. */ + private static final Map SIZES = Map.ofEntries( + Map.entry(EMAIL, 11.5), + Map.entry(PHONE, 11.5), + Map.entry(LOCATION, 11.5), + Map.entry(WEBSITE, 11.5), + Map.entry(LINKEDIN, 11.5), + Map.entry("ux-research", 20.5), + Map.entry("information-architecture", 20.5), + Map.entry("wireframing", 20.5), + Map.entry("prototyping", 20.5), + Map.entry("usability-testing", 20.5), + Map.entry("design-systems", 20.5), + Map.entry("project-wallet", 28.0), + Map.entry("project-health", 28.0), + Map.entry(GRADUATION, 26.0), + Map.entry(QUOTE, 14.1)); + + /** The marks a document may name on a skill, a project or a degree. */ + static final Set ENTRY_TOKENS = Set.of( + "ux-research", "information-architecture", "wireframing", "prototyping", + "usability-testing", "design-systems", "project-wallet", "project-health", + GRADUATION); + + private static final Map CACHE = new ConcurrentHashMap<>(); + + private VioletGridIcons() { + } + + /** + * 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 violet grid 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, VioletGridIcons::read); + } + + private static SvgIcon read(String token) { + String resourcePath = ICON_ROOT + token + ".svg"; + try (InputStream input = VioletGridIcons.class.getResourceAsStream(resourcePath)) { + if (input == null) { + throw new IllegalStateException("Missing violet grid CV icon: " + resourcePath); + } + return SvgIcon.parse(new String(input.readAllBytes(), StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new UncheckedIOException( + "Failed to read violet grid CV icon: " + resourcePath, e); + } + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridMasthead.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridMasthead.java new file mode 100644 index 000000000..7ae5ce376 --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridMasthead.java @@ -0,0 +1,214 @@ +package com.demcha.compose.document.templates.cv.presets; + +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.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.VioletGridStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ACCENT_LIGHT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BODY; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CONTACT_COLUMN_X; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CONTACT_ICON_GAP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CONTACT_PITCH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CONTACT_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.CONTACT_TOP; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DISCIPLINE_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DISCIPLINE_TO_RULE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DISCIPLINE_TRACKING; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DISPLAY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADER_TO_SUMMARY; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.IDENTITY_RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.IDENTITY_RULE_WIDTH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.INK; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.LINE_FACTOR; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.NAME_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SUMMARY_PITCH; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SUMMARY_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.gap; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.style; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.inlineIcon; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.lines; +import static com.demcha.compose.document.templates.cv.presets.VioletGridWidgets.tracked; + +/** + * The top of the sheet: the two-tone name beside the contact column, and the + * opening lines under them. + */ +final class VioletGridMasthead { + + private VioletGridMasthead() { + } + + /** One line of the contact column: a mark, a value and where it points. */ + private record Channel(String token, String value, String href) { + } + + /** + * The masthead, as a top-level row split where the contact marks begin — + * the column is left-aligned on its marks rather than right-aligned to the + * margin, so that x is the split. + */ + static void render(PageFlowBuilder page, CvIdentity identity, ParagraphSection summary) { + page.addRow("Header", row -> { + row.spacing(0); + row.columns( + DocumentRowColumn.fixed(CONTACT_COLUMN_X), + DocumentRowColumn.weight(1.0)); + row.addSection("Identity", block -> renderIdentity(block, identity)); + row.addSection("Contact", block -> renderContact(block, identity)); + }); + renderSummary(page, summary); + } + + // -- the name ---------------------------------------------------------- + + /** + * The name, the discipline line and the accent rule under it. + * + *

Both names are inline runs of ONE paragraph, so the gap between them + * is a real word space that follows the type size rather than a measured + * offset that would not.

+ */ + private static void renderIdentity(SectionBuilder block, CvIdentity identity) { + block.spacing(0); + DocumentTextStyle given = style(DISPLAY_FONT, NAME_SIZE, INK, false); + DocumentTextStyle family = style(DISPLAY_FONT, NAME_SIZE, ACCENT_LIGHT, false); + block.addParagraph(p -> p + .name("Name") + .lineSpacing(0) + .textStyle(given) + .inlineText(identity.name().first().toUpperCase(Locale.ROOT), given) + .inlineText(" ", given) + .inlineText(identity.name().last().toUpperCase(Locale.ROOT), family)); + block.add(tracked("Discipline", identity.jobTitle().toUpperCase(Locale.ROOT), + DISPLAY_FONT, DISCIPLINE_SIZE, ACCENT, true, DISCIPLINE_TRACKING) + .margin(0f, 0f, (float) DISCIPLINE_TO_RULE, 0f) + .build()); + block.addLine(line -> line + .name("IdentityRule") + .horizontal(IDENTITY_RULE_WIDTH) + .thickness(IDENTITY_RULE_THICKNESS) + .color(ACCENT)); + } + + // -- the contact column ------------------------------------------------ + + /** + * The contact lines. + * + *

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

+ * + *

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

+ */ + private static void renderContact(SectionBuilder block, CvIdentity identity) { + block.spacing(0); + block.padding((float) CONTACT_TOP, 0f, 0f, 0f); + DocumentTextStyle value = style(BODY_FONT, CONTACT_SIZE, BODY, false); + // The line box comes from the paragraph's own style, and an inline run + // taller than it is drawn clipped: take whichever of the mark and the + // text needs more room. + double boxSize = Math.max(CONTACT_SIZE, + VioletGridIcons.size(VioletGridIcons.EMAIL) / LINE_FACTOR); + DocumentTextStyle box = style(BODY_FONT, boxSize, BODY, 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); + p.textStyle(box); + inlineIcon(p, channel.token()); + p.inlineText(CONTACT_ICON_GAP, value); + if (channel.href() == null || channel.href().isBlank()) { + p.inlineText(channel.value(), value); + } else { + p.inlineText(channel.value(), value, new DocumentLinkOptions(channel.href())); + } + p.margin(0f, 0f, + last ? 0f : (float) gap(CONTACT_PITCH, boxSize * LINE_FACTOR), 0f); + }); + } + } + + /** The column's order: how to write, how to call, where, then the links. */ + private static List channels(CvIdentity identity) { + Contact contact = identity.contact(); + List channels = new ArrayList<>(); + channels.add(new Channel(VioletGridIcons.EMAIL, contact.email(), + "mailto:" + contact.email())); + channels.add(new Channel(VioletGridIcons.PHONE, contact.phone(), + telUri(contact.phone()))); + channels.add(new Channel(VioletGridIcons.LOCATION, contact.address(), null)); + for (Link link : identity.links()) { + channels.add(new Channel(markFor(link), link.label(), link.url())); + } + return channels; + } + + /** A link takes the mark of the network it points at, or the globe. */ + private static String markFor(Link link) { + String target = (link.url() + " " + link.label()).toLowerCase(Locale.ROOT); + return target.contains("linkedin") ? VioletGridIcons.LINKEDIN : VioletGridIcons.WEBSITE; + } + + /** + * 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; + } + + // -- the opening lines ------------------------------------------------- + + /** + * The opening block — one paragraph per line the document wrote. + * + *

Not a wrapped paragraph, and that is a reading of the design rather + * than a convenience: its first line ends with room for the next word + * several times over, so no greedy wrap could produce it. The lines are + * sentences, set as lines, and the document says so.

+ */ + private static void renderSummary(PageFlowBuilder page, ParagraphSection summary) { + if (summary == null || summary.body().isBlank()) { + return; + } + DocumentTextStyle line = style(BODY_FONT, SUMMARY_SIZE, BODY, false); + List body = lines(summary.body()); + for (int i = 0; i < body.size(); i++) { + boolean last = i == body.size() - 1; + int index = i; + page.addParagraph(p -> p + .name("SummaryLine_" + index) + .text(body.get(index)) + .lineSpacing(0) + .textStyle(line) + .margin(index == 0 ? (float) HEADER_TO_SUMMARY : 0f, 0f, + last ? 0f : (float) gap(SUMMARY_PITCH, SUMMARY_SIZE * LINE_FACTOR), + 0f)); + } + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridStyles.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridStyles.java new file mode 100644 index 000000000..81554035e --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridStyles.java @@ -0,0 +1,421 @@ +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 Violet Grid CV. + * + *

Every length is a measurement, converted once

+ * + *

The design was drawn on a 1055-pixel-wide raster, so each length here is + * written as {@link #px} of a pixel measured off it. That keeps the source + * auditable — a reader can put a ruler on the drawing and find the number — + * and keeps one conversion factor rather than a page of pre-multiplied + * decimals. Widths that are shares of the page derive from + * {@link #CONTENT_WIDTH}; only genuinely independent marks (a disc's + * diameter, a rule's thickness) are their own constants.

+ * + *

The type sizes are solved, not estimated

+ * + *

Each is the drawing's measured ink width for one specific string divided + * by that string's width in ems in the face that sets it. An estimate from an + * average advance came out several per cent small everywhere, which is enough + * to move a line break — and a moved break is the difference a pixel gate can + * see.

+ */ +final class VioletGridStyles { + + private VioletGridStyles() { + } + + // -- the grid ---------------------------------------------------------- + + /** The drawing's raster width against A4's, in points per pixel. */ + static final double PX_TO_PT = 595.276 / 1055.0; + + static final DocumentPageSize PAGE = DocumentPageSize.A4; + + /** + * One measurement off the drawing, in points. + * + * @param pixels the pixel measured on the 1055-wide raster + * @return the same distance on the page + */ + static double px(double pixels) { + return pixels * PX_TO_PT; + } + + /** The engine's line box as a multiple of the type size. */ + static final double LINE_FACTOR = 1.2; + + /** + * 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. + */ + 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; every table here is a layout + * mechanism rather than a grid the reader should see, so each states the + * absence explicitly. + */ + static final DocumentStroke NO_BORDER = + DocumentStroke.of(DocumentColor.rgba(0, 0, 0, 0), 0.0); + + // -- palette ----------------------------------------------------------- + + /** The violet everything but the family name is set in. */ + static final DocumentColor ACCENT = DocumentColor.rgb(118, 78, 175); + + /** + * The lighter violet the family name takes. Two tones, not one: the + * drawing sets them measurably apart, and antialiasing only lightens — so + * the difference is a decision rather than noise. + */ + static final DocumentColor ACCENT_LIGHT = DocumentColor.rgb(141, 105, 193); + + /** The hairline that follows every section heading — the accent at half. */ + static final DocumentColor ACCENT_RULE = DocumentColor.rgb(190, 172, 220); + + /** The tint behind the project tiles, the education badge and the band. */ + static final DocumentColor TINT = DocumentColor.rgb(237, 231, 245); + + static final DocumentColor INK = DocumentColor.rgb(28, 26, 32); + static final DocumentColor BODY = DocumentColor.rgb(58, 56, 72); + static final DocumentColor MUTED = DocumentColor.rgb(96, 94, 110); + static final DocumentColor RULE = DocumentColor.rgb(219, 219, 219); + static final DocumentColor RATING_EMPTY = DocumentColor.rgb(226, 226, 226); + + // -- type -------------------------------------------------------------- + + /** + * The display face: the name, the discipline line, the section headings + * and the skill labels. Chosen by measurement: the drawing sets the name + * at a width-to-cap ratio this face matches within a few per cent, where + * the nearest-looking alternative is a quarter too wide. + */ + static final FontName DISPLAY_FONT = FontName.ASAP_CONDENSED; + + /** The body face: everything the display face does not set. */ + static final FontName BODY_FONT = FontName.LATO; + + static final double NAME_SIZE = 46.55; + static final double DISCIPLINE_SIZE = 17.73; + static final double HEADING_SIZE = 12.90; + + /** + * The skill labels, sized so the longest one clears its column's gutter. + * + *

Solved from the drawing's own ink widths the size comes out larger — + * but at that size the longest label is wider than its column less the + * gutter, and the binding constraint is the gutter rather than the ink. All + * six are set at one size even though only one is constrained: six labels + * of a set at five sizes is a worse document than six one step small.

+ */ + static final double LABEL_SIZE = 6.8; + + static final double CONTACT_SIZE = 8.93; + static final double SUMMARY_SIZE = 9.31; + static final double SKILL_DESC_SIZE = 6.35; + static final double TOOL_SIZE = 8.11; + static final double PERIOD_SIZE = 8.67; + static final double ROLE_SIZE = 9.42; + static final double EMPLOYER_SIZE = 8.09; + static final double LOCATION_SIZE = 8.76; + static final double HIGHLIGHT_SIZE = 8.02; + static final double PROJECT_TITLE_SIZE = 9.62; + static final double PROJECT_SUB_SIZE = 8.35; + static final double PROJECT_YEAR_SIZE = 8.2; + static final double PROJECT_BODY_SIZE = 8.47; + static final double DEGREE_SIZE = 8.93; + static final double INSTITUTION_SIZE = 8.96; + static final double EDU_DETAIL_SIZE = 8.55; + static final double LANGUAGE_SIZE = 8.49; + static final double LEVEL_SIZE = 7.85; + static final double QUOTE_SIZE = 8.64; + + // -- tracking ---------------------------------------------------------- + + /** + * A space's advance in the body face, as a fraction of the em. + * + *

Deliberately the BODY face's number even though tracking is only ever + * applied to display text: the display face's space is narrow enough that + * a gap of the wanted width would need a space run taller than the type it + * separates, and an inline run sets the line box. The body face's space is + * nearly twice as wide, so the same gap keeps the line box the type's — and + * a space has no glyph to give the substitution away.

+ */ + static final double SPACE_RATIO = 0.256; + + /** + * Tracking in points between one letter and the next. The headings' figure + * is an average over all six: solved one at a time they range too widely + * for any single typeface setting, because the drawing is a raster whose + * glyph advances are not internally consistent — six per-heading constants + * would be fitting noise rather than reproducing a design. + */ + static final double DISCIPLINE_TRACKING = 3.15; + static final double HEADING_TRACKING = 0.77; + + /** Gaps measured as constants whatever the words are, written as spaces. */ + static final String CONTACT_ICON_GAP = " "; + static final String TOOL_GAP = " "; + static final String PIPE = " | "; + static final String RATING_GAP = " "; + static final String QUOTE_GAP = " "; + + // -- the page ---------------------------------------------------------- + + static final double PAGE_MARGIN_X = px(53); + + /** + * Back-calculated rather than measured: the first ink on the page is a cap, + * and a line box starts above its caps, so the margin is where the name's + * box has to begin for its caps to land where the drawing puts them. + */ + static final double PAGE_MARGIN_TOP = px(24); + + /** + * Measured under the quote band, then taken in by three pixels. Nothing on + * this page sits at the bottom margin except the closing band, and the + * drawing puts its lower edge exactly ON the margin — so at the measured + * value the flow has no slack and the band's last points spill onto a + * second page. Three pixels of headroom is the difference between a + * one-page CV and a two-page one. + */ + static final double PAGE_MARGIN_BOTTOM = px(18); + + static final double CONTENT_WIDTH = 595.276 - 2.0 * PAGE_MARGIN_X; + + // -- the masthead ------------------------------------------------------ + + /** Where the contact marks begin, which is where the masthead row splits. */ + static final double CONTACT_COLUMN_X = px(653); + static final double CONTACT_TOP = px(8); + static final double CONTACT_PITCH = px(34.3); + static final double DISCIPLINE_TO_RULE = px(23.3); + static final double IDENTITY_RULE_WIDTH = px(70); + static final double IDENTITY_RULE_THICKNESS = px(4); + + /** + * Measured ink to ink, then corrected by two pixels against the render: + * the measurement is a cap-to-cap distance and what the engine wants is a + * margin under a line BOX, which grew when the name's size was solved. + */ + static final double HEADER_TO_SUMMARY = px(26); + static final double SUMMARY_PITCH = px(22); + + // -- headings ---------------------------------------------------------- + + static final double HEADING_TO_RULE = px(20); + static final double HEADING_RULE_THICKNESS = px(1.5); + + /** + * How far below the heading's line top the rule sits. The drawing centres + * it on the cap band rather than on the line box, and the two differ by + * the leading above the caps. + */ + static final double HEADING_RULE_OFFSET = px(13.5); + + // -- the skills grid --------------------------------------------------- + + static final double SUMMARY_TO_SKILLS = px(33.8); + static final double HEADING_TO_SKILLS = px(19.5); + static final double ICON_TO_LABEL = px(17.4); + static final double LABEL_TO_DESC = px(6); + static final double SKILL_DESC_PITCH = px(18); + static final double SKILL_DIVIDER_THICKNESS = px(2); + + /** + * The gutter between a column's content and the separators either side. + * + *

The drawing gives its widest column more room than six equal columns + * leave, so the label that just fits there is flush here. This is that + * column's own narrowest gutter, applied to every column so the grid keeps + * one rhythm.

+ */ + static final double SKILL_COLUMN_INSET = px(11); + + /** + * The measure the descriptions wrap to, which is narrower than the column. + * + *

Solved from the drawing's own line breaks rather than measured off + * it: greedy-wrapping all six descriptions, each column's breaks are + * reproduced by an interval of measures, and this is the value inside the + * most of them. No single measure reproduces all six — the drawing's own + * metrics disagree with any one face — so five of six is the best + * available.

+ */ + static final double SKILL_DESC_MEASURE = 72.5; + + /** + * The dotted separator's height — the one length on this page that is not + * derived from what it sits beside, and a known limit: a skill whose + * description ran to four lines would outgrow its separator. The + * alternative primitive stretches to the content but cannot be dashed, and + * the dotted rule is a visible feature of the design. + */ + static final double SKILL_RAIL_HEIGHT = px(136); + static final double SKILL_DASH_ON = px(2); + static final double SKILL_DASH_OFF = px(3.15); + + // -- the tools strip --------------------------------------------------- + + static final double SKILLS_TO_TOOLS = px(27.3); + static final double HEADING_TO_TOOLS = px(18.7); + static final double TOOL_DOT_DIAMETER = px(5.2); + + // -- the timeline ------------------------------------------------------ + + static final double TOOLS_TO_EXPERIENCE = px(35.7); + static final double HEADING_TO_ENTRIES = px(19.3); + + /** Where the rail stands, as an indent from the page margin. */ + static final double RAIL_INDENT = px(134.5); + + /** The gap between the rail and an entry's own content. */ + static final double ENTRY_INDENT = px(35.5); + static final double RAIL_THICKNESS = px(2); + static final double MARKER_DIAMETER = px(13.5); + static final double ENTRY_WIDTH = + CONTENT_WIDTH - RAIL_INDENT - ENTRY_INDENT - TABLE_SLACK; + static final double LOCATION_COLUMN = px(200); + static final double ROLE_COLUMN = ENTRY_WIDTH - LOCATION_COLUMN; + + /** The dates sit back at the page margin, outside the rail. */ + static final double DATE_OFFSET = -(RAIL_INDENT + ENTRY_INDENT); + + /** Half the disc, plus the indent, puts its centre on the border. */ + static final double MARKER_OFFSET = -(ENTRY_INDENT + MARKER_DIAMETER / 2.0); + + static final double BULLET_COLUMN = px(16); + static final double BULLET_DOT_DIAMETER = px(6); + static final double BULLET_PITCH = px(20.5); + static final double TITLE_TO_BULLETS = px(6.1); + static final double ENTRY_GAP = px(24); + + // -- the projects ------------------------------------------------------ + + static final double EXPERIENCE_TO_PROJECTS = px(27.6); + static final double HEADING_TO_PROJECTS = px(15.1); + static final double PROJECT_GAP = px(17.4); + static final double THUMB_COLUMN = px(138.5); + static final double THUMB_PAD_LEFT = px(21); + static final double THUMB_WIDTH = px(80); + static final double THUMB_HEIGHT = px(76); + static final double THUMB_RADIUS = px(10); + static final double PROJECT_COPY_INDENT = px(34.5); + static final double PROJECT_RULE_THICKNESS = px(2); + static final double PROJECT_COPY_WIDTH = + CONTENT_WIDTH - THUMB_COLUMN - PROJECT_COPY_INDENT - TABLE_SLACK; + static final double PROJECT_YEAR_COLUMN = px(120); + static final double PROJECT_TITLE_COLUMN = PROJECT_COPY_WIDTH - PROJECT_YEAR_COLUMN; + static final double TITLE_TO_BODY = px(3.6); + static final double PROJECT_BODY_PITCH = px(19.5); + + // -- the credentials band ---------------------------------------------- + + static final double PROJECTS_TO_CREDENTIALS = px(15.7); + static final double EDUCATION_COLUMN = px(430); + static final double CREDENTIAL_GUTTER = px(70); + static final double LANGUAGES_COLUMN = + CONTENT_WIDTH - EDUCATION_COLUMN - CREDENTIAL_GUTTER - TABLE_SLACK; + + /** How the two heading rules split what the two heading texts leave. */ + static final double EDUCATION_RULE_WEIGHT = 335.0 / 680.0; + static final double LANGUAGES_RULE_WEIGHT = 345.0 / 680.0; + + static final double HEADING_TO_EDUCATION = px(13.5); + static final double BADGE_DIAMETER = px(72); + static final double BADGE_COLUMN = px(91); + static final double EDUCATION_TEXT_TOP = px(4.1); + static final double DEGREE_TO_INSTITUTION = px(3); + static final double INSTITUTION_TO_DETAIL = px(8.7); + + /** + * The languages rows start a shade below where the education badge does. + * The bodies row already carries the heading gap; this is only the + * difference between the two halves. + */ + static final double LANGUAGES_BODY_OFFSET = px(15.8 - 13.5); + + static final double LANGUAGE_NAME_COLUMN = px(162); + static final double LANGUAGE_LEVEL_COLUMN = px(194); + static final double LANGUAGE_RATING_COLUMN = + LANGUAGES_COLUMN - LANGUAGE_NAME_COLUMN - LANGUAGE_LEVEL_COLUMN; + static final double LANGUAGE_PITCH = px(27.5); + static final double RATING_DOT_DIAMETER = px(10); + + /** How many discs a rating is drawn out of. */ + static final int RATING_SCALE = 5; + + // -- the closing band -------------------------------------------------- + + static final double CREDENTIALS_TO_QUOTE = px(24); + static final double QUOTE_RADIUS = px(6); + static final double QUOTE_PAD_H = px(40); + + /** + * The line box the band has to hold. The quotation mark is taller than the + * type beside it, and an inline run taller than its paragraph's line box is + * drawn clipped — so the box is the mark's height. + */ + static final double QUOTE_LINE_BOX = + Math.max(QUOTE_SIZE * LINE_FACTOR, VioletGridIcons.size(VioletGridIcons.QUOTE)); + + /** The band's measured height less what it holds, halved. */ + static final double QUOTE_PAD_V = (px(48) - QUOTE_LINE_BOX) / 2.0; + + // -- 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(); + } + + /** 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 pitch 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 pitch, double size) { + return Math.max(0.0, pitch - LINE_FACTOR * size); + } + + /** How far to drop a mark of this height to centre it on a title's line box. */ + static double centred(double markHeight) { + return Math.max(0.0, (ROLE_SIZE * LINE_FACTOR - markHeight) / 2.0); + } +} diff --git a/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridWidgets.java b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridWidgets.java new file mode 100644 index 000000000..6b215eeab --- /dev/null +++ b/templates/src/main/java/com/demcha/compose/document/templates/cv/presets/VioletGridWidgets.java @@ -0,0 +1,147 @@ +package com.demcha.compose.document.templates.cv.presets; + +import com.demcha.compose.document.dsl.ParagraphBuilder; +import com.demcha.compose.document.dsl.RowBuilder; +import com.demcha.compose.document.node.DocumentNode; +import com.demcha.compose.document.node.InlineImageAlignment; +import com.demcha.compose.document.style.DocumentColor; +import com.demcha.compose.document.style.DocumentInsets; +import com.demcha.compose.document.style.DocumentRowColumn; +import com.demcha.compose.document.style.DocumentTextStyle; +import com.demcha.compose.font.FontName; + +import java.util.ArrayList; +import java.util.List; + +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ACCENT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.ACCENT_RULE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.BODY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.DISPLAY_FONT; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_RULE_OFFSET; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_RULE_THICKNESS; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_SIZE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TRACKING; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.HEADING_TO_RULE; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.SPACE_RATIO; +import static com.demcha.compose.document.templates.cv.presets.VioletGridStyles.style; + +/** + * The idioms this sheet repeats: the letter-spaced run, the heading followed + * by its hairline, a disc on its own, and a line of text as a node. + */ +final class VioletGridWidgets { + + private VioletGridWidgets() { + } + + /** + * Letter-spaced text, as one inline run per character. + * + *

A text style carries no tracking, so the gap between two letters is a + * space run set at whatever size makes that space the wanted number of + * points wide — which is why the tracking is a number rather than a fixed + * word space. The gap is set in the BODY face even under display text: the + * display face's space is narrow enough that the wanted gap would need a + * run taller than the type it separates, and an inline run sets the line + * box. A space has no glyph to give the substitution away.

+ * + * @param name the node name + * @param text the text to space out + * @param font the face the letters are set in + * @param size the size the letters are set at + * @param color the colour of the letters + * @param bold whether the letters are bold + * @param tracking the gap in points; zero or less writes the text plainly + * @return the paragraph, unbuilt, so a caller can still give it a margin + */ + static ParagraphBuilder tracked(String name, String text, FontName font, double size, + DocumentColor color, boolean bold, double tracking) { + DocumentTextStyle glyph = style(font, size, color, bold); + ParagraphBuilder paragraph = new ParagraphBuilder(); + paragraph.name(name); + paragraph.lineSpacing(0); + paragraph.textStyle(glyph); + if (tracking <= 0.0) { + paragraph.text(text); + return paragraph; + } + DocumentTextStyle gap = style(BODY_FONT, tracking / SPACE_RATIO, color, bold); + for (int index = 0; index < text.length(); index++) { + paragraph.inlineText(String.valueOf(text.charAt(index)), glyph); + if (index < text.length() - 1) { + paragraph.inlineText(" ", gap); + } + } + return paragraph; + } + + /** + * A tracked caps heading followed by a hairline to the right margin. + * + *

The text column takes what its words need and the rule column takes + * what is left, which is what makes the rule start where the text ends + * without anything having to know how wide the text is. Returned as a node + * rather than added to a builder, so one method serves callers holding + * different builder types.

+ */ + static DocumentNode headingRow(String name, String text, double topMargin) { + RowBuilder row = new RowBuilder(); + row.name(name + "Heading"); + row.spacing(0); + row.margin(new DocumentInsets(topMargin, 0, 0, 0)); + row.columns(DocumentRowColumn.auto(), DocumentRowColumn.weight(1.0)); + row.addSection(name + "HeadingText", cell -> { + cell.spacing(0); + cell.add(tracked(name + "HeadingLabel", text, DISPLAY_FONT, HEADING_SIZE, + ACCENT, true, HEADING_TRACKING).build()); + }); + row.addSection(name + "HeadingRule", cell -> { + cell.spacing(0); + cell.padding((float) HEADING_RULE_OFFSET, 0f, 0f, (float) HEADING_TO_RULE); + cell.addLine(line -> line + .name(name + "HeadingRuleLine") + .fill() + .thickness(HEADING_RULE_THICKNESS) + .color(ACCENT_RULE)); + }); + return row.build(); + } + + /** A disc on its own, in a paragraph whose line box is set by its type. */ + static DocumentNode markerDot(String name, double diameter, double boxSize, + DocumentColor fill) { + ParagraphBuilder paragraph = new ParagraphBuilder(); + paragraph.name(name); + paragraph.lineSpacing(0); + paragraph.textStyle(style(BODY_FONT, boxSize, fill, false)); + paragraph.dot(diameter, fill); + return paragraph.build(); + } + + /** One line of text as a node. */ + static DocumentNode text(String name, String value, DocumentTextStyle textStyle) { + return new ParagraphBuilder() + .name(name) + .text(value) + .lineSpacing(0) + .textStyle(textStyle) + .build(); + } + + /** Places a mark inline, on the baseline of the paragraph it opens. */ + static void inlineIcon(ParagraphBuilder paragraph, String token) { + paragraph.inlineSvgIcon(VioletGridIcons.icon(token), VioletGridIcons.size(token), + InlineImageAlignment.CENTER); + } + + /** A body, one entry per line the document wrote. */ + 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; + } +} diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/design-systems.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/design-systems.svg new file mode 100644 index 000000000..abccd250f --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/design-systems.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/email.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/email.svg new file mode 100644 index 000000000..24628a6eb --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/graduation.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/graduation.svg new file mode 100644 index 000000000..f89ae1c16 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/graduation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/information-architecture.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/information-architecture.svg new file mode 100644 index 000000000..ebadcc790 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/information-architecture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/linkedin.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/linkedin.svg new file mode 100644 index 000000000..ab2d1bd8e --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/linkedin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/location.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/location.svg new file mode 100644 index 000000000..fde000d03 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/phone.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/phone.svg new file mode 100644 index 000000000..7c823dae3 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/project-health.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/project-health.svg new file mode 100644 index 000000000..d42590cf3 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/project-health.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/project-wallet.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/project-wallet.svg new file mode 100644 index 000000000..70bd4b1c6 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/project-wallet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/prototyping.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/prototyping.svg new file mode 100644 index 000000000..6dc414529 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/prototyping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/quote.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/quote.svg new file mode 100644 index 000000000..281a38b10 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/quote.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/usability-testing.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/usability-testing.svg new file mode 100644 index 000000000..b2857b690 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/usability-testing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/ux-research.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/ux-research.svg new file mode 100644 index 000000000..31f42319d --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/ux-research.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/website.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/website.svg new file mode 100644 index 000000000..faddf384b --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/website.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/src/main/resources/templates/cv/violet-grid/icons/wireframing.svg b/templates/src/main/resources/templates/cv/violet-grid/icons/wireframing.svg new file mode 100644 index 000000000..0273be191 --- /dev/null +++ b/templates/src/main/resources/templates/cv/violet-grid/icons/wireframing.svg @@ -0,0 +1 @@ + \ No newline at end of file
kqGDl7Qse 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 split is local to one band