// SPDX-FileCopyrightText: 2025 Ethan Reece // // SPDX-License-Identifier: LGPL-3.0-or-later #import "@preview/fontawesome:0.5.0": fa-icon #import "@preview/linguify:0.4.2": linguify #let reset(body) = text(font: "Inter", size: 10pt, weight: "regular", body) #let lang-data = toml("lang.toml") #let l(content) = linguify(content, from: lang-data) #let name(below: 0em, size: 0em, body) = reset(block( width: 100%, below: below, text(size: size, weight: "extrabold", align(center, body)), )) #let section-heading(above: 0em, below: 0em, body) = reset(block( width: 100%, above: above, below: below, text(size: 1.3em, weight: "bold", body), )) #let left_pad(body) = pad(left: 1em, body) #let base( lang: "en", region: "US", self: (:), name-below: 0em, name-size: 0em, body, ) = text( lang: lang, region: region, reset( page( paper: "us-letter", margin: (x: 0.5in, y: 0.4in), { set document( title: lang-data.lang.at(text.lang).Resume, author: self.package.authors, description: self.package.description, keywords: self.package.keywords, ) set list( marker: text(weight: "extralight", size: 0.95em, sym.dash.en), indent: 0.25em, body-indent: 1.5em, tight: false, spacing: 0.85em, ) set text(size: 0.95em) set par(spacing: 0em, justify: true) show list: it => left_pad(it) show par: it => block(width: 100%, it) show raw: it => text(font: "JetBrains Mono", it) show heading.where(level: 1): it => name( below: name-below, size: name-size, it.body, ) show heading.where(level: 2): it => section-heading( above: 1.1em, below: 0.8em, it.body, ) body }, ), ), ) #let contact(gutter: 0em, below: 0em, ..methods) = reset(block( width: 100%, below: below, text( size: 1.05em, weight: "medium", align( center + horizon, grid(columns: methods.pos().len(), rows: 1, gutter: gutter, ..methods), ), ), )) #let contact-method(title: "", icon: "") = grid( rows: 1, columns: 2, gutter: .9em, fa-icon(icon, solid: true), title, ) #let Skills = l("Skills") #let Education = l("Education") #let Experience = l("Experience") #let Organizations = l("Organizations") #let Projects = l("Projects") #let Volunteering = l("Volunteering") #let skills-grid(..skills) = reset(left_pad(grid( columns: 2, gutter: 1em, ..for skill in skills.pos() { ( heading(level: 3, text(weight: "semibold", size: 0.95em, skill.title)), text(size: 0.95em, skill.items.join(", ")), ) } ))) #let item-heading( title: "", subtitle: "", long-subtitle: false, timeframe: "", location: "", type: "", skills: (), condensed: false, below: 0em, above: 0em, ) = { let gutter = 0.6em let subtitle_text = text(weight: "light", size: 0.9em, subtitle) let location_text = text(size: 0.85em, weight: "extralight", location) let skills_text = text(weight: "light", size: 0.9em, skills.join(", ")) let type_text = text(weight: "light", size: 0.85em, type) reset(block( below: below, above: above, left_pad( grid( columns: 1, rows: 2, gutter: gutter, grid( columns: (auto, 1fr), rows: 1, gutter: gutter, align: (left + bottom, right + bottom), grid( columns: 2, rows: 1, column-gutter: 1.5em, row-gutter: gutter, align: bottom, heading(level: 3, text(weight: "semibold", title)), type_text, ), text(weight: "regular", timeframe), ), if long-subtitle { grid( columns: 1, rows: 2, gutter: gutter, subtitle_text, grid( columns: (auto, 1fr), rows: 1, gutter: gutter, align: (left + bottom, right + bottom), location_text, skills_text, ), ) } else if condensed { grid( columns: (auto, 1fr), rows: 1, gutter: gutter, align: (left + bottom, right + bottom), subtitle_text, location_text, ) } else { grid( columns: (auto, 1fr), rows: 1, gutter: gutter, align: (left + bottom, right + bottom), grid( columns: 2, rows: 1, column-gutter: 1.5em, row-gutter: gutter, align: bottom, subtitle_text, location_text, ), skills_text, ) }, ), ), )) }