From 40fef308c54c313440c97771aa1c59415476f489 Mon Sep 17 00:00:00 2001 From: Yichen Han Date: Thu, 12 Feb 2026 13:49:47 +0100 Subject: [PATCH] calmly-touying:0.2.0 --- packages/preview/calmly-touying/0.2.0/LICENSE | 21 + .../preview/calmly-touying/0.2.0/README.md | 533 ++++++++ packages/preview/calmly-touying/0.2.0/lib.typ | 8 + .../calmly-touying/0.2.0/template/main.typ | 194 +++ .../calmly-touying/0.2.0/theme/colors.typ | 500 ++++++++ .../calmly-touying/0.2.0/theme/components.typ | 525 ++++++++ .../calmly-touying/0.2.0/theme/slides.typ | 1076 +++++++++++++++++ .../0.2.0/theme/syntax-themes/Dracula.tmTheme | 535 ++++++++ .../theme/syntax-themes/GitHub-Dark.tmTheme | 641 ++++++++++ .../theme/syntax-themes/GitHub-Light.tmTheme | 643 ++++++++++ .../Tomorrow-Night-Eighties.tmTheme | 247 ++++ .../syntax-themes/Tomorrow-Night.tmTheme | 247 ++++ .../theme/syntax-themes/Tomorrow.tmTheme | 247 ++++ .../calmly-touying/0.2.0/theme/theme.typ | 313 +++++ .../calmly-touying/0.2.0/theme/typography.typ | 95 ++ .../calmly-touying/0.2.0/thumbnail.png | Bin 0 -> 53559 bytes .../preview/calmly-touying/0.2.0/typst.toml | 23 + 17 files changed, 5848 insertions(+) create mode 100644 packages/preview/calmly-touying/0.2.0/LICENSE create mode 100644 packages/preview/calmly-touying/0.2.0/README.md create mode 100644 packages/preview/calmly-touying/0.2.0/lib.typ create mode 100644 packages/preview/calmly-touying/0.2.0/template/main.typ create mode 100644 packages/preview/calmly-touying/0.2.0/theme/colors.typ create mode 100644 packages/preview/calmly-touying/0.2.0/theme/components.typ create mode 100644 packages/preview/calmly-touying/0.2.0/theme/slides.typ create mode 100644 packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Dracula.tmTheme create mode 100644 packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Dark.tmTheme create mode 100644 packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Light.tmTheme create mode 100644 packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night-Eighties.tmTheme create mode 100644 packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night.tmTheme create mode 100644 packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow.tmTheme create mode 100644 packages/preview/calmly-touying/0.2.0/theme/theme.typ create mode 100644 packages/preview/calmly-touying/0.2.0/theme/typography.typ create mode 100644 packages/preview/calmly-touying/0.2.0/thumbnail.png create mode 100644 packages/preview/calmly-touying/0.2.0/typst.toml diff --git a/packages/preview/calmly-touying/0.2.0/LICENSE b/packages/preview/calmly-touying/0.2.0/LICENSE new file mode 100644 index 0000000000..4ebda371ea --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Yichen Han + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/preview/calmly-touying/0.2.0/README.md b/packages/preview/calmly-touying/0.2.0/README.md new file mode 100644 index 0000000000..b7fe3af7e6 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/README.md @@ -0,0 +1,533 @@ +# Calmly - Touying Presentation Theme + +A modern, minimalist presentation theme for [Touying](https://github.com/touying-typ/touying). Calm, approachable, and intelligent—designed to let your content shine. + +[![Typst Universe](https://img.shields.io/badge/Typst_Universe-calmly--touying-blue)](https://typst.app/universe/package/calmly-touying) +![License](https://img.shields.io/badge/license-MIT-blue.svg) +![Typst](https://img.shields.io/badge/typst-0.12+-blue.svg) +![Touying](https://img.shields.io/badge/touying-0.6.1-orange.svg) + +## Installation + +### From [Typst Universe](https://typst.app/universe/package/calmly-touying) + +Use the template directly: + +```bash +# Create a new presentation from template +typst init @preview/calmly-touying:0.2.0 my-presentation +cd my-presentation +typst compile main.typ +``` + +Or import it in an existing project: + +```typst +#import "@preview/calmly-touying:0.2.0": * +``` + +### Local Development + +For local development or contributing, see the [GitHub repository](https://github.com/YHan228/calmly-touying). + +## Features + +- **Four Color Themes**: Tomorrow, Warm Amber, Paper, and Dracula palettes +- **Light/Dark Variants**: Adapt to different venues and preferences +- **Moloch-Inspired Design**: Clean headers, progress bars, and academic styling +- **Multiple Slide Types**: Title, content, focus, standout, section, figure, equation, and more +- **Rich Components**: Highlight boxes, alert/example boxes, algorithm containers, citation gadgets +- **Progressive Reveals**: `#only()` and `#pause` for animations +- **Golden Ratio Spacing**: Mathematically pleasing proportions +- **Bibliography Integration**: Styled citations and reference slides + +## Quick Start + +```typst +#import "@preview/calmly-touying:0.2.0": * + +#show: calmly.with( + config-info( + title: [Your Presentation Title], + subtitle: [Event or Context], + author: [Your Name], + date: datetime.today(), + institution: [Your Institution], + ), +) + +#title-slide() + +== First Slide + +Your content here... + +- Bullet points are styled automatically +- *Emphasis* and **strong text** work as expected + +#focus-slide[ + Key Takeaway Message +] + +#ending-slide( + contact: ("email@example.com", "github.com/username"), +) +``` + +## Configuration Options + +The theme supports extensive customization through configuration options: + +```typst +#show: calmly.with( + config-info( + title: [Your Title], + author: [Your Name], + ), + variant: "light", // "light" | "dark" + colortheme: "tomorrow", // "tomorrow" | "warm-amber" | "paper" | "dracula" + progressbar: "foot", // "foot" | "head" | "frametitle" | "none" + header-style: "moloch", // "moloch" | "minimal" + title-layout: "moloch", // "moloch" | "centered" | "split" +) +``` + +| Option | Values | Description | +|--------|--------|-------------| +| `variant` | `"light"`, `"dark"` | Color mode for the presentation | +| `colortheme` | `"tomorrow"`, `"warm-amber"`, `"paper"`, `"dracula"` | Color palette (tomorrow is default) | +| `progressbar` | `"foot"`, `"head"`, `"frametitle"`, `"none"` | Progress bar position | +| `header-style` | `"moloch"`, `"minimal"` | Slide header style (colored bar vs underline) | +| `title-layout` | `"moloch"`, `"centered"`, `"split"` | Title slide layout variant | + +### Color Themes + +- **Tomorrow** (default): Programmer-friendly palette based on Tomorrow theme. Balanced colors. +- **Warm Amber**: Soft, warm tones with amber accents. Premium, modern feel. +- **Paper**: High contrast black/white with blue accents. Academic style. +- **Dracula**: Purple and pink accents. + +## Slide Types + +### Title Slide +```typst +#title-slide() +#title-slide(layout: "centered") // Alternative layouts +#title-slide(layout: "split") +``` + +### Content Slides +Standard slides are created automatically with level-2 headings: +```typst +== Slide Title + +Content goes here... +``` + +### Focus Slide +Full-bleed accent gradient background for emphasis: +```typst +#focus-slide[ + Important statement or takeaway +] +``` + +### Standout Slide +High-contrast background for maximum emphasis: +```typst +#standout-slide[ + Key Message +] +``` + +### Section Slide +Clean section dividers with optional progress: +```typst +#section-slide[Methods] +#section-slide(show-progress: true)[Results] +``` + +### Figure Slide +Centered figure with optional caption: +```typst +#figure-slide( + image("figure.svg"), + title: [Figure Title], + caption: [Description of the figure], +) +``` + +### Split Figure Slide +Two figures side-by-side: +```typst +#figure-slide-split( + image("left.svg"), + image("right.svg"), + title: [Comparison], + caption-left: [Before], + caption-right: [After], +) +``` + +### Equation Slide +Centered equation with definition box and optional citation: +```typst +#equation-slide( + $E = m c^2$, + title: [Mass-Energy Equivalence], + subtitle: [Einstein's famous equation], + definitions: [ + $E$ — Energy \ + $m$ — Mass \ + $c$ — Speed of light + ], + citation: (bib-key: "einstein1905", label: "Einstein 1905"), +) +``` + +### Bibliography Slide +```typst +#bibliography-slide(bib-content: bibliography("refs.bib", title: none, style: "apa")) +``` + +### Acknowledgement Slide +```typst +#acknowledgement-slide( + subtitle: [We thank the following], + people: ( + (name: "Prof. Smith", role: "Supervisor"), + (name: "Dr. Jones", role: "Advisor"), + ), + institutions: ("University A", "Lab B"), + extra: [Special thanks to all contributors.], +) +``` + +### Ending Slide +```typst +#ending-slide( + title: [Thank You], + subtitle: [Questions?], + contact: ("email@example.com", "github.com/username"), +) +``` + +## Components + +### Box Components + +```typst +// Key concepts and summaries +#highlight-box(title: "Key Point")[ + Important information here. +] + +// Warnings and critical notes +#alert-box(title: "Warning")[ + Critical information. +] + +// Examples and demonstrations +#example-box(title: "Example")[ + Illustrative content. +] + +// Generic themed container +#themed-block(title: "Block Title")[ + General content. +] +#themed-block(title: "Filled", fill-mode: "fill")[Filled background.] +``` + +### Algorithm Box +```typst +#algorithm-box(title: "Algorithm 1: Example")[ + *Input:* Data $X$ \ + *Output:* Result $Y$ \ + 1: Process data \ + 2: Return result +] +``` + +### Text Helpers +```typst +This is #alert[important] information. // Accent colored +This is #muted[secondary] information. // Muted grey +This is #subtle[tertiary] information. // Light subtle +``` + +### Citations + +**Inline Citations** (grey-boxed): +```typst +Recent work has shown improvements @smith2023. +``` +Renders with a subtle grey background pill. + +**Citation Box** (positioned in corners): +```typst +#cite-box("key", display-label: "Author 2023", position: "bottom-right") + +// Multiple citations +#cite-box( + ("key1", "key2"), + display-label: "Author1; Author2", + position: "top-right" +) +``` +Positions: `"top-right"`, `"bottom-left"`, `"bottom-right"` + +### Multi-Column Layouts +```typst +#two-col( + [Left column content], + [Right column content], +) + +#three-col([A], [B], [C]) +``` + +## Progressive Reveals + +### Using `#only(n)[...]` +Show content only on specific sub-slides: +```typst +== Building Concepts + +#only(1)[Step 1: Introduction] +#only(2)[Step 2: Details] +#only(3)[Step 3: Conclusion] +``` + +### Using `#pause` +Reveal content progressively: +```typst +== Points + +- First point +#pause +- Second point (appears after click) +#pause +- Third point +``` + +## Spacing Utilities + +### Flexible Spacing +```typst +#v(1fr) // Flexible vertical space +#v(spacing-md) // Fixed spacing (16pt) +``` + +### Vertical Centering +```typst +#v(1fr) +#align(center)[Centered content] +#v(1fr) +``` + +### Spacing Constants +| Constant | Size | +|----------|------| +| `spacing-xs` | 6pt | +| `spacing-sm` | 10pt | +| `spacing-md` | 16pt | +| `spacing-lg` | 24pt | +| `spacing-xl` | 36pt | +| `spacing-2xl` | 48pt | + +### Typography Constants +| Constant | Size | +|----------|------| +| `size-display` | 42pt | +| `size-title` | 34pt | +| `size-slide-title` | 26pt | +| `size-body` | 17pt | +| `size-small` | 15pt | +| `size-caption` | 13pt | + +### Golden Ratio Utilities +| Constant | Description | +|----------|-------------| +| `phi` | 1.618... golden ratio constant | +| `golden-major` | ~0.618 proportion | +| `golden-minor` | ~0.382 proportion | +| `golden-center(body)` | Vertically center with golden ratio offset | + +## Customization + +### Colors +Edit `theme/colors.typ` to customize the color palette. Each theme defines: +- Accent colors (primary, secondary, subtle) +- Background hierarchy (base, elevated, muted, surface) +- Text hierarchy (primary, secondary, muted) +- Functional colors (alert, example, focus) + +### Typography +Edit `theme/typography.typ` for font settings: + +```typst +#let font-heading = ("Source Sans Pro", "Noto Sans", "sans-serif") +#let font-body = ("Source Sans Pro", "Noto Sans", "sans-serif") +#let font-mono = ("JetBrains Mono", "Fira Code", "monospace") +``` + +### Recommended Fonts +For best results, install: +- [Source Sans Pro](https://fonts.google.com/specimen/Source+Sans+3) +- [JetBrains Mono](https://www.jetbrains.com/lp/mono/) +- [STIX Two Math](https://github.com/stipub/stixfonts) + +The theme will gracefully fall back to system fonts if these aren't available. + +## Examples + +The `examples/` directory contains several templates: + +| File | Description | +|------|-------------| +| `feature-showcase.typ` | Complete feature demonstration | +| `academic-talk.typ` | Realistic research presentation | +| `dark-variant.typ` | Dark mode example | +| `paper-theme.typ` | Paper color theme | +| `dracula-theme.typ` | Dracula color theme | +| `centered-title.typ` | Centered title layout | + +## File Structure + +```text +calmly-touying/ +├── typst.toml # Package manifest +├── lib.typ # Package entrypoint +├── LICENSE # MIT License +├── README.md +├── thumbnail.png # Package thumbnail (for Universe listing) +├── theme/ +│ ├── theme.typ # Main theme configuration +│ ├── colors.typ # Color palettes (4 themes × 2 variants) +│ ├── typography.typ # Font settings and spacing +│ ├── components.typ # Reusable components (30+) +│ ├── slides.typ # Slide type definitions +│ └── syntax-themes/ # .tmTheme files for code syntax highlighting +├── template/ # Starter template (for typst init) +│ └── main.typ # Template entry point +└── examples/ # Example presentations +``` + +## Building + +```bash +typst compile main.typ +``` + +Or use `typst watch main.typ` for live preview. + +## License + +MIT License - feel free to use and modify for your presentations. + +## Credits & References + +- Built on [Touying](https://github.com/touying-typ/touying) presentation framework by OrangeX4 +- Layout inspired by [Moloch](https://github.com/jolars/moloch) (Beamer theme) by Johan Larsson, itself based on [Metropolis](https://github.com/matze/mtheme) by Matthias Vogelgesang +- Color palette based on [Tailwind CSS](https://tailwindcss.com/docs/colors) Stone and Amber scales + +--- + +## Function Reference + +### Modified from Touying + +These functions wrap or extend Touying's base functionality: + +| Function | Description | +|----------|-------------| +| `slide()` | Enhanced slide with Moloch headers and progress bars | +| `title-slide()` | Router for title layout variants | +| `title-slide-moloch()` | Left-aligned title with separator line | +| `title-slide-centered()` | Centered title with accent underline | +| `title-slide-split()` | Two-column title with vertical separator | +| `focus-slide()` | Gradient background emphasis slide | +| `standout-slide()` | High-contrast emphasis slide | +| `section-slide()` | Section divider with optional progress | +| `figure-slide()` | Single centered figure display | +| `figure-slide-split()` | Side-by-side figure comparison | +| `equation-slide()` | Equation with definitions and citation | +| `acknowledgement-slide()` | People and institution cards | +| `ending-slide()` | Thank you / closing slide | +| `bibliography-slide()` | Styled references slide | + +### Created for This Theme + +**Layout Helpers** (`components.typ`): +| Function | Description | +|----------|-------------| +| `two-col()` | Two-column grid layout | +| `three-col()` | Three-column grid layout | +| `spacer()` | Vertical spacing helper | + +**Box Components** (`components.typ`): +| Function | Description | +|----------|-------------| +| `highlight-box()` | Left-accent gradient box with title | +| `alert-box()` | Red-accented warning box | +| `example-box()` | Green-accented example box | +| `themed-block()` | Generic themed container | +| `algorithm-box()` | Code/algorithm container with header | +| `quote-block()` | Blockquote with attribution | +| `code-block()` | Styled code display | +| `soft-shadow-box()` | Elevated box with subtle stroke | + +**Text Helpers** (`components.typ`): +| Function | Description | +|----------|-------------| +| `alert()` | Accent-colored inline text | +| `muted()` | Grey muted text | +| `subtle()` | Light subtle text | +| `fig-caption()` | Italic figure caption | + +**Visual Elements** (`components.typ`): +| Function | Description | +|----------|-------------| +| `cite-box()` | Corner-positioned citation gadget | +| `accent-line()` | Gradient accent line | +| `soft-divider()` | Subtle horizontal divider | +| `pill()` | Rounded tag/label | +| `bullet-circle()` | Level 1 bullet marker | +| `bullet-square()` | Level 2 bullet marker | +| `bullet-dash()` | Level 3 bullet marker | + +**Card Components** (`components.typ`): +| Function | Description | +|----------|-------------| +| `person-card()` | Person display with optional image | +| `institution-card()` | Institution logo/name display | +| `contact-item()` | Contact info helper | + +**Color System** (`colors.typ`): +| Function | Description | +|----------|-------------| +| `get-theme-colors()` | Get color palette by theme/variant | +| `make-gradients()` | Generate gradient definitions | +| `resolve-theme-colors()` | Resolve colors from param or state | +| `get-color-from()` | Safe dictionary access with fallback | + +**Golden Ratio** (`typography.typ`): +| Function | Description | +|----------|-------------| +| `phi` | Golden ratio constant (1.618...) | +| `golden-center()` | Golden-ratio vertical centering | +| `golden-major` | ~0.618 proportion | +| `golden-minor` | ~0.382 proportion | +| `golden-split-left` | ~38.2% width for layouts | +| `golden-split-right` | ~61.8% width for layouts | + +**Theme Entry** (`theme.typ`): +| Function | Description | +|----------|-------------| +| `calmly()` | Main theme configuration function | +| `warm-amber-theme` | Backward compatibility alias | +| `thesis-theme` | Alias for calmly | +| `moloch-style-theme` | Preconfigured Moloch settings | +| `minimal-style-theme` | Preconfigured minimal settings | +| `dark-theme` | Preconfigured dark variant | diff --git a/packages/preview/calmly-touying/0.2.0/lib.typ b/packages/preview/calmly-touying/0.2.0/lib.typ new file mode 100644 index 0000000000..b4466ab9b2 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/lib.typ @@ -0,0 +1,8 @@ +// Calmly-Touying - A calm, modern presentation theme +// https://github.com/YHan228/calmly-touying + +// Re-export everything from the theme module +#import "theme/theme.typ": * + +// Re-export Touying core utilities that users commonly need +#import "@preview/touying:0.6.1": pause, only, uncover, alternatives, config-info diff --git a/packages/preview/calmly-touying/0.2.0/template/main.typ b/packages/preview/calmly-touying/0.2.0/template/main.typ new file mode 100644 index 0000000000..a267414a5b --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/template/main.typ @@ -0,0 +1,194 @@ +// Calmly-Touying Presentation Template +// A calm, modern presentation theme with Moloch-inspired design +// +// Documentation: https://github.com/YHan228/calmly-touying + +#import "@preview/calmly-touying:0.2.0": * + +// Configure your presentation +#show: calmly.with( + config-info( + title: [Your Presentation Title], + subtitle: [Conference or Event Name], + author: [Your Name], + date: datetime.today(), + institution: [Your Institution], + ), + // Theme options (all optional): + // variant: "light", // "light" | "dark" + // colortheme: "tomorrow", // "tomorrow" | "warm-amber" | "paper" | "dracula" + // progressbar: "foot", // "foot" | "head" | "frametitle" | "none" + // header-style: "moloch", // "moloch" | "minimal" + // title-layout: "moloch", // "moloch" | "centered" | "split" +) + +#title-slide() + +// ============================================================================= +// Introduction +// ============================================================================= + +#section-slide[Introduction] + +== Motivation + +#highlight-box(title: "Research Question")[ + What problem are you solving, and why does it matter? +] + +#v(0.8em) + +- Provide context and background +- State the gap in existing work +- #alert[Highlight] the key challenge + +#v(1fr) + +== Approach + +#v(1fr) + +#two-col( + [ + #alert-box(title: "Existing Methods")[ + Describe limitations of prior approaches. + ] + ], + [ + #example-box(title: "Our Contribution")[ + Explain what your work adds. + ] + ], +) + +#v(2fr) + +// ============================================================================= +// Methods +// ============================================================================= + +#section-slide[Methods] + +== Algorithm + +Code blocks get automatic syntax highlighting matched to your color theme: + +```python +def gradient_descent(f, x0, lr=0.01): + x = x0 + for _ in range(1000): + x -= lr * grad(f, x) + return x +``` + +#themed-block(title: "Complexity")[ + Time: $O(n dot T)$ where $T$ is the number of iterations. +] + +== Pseudocode + +#algorithm-box(title: "Algorithm 1: Gradient Descent")[ + *Input:* Function $f$, initial point $x_0$, learning rate $eta$ \ + *Output:* Approximate minimizer $x^*$ + + 1: $x <- x_0$ \ + 2: *for* $t = 1, 2, dots, T$ *do* \ + 3: #h(1em) $g <- nabla f(x)$ \ + 4: #h(1em) $x <- x - eta dot g$ \ + 5: *end for* \ + 6: *return* $x$ +] + +#v(1fr) + +== Formulation + +#v(1fr) + +#two-col( + [ + The objective function: + + $ min_theta L(theta) = -1/n sum_(i=1)^n log p(x_i | theta) $ + ], + [ + *Key variables* + + - $theta$ --- model parameters + - $x_i$ --- observed data points + - $n$ --- sample size + ], +) + +#v(2fr) + +// ============================================================================= +// Results +// ============================================================================= + +#section-slide(show-progress: true)[Results] + +== Comparison + +#v(1fr) + +#table( + columns: (1fr, auto, auto, auto), + stroke: 0.5pt + luma(200), + inset: 8pt, + table.header( + [*Method*], [*Precision*], [*Recall*], [*F1*], + ), + [Baseline], [0.72], [0.68], [0.70], + [Improved], [0.85], [0.81], [0.83], + [*Ours*], [*0.91*], [*0.89*], [*0.90*], +) + +#v(2fr) + +// ============================================================================= +// Conclusion +// ============================================================================= + +// Use #focus-slide for high-impact statements: +// #focus-slide[Key Takeaway Message] + +#section-slide[Conclusion] + +== Summary + +#three-col( + [ + *Problem* + + Clearly defined the research gap. + ], + [ + *Method* + + Proposed a novel approach with formal guarantees. + ], + [ + *Result* + + Achieved state-of-the-art on standard benchmarks. + ], +) + +#v(1em) + +#alert-box(title: "Future Work")[ + - Extend to larger-scale datasets + - Explore alternative architectures +] + +#v(1fr) + +#ending-slide( + title: [Thank You], + subtitle: [Questions?], + contact: ( + "your.email@example.com", + "github.com/yourusername", + ), +) diff --git a/packages/preview/calmly-touying/0.2.0/theme/colors.typ b/packages/preview/calmly-touying/0.2.0/theme/colors.typ new file mode 100644 index 0000000000..5bd2a589d4 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/colors.typ @@ -0,0 +1,500 @@ +// Warm Amber Theme - Color System with Light/Dark Variants +// Inspired by Moloch's semantic color system with persistent customization + +// ============================================================================= +// THEME STATE FOR DYNAMIC COMPONENTS +// ============================================================================= + +// State to store current theme colors - set by theme, read by components +#let theme-colors-state = state("theme-colors-state", none) + +// ============================================================================= +// COLOR THEME PRESETS +// ============================================================================= + +// Warm Amber theme (default) - Light variant +#let warm-amber-light = ( + // Primary accent colors + accent-primary: rgb("#C2762E"), + accent-secondary: rgb("#D4915A"), + accent-subtle: rgb("#FDF6EE"), + accent-glow: rgb("#E8A756"), + accent-deep: rgb("#9E5F23"), + + // Background hierarchy + bg-base: rgb("#FDFCFA"), + bg-elevated: rgb("#FFFFFF"), + bg-muted: rgb("#F9F7F4"), + bg-surface: rgb("#F5F2EE"), + bg-wash: rgb("#FAF8F5"), + + // Text hierarchy + text-primary: rgb("#2D2A26"), + text-secondary: rgb("#5C564E"), + text-muted: rgb("#8C857B"), + text-light: rgb("#B5AFA6"), + text-subtle: rgb("#A49E95"), + + // Borders + border-subtle: rgb("#EAE6E1"), + border-soft: rgb("#E0DBD4"), + border-medium: rgb("#D4CEC5"), + progress-track: rgb("#E8E4DE"), + + // Functional colors + alert-bg: rgb("#FEF3F2"), + alert-border: rgb("#F87171"), + alert-text: rgb("#DC2626"), + example-bg: rgb("#F0FDF4"), + example-border: rgb("#4ADE80"), + example-text: rgb("#16A34A"), + + // Focus slide (gradient amber) + focus-bg: rgb("#C2762E"), + focus-text: rgb("#FFFEFA"), + + // Standout slide - deep amber with warm cream (elegant, cohesive) + standout-bg: rgb("#8B5A2B"), // Deep sienna brown + standout-text: rgb("#FFF8F0"), // Warm cream text + + // Header bar (Moloch-style) - using warm amber tones + header-bg: rgb("#9E5F23"), // Deep amber for header + header-text: rgb("#FFFEFA"), // Warm white text +) + +// Warm Amber theme - Dark variant +#let warm-amber-dark = ( + // Primary accent colors (slightly brighter for dark bg) + accent-primary: rgb("#E8A756"), + accent-secondary: rgb("#D4915A"), + accent-subtle: rgb("#3D3530"), + accent-glow: rgb("#F0B866"), + accent-deep: rgb("#C2762E"), + + // Background hierarchy (inverted) + bg-base: rgb("#1C1917"), + bg-elevated: rgb("#292524"), + bg-muted: rgb("#1F1C1A"), + bg-surface: rgb("#262220"), + bg-wash: rgb("#211E1C"), + + // Text hierarchy (inverted) + text-primary: rgb("#FAFAF9"), + text-secondary: rgb("#D6D3D1"), + text-muted: rgb("#A8A29E"), + text-light: rgb("#78716C"), + text-subtle: rgb("#57534E"), + + // Borders (inverted) + border-subtle: rgb("#3D3835"), + border-soft: rgb("#44403C"), + border-medium: rgb("#57534E"), + progress-track: rgb("#44403C"), + + // Functional colors (adjusted for dark) + alert-bg: rgb("#450A0A"), + alert-border: rgb("#DC2626"), + alert-text: rgb("#FCA5A5"), + example-bg: rgb("#052E16"), + example-border: rgb("#16A34A"), + example-text: rgb("#86EFAC"), + + // Focus slide (gradient amber) + focus-bg: rgb("#E8A756"), + focus-text: rgb("#1C1917"), + + // Standout slide - warm cream with deep amber (inverted from light) + standout-bg: rgb("#FFF8F0"), // Warm cream background + standout-text: rgb("#8B5A2B"), // Deep sienna text + + // Header bar - amber accent on dark + header-bg: rgb("#C2762E"), // Warm amber header + header-text: rgb("#FAFAF9"), // Light text +) + +// Tomorrow theme (programmer-friendly) - Light variant +#let tomorrow-light = ( + accent-primary: rgb("#4271AE"), + accent-secondary: rgb("#718C00"), + accent-subtle: rgb("#EFF1F5"), + accent-glow: rgb("#3E999F"), + accent-deep: rgb("#8959A8"), + + bg-base: rgb("#FFFFFF"), + bg-elevated: rgb("#FFFFFF"), + bg-muted: rgb("#F2F2F2"), + bg-surface: rgb("#EFEFEF"), + bg-wash: rgb("#F7F7F7"), + + text-primary: rgb("#1D1F21"), + text-secondary: rgb("#4D4D4C"), + text-muted: rgb("#8E908C"), + text-light: rgb("#C5C8C6"), + text-subtle: rgb("#A0A1A0"), + + border-subtle: rgb("#E0E0E0"), + border-soft: rgb("#D6D6D6"), + border-medium: rgb("#C8C8C8"), + progress-track: rgb("#E0E0E0"), + + alert-bg: rgb("#FDF2F2"), + alert-border: rgb("#C82829"), + alert-text: rgb("#C82829"), + example-bg: rgb("#F2FDF5"), + example-border: rgb("#718C00"), + example-text: rgb("#718C00"), + + focus-bg: rgb("#4271AE"), + focus-text: rgb("#FFFFFF"), + + // Standout slide + standout-bg: rgb("#1D1F21"), + standout-text: rgb("#81A2BE"), + + // Header bar - using blue accent + header-bg: rgb("#4271AE"), + header-text: rgb("#FFFFFF"), +) + +// Tomorrow theme - Dark variant +#let tomorrow-dark = ( + accent-primary: rgb("#81A2BE"), + accent-secondary: rgb("#B5BD68"), + accent-subtle: rgb("#373B41"), + accent-glow: rgb("#8ABEB7"), + accent-deep: rgb("#B294BB"), + + bg-base: rgb("#1D1F21"), + bg-elevated: rgb("#282A2E"), + bg-muted: rgb("#232527"), + bg-surface: rgb("#2D2F33"), + bg-wash: rgb("#252729"), + + text-primary: rgb("#C5C8C6"), + text-secondary: rgb("#969896"), + text-muted: rgb("#707070"), + text-light: rgb("#4D4D4C"), + text-subtle: rgb("#5C5E5C"), + + border-subtle: rgb("#373B41"), + border-soft: rgb("#444850"), + border-medium: rgb("#555960"), + progress-track: rgb("#373B41"), + + alert-bg: rgb("#3A1F1F"), + alert-border: rgb("#CC6666"), + alert-text: rgb("#CC6666"), + example-bg: rgb("#1F3A1F"), + example-border: rgb("#B5BD68"), + example-text: rgb("#B5BD68"), + + focus-bg: rgb("#81A2BE"), + focus-text: rgb("#1D1F21"), + + // Standout slide + standout-bg: rgb("#C5C8C6"), + standout-text: rgb("#1D1F21"), + + // Header bar - lighter blue on dark + header-bg: rgb("#81A2BE"), + header-text: rgb("#1D1F21"), +) + +// Paper theme (high contrast, academic) - Light variant +#let paper-light = ( + accent-primary: rgb("#1A1A1A"), + accent-secondary: rgb("#2563EB"), + accent-subtle: rgb("#F5F5F5"), + accent-glow: rgb("#3B82F6"), + accent-deep: rgb("#0F172A"), + + bg-base: rgb("#FFFFFF"), + bg-elevated: rgb("#FFFFFF"), + bg-muted: rgb("#F8F8F8"), + bg-surface: rgb("#F3F3F3"), + bg-wash: rgb("#FAFAFA"), + + text-primary: rgb("#000000"), + text-secondary: rgb("#333333"), + text-muted: rgb("#666666"), + text-light: rgb("#999999"), + text-subtle: rgb("#808080"), + + border-subtle: rgb("#E5E5E5"), + border-soft: rgb("#D4D4D4"), + border-medium: rgb("#A3A3A3"), + progress-track: rgb("#E5E5E5"), + + alert-bg: rgb("#FEF2F2"), + alert-border: rgb("#EF4444"), + alert-text: rgb("#DC2626"), + example-bg: rgb("#EFF6FF"), + example-border: rgb("#2563EB"), + example-text: rgb("#1D4ED8"), + + focus-bg: rgb("#2563EB"), + focus-text: rgb("#FFFFFF"), + + // Standout slide + standout-bg: rgb("#000000"), + standout-text: rgb("#FFFFFF"), + + // Header bar - blue accent for paper theme + header-bg: rgb("#2563EB"), + header-text: rgb("#FFFFFF"), +) + +// Paper theme - Dark variant +#let paper-dark = ( + accent-primary: rgb("#FFFFFF"), + accent-secondary: rgb("#60A5FA"), + accent-subtle: rgb("#262626"), + accent-glow: rgb("#93C5FD"), + accent-deep: rgb("#F8FAFC"), + + bg-base: rgb("#0A0A0A"), + bg-elevated: rgb("#171717"), + bg-muted: rgb("#0F0F0F"), + bg-surface: rgb("#1A1A1A"), + bg-wash: rgb("#141414"), + + text-primary: rgb("#FFFFFF"), + text-secondary: rgb("#E5E5E5"), + text-muted: rgb("#A3A3A3"), + text-light: rgb("#737373"), + text-subtle: rgb("#525252"), + + border-subtle: rgb("#262626"), + border-soft: rgb("#404040"), + border-medium: rgb("#525252"), + progress-track: rgb("#262626"), + + alert-bg: rgb("#450A0A"), + alert-border: rgb("#F87171"), + alert-text: rgb("#FCA5A5"), + example-bg: rgb("#172554"), + example-border: rgb("#60A5FA"), + example-text: rgb("#93C5FD"), + + focus-bg: rgb("#60A5FA"), + focus-text: rgb("#0A0A0A"), + + // Standout slide + standout-bg: rgb("#FFFFFF"), + standout-text: rgb("#0A0A0A"), + + // Header bar - lighter blue on dark paper + header-bg: rgb("#60A5FA"), + header-text: rgb("#0A0A0A"), +) + +// Dracula theme - Light variant +#let dracula-light = ( + accent-primary: rgb("#BD93F9"), + accent-secondary: rgb("#FF79C6"), + accent-subtle: rgb("#F8F8F2"), + accent-glow: rgb("#8BE9FD"), + accent-deep: rgb("#6272A4"), + + bg-base: rgb("#F8F8F2"), + bg-elevated: rgb("#FFFFFF"), + bg-muted: rgb("#F0F0EB"), + bg-surface: rgb("#E8E8E3"), + bg-wash: rgb("#F5F5F0"), + + text-primary: rgb("#282A36"), + text-secondary: rgb("#44475A"), + text-muted: rgb("#6272A4"), + text-light: rgb("#9090A0"), + text-subtle: rgb("#7575A0"), + + border-subtle: rgb("#E0E0D8"), + border-soft: rgb("#D0D0C8"), + border-medium: rgb("#B0B0A8"), + progress-track: rgb("#E0E0D8"), + + alert-bg: rgb("#FFF0F0"), + alert-border: rgb("#FF5555"), + alert-text: rgb("#FF5555"), + example-bg: rgb("#F0FFF4"), + example-border: rgb("#50FA7B"), + example-text: rgb("#50FA7B"), + + focus-bg: rgb("#BD93F9"), + focus-text: rgb("#282A36"), + + standout-bg: rgb("#FF79C6"), + standout-text: rgb("#282A36"), + + header-bg: rgb("#BD93F9"), + header-text: rgb("#282A36"), +) + +// Dracula theme - Dark variant +#let dracula-dark = ( + accent-primary: rgb("#BD93F9"), + accent-secondary: rgb("#FF79C6"), + accent-subtle: rgb("#44475A"), + accent-glow: rgb("#8BE9FD"), + accent-deep: rgb("#6272A4"), + + bg-base: rgb("#282A36"), + bg-elevated: rgb("#343746"), + bg-muted: rgb("#21222C"), + bg-surface: rgb("#3A3C4E"), + bg-wash: rgb("#2E303E"), + + text-primary: rgb("#F8F8F2"), + text-secondary: rgb("#E0E0E0"), + text-muted: rgb("#BFBFBF"), + text-light: rgb("#6272A4"), + text-subtle: rgb("#7580A0"), + + border-subtle: rgb("#44475A"), + border-soft: rgb("#4A4D5E"), + border-medium: rgb("#6272A4"), + progress-track: rgb("#44475A"), + + alert-bg: rgb("#3A1F2A"), + alert-border: rgb("#FF5555"), + alert-text: rgb("#FF6E6E"), + example-bg: rgb("#253D2A"), + example-border: rgb("#50FA7B"), + example-text: rgb("#69FF94"), + + focus-bg: rgb("#BD93F9"), + focus-text: rgb("#282A36"), + + standout-bg: rgb("#FF79C6"), + standout-text: rgb("#282A36"), + + header-bg: rgb("#BD93F9"), + header-text: rgb("#282A36"), +) + +// ============================================================================= +// COLOR GETTER SYSTEM +// ============================================================================= + +// Get colors for a given theme and variant +#let get-theme-colors(theme: "warm-amber", variant: "light") = { + let themes = ( + "warm-amber": (light: warm-amber-light, dark: warm-amber-dark), + "tomorrow": (light: tomorrow-light, dark: tomorrow-dark), + "paper": (light: paper-light, dark: paper-dark), + "dracula": (light: dracula-light, dark: dracula-dark), + ) + + let selected-theme = themes.at(theme, default: themes.warm-amber) + selected-theme.at(variant, default: selected-theme.light) +} + +// ============================================================================= +// DEFAULT COLORS (backwards compatibility - warm-amber light) +// ============================================================================= + +#let accent-primary = warm-amber-light.accent-primary +#let accent-secondary = warm-amber-light.accent-secondary +#let accent-subtle = warm-amber-light.accent-subtle +#let accent-glow = warm-amber-light.accent-glow +#let accent-deep = warm-amber-light.accent-deep + +#let bg-base = warm-amber-light.bg-base +#let bg-elevated = warm-amber-light.bg-elevated +#let bg-muted = warm-amber-light.bg-muted +#let bg-surface = warm-amber-light.bg-surface +#let bg-wash = warm-amber-light.bg-wash + +#let text-primary = warm-amber-light.text-primary +#let text-secondary = warm-amber-light.text-secondary +#let text-muted = warm-amber-light.text-muted +#let text-light = warm-amber-light.text-light +#let text-subtle = warm-amber-light.text-subtle + +#let border-subtle = warm-amber-light.border-subtle +#let border-soft = warm-amber-light.border-soft +#let border-medium = warm-amber-light.border-medium +#let progress-track = warm-amber-light.progress-track + +#let alert-bg = warm-amber-light.alert-bg +#let alert-border = warm-amber-light.alert-border +#let alert-text = warm-amber-light.alert-text +#let example-bg = warm-amber-light.example-bg +#let example-border = warm-amber-light.example-border +#let example-text = warm-amber-light.example-text + +#let focus-bg = warm-amber-light.focus-bg +#let focus-text = warm-amber-light.focus-text + +#let standout-bg = warm-amber-light.standout-bg +#let standout-text = warm-amber-light.standout-text + +#let header-bg = warm-amber-light.header-bg +#let header-text = warm-amber-light.header-text + +// ============================================================================= +// GRADIENTS (generated based on colors) +// ============================================================================= + +#let make-gradients(colors) = { + ( + bg-gradient: gradient.linear( + angle: 180deg, + (colors.bg-base, 0%), + (colors.bg-muted, 100%) + ), + accent-gradient: gradient.linear( + angle: 135deg, + (colors.accent-secondary, 0%), + (colors.accent-primary, 50%), + (colors.accent-deep, 100%) + ), + title-gradient: gradient.linear( + angle: 180deg, + (colors.bg-base, 0%), + (colors.accent-subtle, 100%) + ), + header-gradient: gradient.linear( + angle: 0deg, + (colors.accent-primary.transparentize(20%), 0%), + (colors.accent-secondary.transparentize(60%), 30%), + (colors.border-subtle, 100%) + ), + progress-gradient: gradient.linear( + angle: 0deg, + (colors.accent-secondary, 0%), + (colors.accent-primary, 100%) + ), + ) +} + +// Default gradients +#let bg-gradient = gradient.linear( + angle: 180deg, + (rgb("#FDFCFA"), 0%), + (rgb("#F9F7F4"), 100%) +) + +#let accent-gradient = gradient.linear( + angle: 135deg, + (rgb("#D4915A"), 0%), + (rgb("#C2762E"), 50%), + (rgb("#A86B2D"), 100%) +) + +#let title-gradient = gradient.linear( + angle: 180deg, + (rgb("#FDFCFA"), 0%), + (rgb("#FDF6EE"), 100%) +) + +// ============================================================================= +// SHADOWS +// ============================================================================= + +#let shadow-soft = rgb("#2D2A26").transparentize(96%) +#let shadow-medium = rgb("#2D2A26").transparentize(92%) +#let shadow-strong = rgb("#2D2A26").transparentize(88%) + +#let overlay-light = rgb("#FFFFFF").transparentize(40%) +#let overlay-dark = rgb("#2D2A26").transparentize(95%) diff --git a/packages/preview/calmly-touying/0.2.0/theme/components.typ b/packages/preview/calmly-touying/0.2.0/theme/components.typ new file mode 100644 index 0000000000..6e129609da --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/components.typ @@ -0,0 +1,525 @@ +// Reusable Components - Theme-Aware +// All components accept optional `colors` parameter for theming +#import "colors.typ": * +#import "typography.typ": * + +// ============================================================================= +// HELPER: Get colors from theme or state +// ============================================================================= + +// Resolve colors - either from explicit parameter, or from state, or fallback +// This must be called INSIDE a context block to work with state +#let resolve-theme-colors(colors-param) = { + if colors-param != none { + colors-param + } else { + let from-state = theme-colors-state.get() + if from-state != none { from-state } else { warm-amber-light } + } +} + +// Get a specific color from a colors dict +#let get-color-from(colors, key) = { + colors.at(key, default: rgb("#888888")) +} + +// ============================================================================= +// LAYOUT COMPONENTS +// ============================================================================= + +// Two-column layout with proper gutter +#let two-col(left, right, gutter: spacing-xl) = { + grid( + columns: (1fr, 1fr), + column-gutter: gutter, + left, right + ) +} + +// Three-column layout +#let three-col(a, b, c, gutter: spacing-lg) = { + grid( + columns: (1fr, 1fr, 1fr), + column-gutter: gutter, + a, b, c + ) +} + +// Spacer helper +#let spacer(size: spacing-lg) = v(size) + +// ============================================================================= +// BOX COMPONENTS +// ============================================================================= + +// Soft shadow box helper +#let soft-shadow-box( + body, + fill: none, + radius: radius-lg, + inset: spacing-lg, + width: 100%, + colors: none, +) = context { + let c = resolve-theme-colors(colors) + let bg = if fill != none { fill } else { get-color-from(c, "bg-elevated") } + let border = get-color-from(c, "border-subtle") + + block( + width: width, + inset: 0pt, + outset: 0pt, + )[ + #box( + width: 100%, + radius: radius, + fill: bg, + stroke: 0.5pt + border, + inset: inset, + )[ + #body + ] + ] +} + +// Elegant highlight box with soft left accent +#let highlight-box(body, title: none, colors: none) = context { + let c = resolve-theme-colors(colors) + + block( + fill: gradient.linear( + angle: 90deg, + (get-color-from(c, "accent-subtle"), 0%), + (get-color-from(c, "bg-elevated"), 15%), + (get-color-from(c, "bg-elevated"), 100%), + ), + stroke: ( + left: 2.5pt + get-color-from(c, "accent-primary"), + rest: 0.5pt + get-color-from(c, "border-subtle"), + ), + inset: (left: spacing-lg, right: spacing-md, top: spacing-md, bottom: spacing-md), + radius: (left: 2pt, right: radius-md), + width: 100%, + )[ + #if title != none { + text( + weight: "medium", + fill: get-color-from(c, "accent-deep"), + size: size-small, + )[#title] + v(spacing-xs) + } + #text(fill: get-color-from(c, "text-secondary"))[#body] + ] +} + +// Elegant algorithm box with refined header +#let algorithm-box(body, title: none, colors: none) = context { + let c = resolve-theme-colors(colors) + + block( + fill: get-color-from(c, "bg-elevated"), + stroke: 0.5pt + get-color-from(c, "border-soft"), + radius: radius-lg, + width: 100%, + clip: true, + )[ + #if title != none { + block( + fill: get-color-from(c, "bg-wash"), + width: 100%, + inset: (x: spacing-md, y: spacing-sm), + )[ + #text( + weight: "medium", + fill: get-color-from(c, "accent-primary"), + size: size-small, + tracking: tracking-wide, + )[#title] + ] + } + #block(inset: spacing-md)[ + #set text(font: font-mono, size: size-code, fill: get-color-from(c, "text-secondary")) + #set par(leading: 1em) + #show math.equation: set text(size: size-body) + #body + ] + ] +} + +// Elegant code block with soft styling +#let code-block(code, lang: none, colors: none) = context { + let c = resolve-theme-colors(colors) + + block( + fill: get-color-from(c, "bg-surface"), + stroke: 0.5pt + get-color-from(c, "border-soft"), + radius: radius-md, + inset: spacing-md, + width: 100%, + )[ + #set text(font: font-mono, size: size-code, fill: get-color-from(c, "text-secondary")) + #raw(code, lang: lang) + ] +} + +// ============================================================================= +// TEXT HELPERS +// ============================================================================= + +// Soft alert/emphasis text +#let alert(body, colors: none) = context { + let c = resolve-theme-colors(colors) + text(fill: get-color-from(c, "accent-primary"), weight: "medium")[#body] +} + +// Muted text helper +#let muted(body, colors: none) = context { + let c = resolve-theme-colors(colors) + text(fill: get-color-from(c, "text-muted"), size: size-caption)[#body] +} + +// Subtle text +#let subtle(body, colors: none) = context { + let c = resolve-theme-colors(colors) + text(fill: get-color-from(c, "text-light"), size: size-small)[#body] +} + +// Elegant figure caption +#let fig-caption(body, colors: none) = context { + let c = resolve-theme-colors(colors) + text( + fill: get-color-from(c, "text-muted"), + size: size-caption, + style: "italic", + tracking: tracking-wide, + )[#body] +} + +// ============================================================================= +// VISUAL ELEMENTS +// ============================================================================= + +// Elegant accent line with gradient fade +#let accent-line(width: 64pt, colors: none) = context { + let c = resolve-theme-colors(colors) + + box(width: width, height: 2pt)[ + #rect( + width: 100%, + height: 100%, + radius: 1pt, + fill: gradient.linear( + angle: 0deg, + (get-color-from(c, "accent-secondary"), 0%), + (get-color-from(c, "accent-primary"), 50%), + (get-color-from(c, "accent-secondary"), 100%), + ), + ) + ] +} + +// Soft divider line +#let soft-divider(width: 100%, colors: none) = context { + let c = resolve-theme-colors(colors) + line(length: width, stroke: 0.5pt + get-color-from(c, "border-subtle")) +} + +// Refined bullet point with soft accent +#let bullet(body, colors: none) = context { + let c = resolve-theme-colors(colors) + grid( + columns: (auto, 1fr), + column-gutter: spacing-sm, + align(top)[ + #box( + width: 5pt, + height: 5pt, + radius: radius-full, + fill: get-color-from(c, "accent-secondary"), + baseline: 0.4em, + ) + ], + body + ) +} + +// Pill/tag component +#let pill(body, accent: false, colors: none) = context { + let c = resolve-theme-colors(colors) + let c-accent-subtle = get-color-from(c, "accent-subtle") + let c-bg-surface = get-color-from(c, "bg-surface") + let c-accent-secondary = get-color-from(c, "accent-secondary") + let c-border-subtle = get-color-from(c, "border-subtle") + let c-accent-deep = get-color-from(c, "accent-deep") + let c-text-muted = get-color-from(c, "text-muted") + + box( + fill: if accent { c-accent-subtle } else { c-bg-surface }, + stroke: 0.5pt + if accent { c-accent-secondary.transparentize(50%) } else { c-border-subtle }, + radius: radius-full, + inset: (x: spacing-sm, y: spacing-2xs), + )[ + #text( + size: size-micro, + weight: "medium", + fill: if accent { c-accent-deep } else { c-text-muted }, + )[#body] + ] +} + +// Quote block +#let quote-block(body, attribution: none, colors: none) = context { + let c = resolve-theme-colors(colors) + + block( + inset: (left: spacing-lg, y: spacing-sm), + stroke: (left: 2pt + get-color-from(c, "border-soft")), + )[ + #text(style: "italic", fill: get-color-from(c, "text-secondary"), size: size-body)[#body] + #if attribution != none { + v(spacing-xs) + text(fill: get-color-from(c, "text-muted"), size: size-caption)[— #attribution] + } + ] +} + +// ============================================================================= +// CARD COMPONENTS +// ============================================================================= + +// Refined person card for acknowledgements +#let person-card(name, role, image-path: none, colors: none) = context { + let c = resolve-theme-colors(colors) + + align(center)[ + #if image-path != none { + box( + width: 72pt, + height: 72pt, + radius: radius-full, + clip: true, + stroke: 1.5pt + get-color-from(c, "border-soft"), + fill: get-color-from(c, "bg-muted"), + )[ + #image(image-path, width: 100%, height: 100%, fit: "cover") + ] + } else { + // Elegant placeholder with initials-style circle + box( + width: 72pt, + height: 72pt, + radius: radius-full, + fill: gradient.radial( + (get-color-from(c, "bg-muted"), 0%), + (get-color-from(c, "bg-surface"), 100%), + ), + stroke: 1.5pt + get-color-from(c, "border-soft"), + )[ + #align(center + horizon)[ + #text(fill: get-color-from(c, "text-light"), size: 28pt, weight: "light")[#name.first()] + ] + ] + } + #v(spacing-sm) + #text(weight: "medium", size: size-body, fill: get-color-from(c, "text-primary"))[#name] + #v(spacing-3xs) + #text(fill: get-color-from(c, "text-muted"), size: size-caption)[#role] + ] +} + +// Refined institution card +#let institution-card(name, logo-path: none, colors: none) = context { + let c = resolve-theme-colors(colors) + + align(center)[ + #if logo-path != none { + box(height: 48pt)[ + #image(logo-path, height: 100%) + ] + } else { + box( + width: 100pt, + height: 48pt, + fill: get-color-from(c, "bg-surface"), + radius: radius-md, + stroke: 0.5pt + get-color-from(c, "border-subtle"), + )[ + #align(center + horizon)[ + #text(fill: get-color-from(c, "text-light"), size: size-caption, weight: "medium")[#name] + ] + ] + } + #v(spacing-xs) + #text(fill: get-color-from(c, "text-muted"), size: size-caption)[#name] + ] +} + +// Contact info item with icon placeholder +#let contact-item(content, colors: none) = context { + let c = resolve-theme-colors(colors) + text(fill: get-color-from(c, "text-muted"), size: size-caption)[#content] +} + +// ============================================================================= +// ALERT AND EXAMPLE BOXES (Moloch-inspired) +// ============================================================================= + +// Alert box - for warnings, important notes, critical information +#let alert-box(body, title: none, colors: none) = context { + let c = resolve-theme-colors(colors) + let c-alert-bg = get-color-from(c, "alert-bg") + let c-alert-border = get-color-from(c, "alert-border") + let c-alert-text = get-color-from(c, "alert-text") + let c-text-secondary = get-color-from(c, "text-secondary") + + block( + fill: c-alert-bg, + stroke: ( + left: 3pt + c-alert-border, + rest: 0.5pt + c-alert-border.transparentize(60%), + ), + inset: (left: spacing-lg, right: spacing-md, top: spacing-md, bottom: spacing-md), + radius: (left: 2pt, right: radius-md), + width: 100%, + )[ + #if title != none { + text( + weight: "semibold", + fill: c-alert-text, + size: size-small, + tracking: tracking-wide, + )[#title] + v(spacing-xs) + } + #text(fill: c-text-secondary)[#body] + ] +} + +// Example box - for examples, code samples, demonstrations +#let example-box(body, title: none, colors: none) = context { + let c = resolve-theme-colors(colors) + let c-example-bg = get-color-from(c, "example-bg") + let c-example-border = get-color-from(c, "example-border") + let c-example-text = get-color-from(c, "example-text") + let c-text-secondary = get-color-from(c, "text-secondary") + + block( + fill: c-example-bg, + stroke: ( + left: 3pt + c-example-border, + rest: 0.5pt + c-example-border.transparentize(60%), + ), + inset: (left: spacing-lg, right: spacing-md, top: spacing-md, bottom: spacing-md), + radius: (left: 2pt, right: radius-md), + width: 100%, + )[ + #if title != none { + text( + weight: "semibold", + fill: c-example-text, + size: size-small, + tracking: tracking-wide, + )[#title] + v(spacing-xs) + } + #text(fill: c-text-secondary)[#body] + ] +} + +// Generic block with transparent or filled mode (Moloch-style) +#let themed-block(body, title: none, fill-mode: "transparent", colors: none) = context { + let c = resolve-theme-colors(colors) + let c-bg-surface = get-color-from(c, "bg-surface") + let c-bg-elevated = get-color-from(c, "bg-elevated") + let c-border-soft = get-color-from(c, "border-soft") + let c-accent-primary = get-color-from(c, "accent-primary") + let c-text-secondary = get-color-from(c, "text-secondary") + + let bg = if fill-mode == "fill" { c-bg-surface } else { c-bg-elevated } + + block( + fill: bg, + stroke: 0.5pt + c-border-soft, + inset: spacing-md, + radius: radius-lg, + width: 100%, + )[ + #if title != none { + text( + weight: "semibold", + fill: c-accent-primary, + size: size-body, + )[#title] + v(spacing-sm) + } + #text(fill: c-text-secondary)[#body] + ] +} + +// ============================================================================= +// HAND-DRAWN LIST SYMBOLS (Moloch-inspired) +// ============================================================================= + +// Level 1: Filled circle +#let bullet-circle(size: 6pt, color: accent-secondary) = { + circle(radius: size / 2, fill: color) +} + +// Level 2: Filled square +#let bullet-square(size: 5pt, color: accent-secondary) = { + rect(width: size, height: size, fill: color) +} + +// Level 3: Dash/line +#let bullet-dash(size: 8pt, color: accent-secondary) = { + rect(width: size, height: 2pt, fill: color, radius: 1pt) +} + +// ============================================================================= +// CITATION GADGET +// ============================================================================= + +// Citation gadget - small box shown at slide corner with integrated bibliography citation +// bib-key: single key (string) or multiple keys (array of strings) +// display-label: display text - if none, uses the citation key(s) +// Position options: "top-right", "bottom-left", "bottom-right" +#let cite-box(bib-key, display-label: none, position: "bottom-right", colors: none) = context { + let c = resolve-theme-colors(colors) + + // Handle single or multiple keys + let keys = if type(bib-key) == array { bib-key } else { (bib-key,) } + + // Use provided label or show citation key(s) + let display-content = if display-label != none { display-label } else { keys.join(", ") } + + // Hidden citations to register with bibliography (placed outside box) + place(hide[#for key in keys { cite(label(key)) }]) + + let cite-pill = box( + fill: get-color-from(c, "bg-wash"), + stroke: ( + left: 1.5pt + get-color-from(c, "accent-primary"), + rest: 0.5pt + get-color-from(c, "border-subtle"), + ), + radius: (right: 4pt), + inset: (left: spacing-xs, right: spacing-sm, y: spacing-2xs), + )[ + // Clickable link to bibliography slide + #link()[ + #text( + size: size-micro, + fill: get-color-from(c, "text-secondary"), + )[#emph[#display-content]] + ] + ] + + // Position in corner + if position == "top-right" { + place(top + right, dx: -spacing-md, dy: spacing-md)[#cite-pill] + } else if position == "bottom-left" { + place(bottom + left, dx: spacing-md, dy: -spacing-md)[#cite-pill] + } else { + place(bottom + right, dx: -spacing-md, dy: -spacing-md)[#cite-pill] + } +} diff --git a/packages/preview/calmly-touying/0.2.0/theme/slides.typ b/packages/preview/calmly-touying/0.2.0/theme/slides.typ new file mode 100644 index 0000000000..fc23499050 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/slides.typ @@ -0,0 +1,1076 @@ +// Slide Type Definitions - Enhanced with Moloch-inspired Features +// Includes: progress bar placement, Moloch-style headers, title variants, standout slides +#import "@preview/touying:0.6.1": * +#import "colors.typ": * +#import "typography.typ": * +#import "components.typ": * + +// ============================================================================= +// MOLOCH HEADER BAR COMPONENT +// ============================================================================= + +// Header bar for use in Touying's header area (all slides) +// Outset extends to page edges (horizontal and top), comfortable padding +#let moloch-header-bar-touying(title, colors) = { + block( + width: 100%, + fill: colors.header-bg, + inset: (x: spacing-lg, top: spacing-md, bottom: 14pt), + outset: (x: spacing-2xl, top: spacing-2xl + spacing-md), // Match the increased top margin + )[ + #text( + size: size-slide-title, + weight: "semibold", + fill: colors.header-text, + tracking: tracking-tight, + )[#title] + ] +} + +// ============================================================================= +// PROGRESS BAR COMPONENT +// ============================================================================= + +// Progress bar that can be placed in different locations +// position: "head", "foot", "frametitle", "none" +#let make-progress-bar(colors, height: 2pt, position: "foot") = { + if position == "none" { return none } + + // Use Touying's built-in progress bar approach + // The key is to use context with separate counter access + context { + let current = utils.slide-counter.get().first() + let total = utils.last-slide-counter.final().first() + let ratio = if total > 0 { calc.min(current / total, 1.0) } else { 0 } + + box(width: 100%, height: height)[ + #rect(width: 100%, height: height, radius: height / 2, fill: colors.progress-track) + #place(left)[ + #rect( + width: ratio * 100%, + height: height, + radius: height / 2, + fill: gradient.linear( + angle: 0deg, + (colors.accent-secondary, 0%), + (colors.accent-primary, 100%), + ), + ) + ] + ] + } +} + +// ============================================================================= +// DEFAULT SLIDE WITH MOLOCH-STYLE HEADER +// ============================================================================= + +/// Default slide function with configurable header style and progress bar placement +/// header-style: "moloch" (colored bar) or "minimal" (gradient underline) +/// progressbar: "head", "foot", "frametitle", "none" +#let slide( + config: (:), + repeat: auto, + setting: body => body, + composer: auto, + colors: none, + header-style: "moloch", + progressbar: "foot", + ..bodies, +) = touying-slide-wrapper(self => { + // Get colors from self or use defaults + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + // Moloch-style header with colored background + let moloch-header(self) = { + let title = utils.display-current-heading(level: 2, depth: self.slide-level) + if title != none { + // Use the Touying-specific header bar (for header area) + moloch-header-bar-touying(title, c) + + // Progress bar under header if frametitle position + if progressbar == "frametitle" { + v(-spacing-sm) + make-progress-bar(c, height: 2pt, position: "frametitle") + } + } + } + + // Minimal header with gradient underline (original style) + let minimal-header(self) = { + let title = utils.display-current-heading(level: 2, depth: self.slide-level) + if title != none { + // Stack everything vertically + stack(dir: ttb, spacing: spacing-xs)[ + #text(size: size-slide-title, weight: "semibold", fill: c.text-primary)[#title] + ][ + #box(width: 100%, height: 1.5pt)[ + #rect( + width: 100%, + height: 100%, + fill: gradient.linear( + angle: 0deg, + (c.accent-primary.transparentize(20%), 0%), + (c.accent-secondary.transparentize(60%), 30%), + (c.border-subtle, 100%), + ), + ) + ] + ] + + // Progress bar under title if frametitle position + if progressbar == "frametitle" { + v(spacing-xs) + make-progress-bar(c, height: 2pt, position: "frametitle") + } + + v(spacing-sm) + } + } + + // Choose header based on style + let header-fn = if header-style == "moloch" { moloch-header } else { minimal-header } + + // Footer with optional progress bar + let footer(self) = context { + let current = utils.slide-counter.get().first() + let total = utils.last-slide-counter.final().first() + + v(spacing-sm) + + if progressbar == "foot" { + components.left-and-right( + make-progress-bar(c, height: 2pt, position: "foot"), + text(fill: c.text-secondary, size: size-small)[ + #current #text(fill: c.text-muted)[/] #total + ] + ) + } else { + // Just show page numbers without progress bar + align(right)[ + #text(fill: c.text-secondary, size: size-small)[ + #current #text(fill: c.text-muted)[/] #total + ] + ] + } + } + + // Header at top with progress bar if head position + let header-with-progress(self) = { + if progressbar == "head" { + make-progress-bar(c, height: 3pt, position: "head") + v(spacing-sm) + } + header-fn(self) + } + + let self = utils.merge-dicts( + self, + config-page( + header: header-with-progress, + footer: footer, + ), + ) + + touying-slide(self: self, config: config, repeat: repeat, setting: setting, composer: composer, ..bodies) +}) + +// ============================================================================= +// TITLE SLIDE VARIANTS +// ============================================================================= + +/// Centered title slide (original style) +#let title-slide-centered( + config: (:), + logo: none, + extra: none, + colors: none, + use-golden-ratio: false, +) = touying-slide-wrapper(self => { + let info = self.info + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + let self = utils.merge-dicts( + self, + config-common(freeze-slide-counter: true), + config-page( + margin: spacing-3xl, + header: none, + footer: none, + fill: c.bg-base, + ), + ) + + let body = { + set align(center) + + // Use golden ratio or equal spacing + if use-golden-ratio { + v(1fr * phi) + } else { + v(1fr) + } + + // Optional logo + if logo != none { + box(height: 56pt, inset: spacing-sm)[#logo] + v(spacing-2xl) + } + + // Title + text( + size: size-title, + weight: "semibold", + fill: c.text-primary, + tracking: tracking-tight, + )[#info.title] + + // Subtitle + if info.subtitle != none { + v(spacing-sm) + text( + size: size-subtitle, + weight: "regular", + fill: c.text-muted, + )[#info.subtitle] + } + + // Accent line + v(spacing-xl) + accent-line(width: 56pt, colors: c) + v(spacing-xl) + + // Author + text( + size: size-body, + weight: "medium", + fill: c.text-secondary, + )[#info.author] + + // Institution + if info.institution != none { + v(spacing-xs) + text( + size: size-caption, + fill: c.text-muted, + weight: "regular", + )[#info.institution] + } + + // Date + if info.date != none { + v(spacing-md) + text( + size: size-caption, + fill: c.text-light, + weight: "light", + )[ + #if type(info.date) == datetime { + info.date.display("[month repr:long] [day], [year]") + } else { + info.date + } + ] + } + + // Extra content + if extra != none { + v(spacing-lg) + extra + } + + v(1fr) + } + + touying-slide(self: self, config: config, body) +}) + +/// Moloch-style title slide (left-aligned with horizontal separator) +#let title-slide-moloch( + config: (:), + logo: none, + extra: none, + colors: none, +) = touying-slide-wrapper(self => { + let info = self.info + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + let self = utils.merge-dicts( + self, + config-common(freeze-slide-counter: true), + config-page( + margin: spacing-3xl, + header: none, + footer: none, + fill: c.bg-base, + ), + ) + + let body = { + // Golden ratio spacing above + v(1fr * phi) + + // Left-aligned title block + set align(left) + + // Optional logo + if logo != none { + box(height: 48pt)[#logo] + v(spacing-xl) + } + + // Title + text( + size: size-title, + weight: "semibold", + fill: c.text-primary, + tracking: tracking-tight, + )[#info.title] + + // Subtitle + if info.subtitle != none { + v(spacing-sm) + text( + size: size-subtitle, + weight: "regular", + fill: c.text-muted, + )[#info.subtitle] + } + + // Horizontal separator line (full width) + v(spacing-lg) + line(length: 100%, stroke: 1pt + c.border-medium) + v(spacing-lg) + + // Author, institution, date (left-aligned) + text( + size: size-body, + weight: "medium", + fill: c.text-secondary, + )[#info.author] + + if info.institution != none { + v(spacing-2xs) + text( + size: size-caption, + fill: c.text-muted, + )[#info.institution] + } + + if info.date != none { + v(spacing-sm) + text( + size: size-caption, + fill: c.text-light, + weight: "light", + )[ + #if type(info.date) == datetime { + info.date.display("[month repr:long] [day], [year]") + } else { + info.date + } + ] + } + + // Extra content + if extra != none { + v(spacing-lg) + extra + } + + // Golden ratio spacing below + v(1fr) + } + + touying-slide(self: self, config: config, body) +}) + +/// Split title slide (two-column with vertical separator) +#let title-slide-split( + config: (:), + logo: none, + extra: none, + colors: none, + graphic: none, // Optional graphic for right side +) = touying-slide-wrapper(self => { + let info = self.info + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + let self = utils.merge-dicts( + self, + config-common(freeze-slide-counter: true), + config-page( + margin: spacing-2xl, + header: none, + footer: none, + fill: c.bg-base, + ), + ) + + let body = { + grid( + columns: (golden-split-left, 2pt, 1fr), + column-gutter: spacing-xl, + rows: (1fr,), + // Left side: Title and subtitle + { + set align(left + horizon) + block(width: 100%)[ + // Logo at top + #if logo != none { + box(height: 40pt)[#logo] + v(spacing-xl) + } + + // Title + #text( + size: size-title, + weight: "semibold", + fill: c.text-primary, + tracking: tracking-tight, + )[#info.title] + + // Subtitle + #if info.subtitle != none { + v(spacing-sm) + text( + size: size-subtitle, + weight: "regular", + fill: c.text-muted, + )[#info.subtitle] + } + ] + }, + // Vertical separator + { + align(center + horizon)[ + #rect( + width: 2pt, + height: 60%, + fill: c.border-medium, + radius: 1pt, + ) + ] + }, + // Right side: Author info or graphic + { + set align(left + horizon) + block(width: 100%)[ + #if graphic != none { + align(center)[#graphic] + v(spacing-xl) + } + + // Author + #text( + size: size-body, + weight: "medium", + fill: c.text-secondary, + )[#info.author] + + // Institution + #if info.institution != none { + v(spacing-xs) + text( + size: size-caption, + fill: c.text-muted, + )[#info.institution] + } + + // Date + #if info.date != none { + v(spacing-md) + text( + size: size-caption, + fill: c.text-light, + weight: "light", + )[ + #if type(info.date) == datetime { + info.date.display("[month repr:long] [day], [year]") + } else { + info.date + } + ] + } + + // Extra content + #if extra != none { + v(spacing-lg) + extra + } + ] + } + ) + } + + touying-slide(self: self, config: config, body) +}) + +/// Main title slide function with layout selection +/// layout: "moloch" (default), "centered", "split" +#let title-slide( + config: (:), + logo: none, + extra: none, + colors: none, + layout: "moloch", + use-golden-ratio: true, + graphic: none, +) = { + if layout == "moloch" { + title-slide-moloch(config: config, logo: logo, extra: extra, colors: colors) + } else if layout == "split" { + title-slide-split(config: config, logo: logo, extra: extra, colors: colors, graphic: graphic) + } else { + title-slide-centered(config: config, logo: logo, extra: extra, colors: colors, use-golden-ratio: use-golden-ratio) + } +} + +// ============================================================================= +// STANDOUT SLIDE (Moloch-inspired) +// ============================================================================= + +/// Standout slide with contrast colors for emphasis +/// Perfect for "Thank you", "Questions?", key takeaways +/// Uses dark bg with accent text (different from focus slide's gradient) +#let standout-slide(config: (:), body, colors: none) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + let self = utils.merge-dicts( + self, + config-common(freeze-slide-counter: true), + config-page( + fill: c.standout-bg, // Dark/contrast background + margin: spacing-3xl, + header: none, + footer: none, + ), + ) + + set text( + size: size-focus, + weight: "semibold", + fill: c.standout-text, // Accent color text + tracking: tracking-tight, + ) + + // True vertical centering using fil spacing (Moloch fix) + touying-slide(self: self, config: config)[ + #v(1fr) + #align(center)[#body] + #v(1fr) + ] +}) + +// ============================================================================= +// FOCUS SLIDE (Gradient background - original style) +// ============================================================================= + +/// Focus slide with gradient background +#let focus-slide(config: (:), body, colors: none) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + let accent-grad = gradient.linear( + angle: 135deg, + (c.accent-secondary, 0%), + (c.accent-primary, 50%), + (c.accent-deep, 100%) + ) + + let self = utils.merge-dicts( + self, + config-common(freeze-slide-counter: true), + config-page( + fill: accent-grad, + margin: spacing-3xl, + header: none, + footer: none, + ), + ) + + set text( + size: size-focus, + weight: "medium", + fill: c.focus-text, + tracking: tracking-tight, + ) + + touying-slide(self: self, config: config, align(center + horizon, body)) +}) + +// ============================================================================= +// SECTION SLIDE +// ============================================================================= + +/// Section slide with optional progress bar +#let section-slide(config: (:), body, colors: none, show-progress: false) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + let self = utils.merge-dicts( + self, + config-common(freeze-slide-counter: true), + config-page( + margin: spacing-3xl, + header: none, + footer: none, + fill: c.bg-base, + ), + ) + + let content = { + set align(center) + v(1fr * phi) + + text( + size: size-title, + weight: "semibold", + fill: c.text-primary, + tracking: tracking-tight, + )[#body] + + v(spacing-md) + + // Show either progress bar OR accent line, not both + if show-progress { + block(width: 50%)[ + #make-progress-bar(c, height: 3pt, position: "foot") + ] + } else { + accent-line(width: 72pt, colors: c) + } + + v(1fr) + } + + touying-slide(self: self, config: config, content) +}) + +/// New section slide function (auto-called by Touying) +#let new-section-slide(config: (:), body, colors: none) = section-slide(config: config, colors: colors)[ + #utils.display-current-heading(level: 1) + #body +] + +// ============================================================================= +// CENTERED SLIDE HELPER +// ============================================================================= + +/// Centered slide helper +#let centered-slide(config: (:), ..args) = touying-slide-wrapper(self => { + touying-slide( + self: self, + ..args.named(), + config: config, + align(center + horizon, args.pos().sum(default: none)) + ) +}) + +// ============================================================================= +// FIGURE SLIDES +// ============================================================================= + +/// Figure slide with elegant framing +#let figure-slide( + fig, + config: (:), + title: none, + caption: none, + colors: none, +) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + // Use Touying's header mechanism (identical to regular slides) + let header-fn(self) = { + if title != none { + moloch-header-bar-touying(title, c) + } + } + + let self = utils.merge-dicts( + self, + config-page(header: header-fn), + ) + + let body = { + v(1fr) + + set align(center) + block( + width: 85%, + inset: spacing-sm, + )[#fig] + + if caption != none { + v(spacing-md) + fig-caption(caption, colors: c) + } + + v(1fr) + } + + touying-slide(self: self, config: config, body) +}) + +/// Split figure slide +#let figure-slide-split( + fig-left, + fig-right, + config: (:), + title: none, + caption-left: none, + caption-right: none, + colors: none, +) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + // Use Touying's header mechanism (identical to regular slides) + let header-fn(self) = { + if title != none { + moloch-header-bar-touying(title, c) + } + } + + let self = utils.merge-dicts( + self, + config-page(header: header-fn), + ) + + let body = { + v(1fr) + + grid( + columns: (1fr, 1fr), + column-gutter: spacing-xl, + { + set align(center) + fig-left + if caption-left != none { + v(spacing-sm) + fig-caption(caption-left, colors: c) + } + }, + { + set align(center) + fig-right + if caption-right != none { + v(spacing-sm) + fig-caption(caption-right, colors: c) + } + } + ) + + v(1fr) + } + + touying-slide(self: self, config: config, body) +}) + +// ============================================================================= +// EQUATION SLIDE +// ============================================================================= + +/// Equation slide with elegant definition box +/// citation: optional (bib-key: "...", label: "...") for cite-box +#let equation-slide( + eq, + config: (:), + title: none, + subtitle: none, + definitions: none, + citation: none, + colors: none, +) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + let progressbar = self.store.at("progressbar", default: "foot") + + // Use Touying's header mechanism (identical to regular slides) + let header-fn(self) = { + if title != none { + moloch-header-bar-touying(title, c) + } + } + + // Footer with progress bar and page numbers (same as regular slide) + let footer-fn(self) = context { + let current = utils.slide-counter.get().first() + let total = utils.last-slide-counter.final().first() + + v(spacing-sm) + + if progressbar == "foot" { + components.left-and-right( + make-progress-bar(c, height: 2pt, position: "foot"), + text(fill: c.text-secondary, size: size-small)[ + #current #text(fill: c.text-muted)[/] #total + ] + ) + } else { + align(right)[ + #text(fill: c.text-secondary, size: size-small)[ + #current #text(fill: c.text-muted)[/] #total + ] + ] + } + } + + let self = utils.merge-dicts( + self, + config-page(header: header-fn, footer: footer-fn), + ) + + let body = { + // Subtitle below header (in body) + if subtitle != none { + text(size: size-small, fill: c.text-muted)[#subtitle] + v(spacing-md) + } + + v(1fr) + + set align(center) + text(size: 22pt, fill: c.text-primary)[#eq] + + if definitions != none { + v(spacing-2xl) + block( + fill: c.bg-wash, + stroke: 0.5pt + c.border-subtle, + radius: radius-lg, + inset: spacing-lg, + width: auto, + )[ + #set align(left) + #set text(size: size-small, fill: c.text-secondary) + #definitions + ] + } + + v(1fr) + + // Citation box if provided + if citation != none { + cite-box( + citation.at("bib-key"), + display-label: citation.at("label", default: none), + position: citation.at("position", default: "bottom-right"), + colors: c, + ) + } + } + + touying-slide(self: self, config: config, body) +}) + +// ============================================================================= +// ACKNOWLEDGEMENT SLIDE +// ============================================================================= + +/// Acknowledgement slide with refined cards +#let acknowledgement-slide( + config: (:), + title: [Acknowledgements], + subtitle: none, + people: (), + institutions: (), + extra: none, + colors: none, +) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + // Use Touying's header mechanism (identical to regular slides) + let header-fn(self) = { + moloch-header-bar-touying(title, c) + } + + let self = utils.merge-dicts( + self, + config-page(header: header-fn), + ) + + let body = { + // Subtitle below header (in body) + if subtitle != none { + text(size: size-small, fill: c.text-muted)[#subtitle] + v(spacing-md) + } + + // People grid + if people.len() > 0 { + let cols = calc.min(people.len(), 4) + grid( + columns: (1fr,) * cols, + column-gutter: spacing-xl, + ..people.map(p => { + person-card( + p.at("name", default: "Name"), + p.at("role", default: "Role"), + image-path: p.at("image", default: none), + ) + }) + ) + v(spacing-2xl) + } + + // Institutions + if institutions.len() > 0 { + let cols = calc.min(institutions.len(), 4) + grid( + columns: (1fr,) * cols, + column-gutter: spacing-xl, + ..institutions.map(inst => { + if type(inst) == str { + institution-card(inst) + } else { + institution-card( + inst.at("name", default: "Institution"), + logo-path: inst.at("logo", default: none), + ) + } + }) + ) + v(spacing-lg) + } + + // Extra content + if extra != none { + v(spacing-md) + text(fill: c.text-muted, size: size-small)[#extra] + } + } + + touying-slide(self: self, config: config, body) +}) + +// ============================================================================= +// ENDING SLIDE +// ============================================================================= + +/// Elegant ending/thank you slide +#let ending-slide( + config: (:), + title: [Thank You], + subtitle: [Questions?], + contact: (), + colors: none, +) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + let self = utils.merge-dicts( + self, + config-page( + margin: spacing-3xl, + header: none, + footer: none, + fill: c.bg-base, + ), + ) + + let body = { + set align(center) + + v(1fr * phi) + + // Elegant title + text( + size: size-display, + weight: "light", + fill: c.text-primary, + tracking: tracking-tight, + )[#title] + + // Accent line + v(spacing-lg) + accent-line(width: 48pt, colors: c) + v(spacing-lg) + + // Subtitle + if subtitle != none { + text( + size: size-subtitle, + weight: "regular", + fill: c.text-muted, + )[#subtitle] + } + + // Contact info + if contact.len() > 0 { + v(spacing-2xl) + for item in contact { + text(fill: c.text-light, size: size-caption, weight: "light")[#item] + v(spacing-2xs) + } + } + + v(1fr) + } + + touying-slide(self: self, config: config, body) +}) + +// ============================================================================= +// BIBLIOGRAPHY SLIDE +// ============================================================================= + +/// Bibliography slide using Typst's native bibliography support +/// bib-content: pass `bibliography("path/to/file.bib")` directly +#let bibliography-slide( + config: (:), + title: [References], + bib-content: none, + colors: none, +) = touying-slide-wrapper(self => { + let c = if colors != none { colors } else { + self.store.at("theme-colors", default: get-theme-colors()) + } + + // Use Touying's header mechanism + let header-fn(self) = { + moloch-header-bar-touying(title, c) + } + + let self = utils.merge-dicts( + self, + config-page(header: header-fn), + ) + + let body = { + // Add label for cite-box linking + [#metadata("bibliography") ] + + v(spacing-sm) + + // Display the bibliography content + set text(size: size-small, fill: c.text-secondary) + if bib-content != none { + bib-content + } else { + text(fill: c.text-muted)[No bibliography specified.] + } + } + + touying-slide(self: self, config: config, body) +}) diff --git a/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Dracula.tmTheme b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Dracula.tmTheme new file mode 100644 index 0000000000..b45d2f988b --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Dracula.tmTheme @@ -0,0 +1,535 @@ + + + + + + + + name + Dracula + settings + + + settings + + background + #282a36 + caret + #f8f8f0 + foreground + #f8f8f2 + invisibles + #3B3A32 + lineHighlight + #44475a + selection + #44475a + findHighlight + #effb7b + findHighlightForeground + #000000 + selectionBorder + #222218 + activeGuide + #9D550FB0 + bracketsForeground + #F8F8F2A5 + bracketsOptions + underline + bracketContentsForeground + #F8F8F2A5 + bracketContentsOptions + underline + tagsOptions + stippled_underline + + + + name + Comment + scope + comment + settings + + foreground + #6272a4 + fontStyle + + + + + name + String + scope + string + settings + + foreground + #f1fa8c + + + + name + Number + scope + constant.numeric + settings + + foreground + #bd93f9 + + + + name + Built-in constant + scope + constant.language + settings + + foreground + #bd93f9 + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #bd93f9 + + + + name + Variable + scope + variable + settings + + fontStyle + + + + + name + Ruby's @variable + scope + variable.other.readwrite.instance + settings + + fontStyle + + foreground + #ffb86c + + + + name + String interpolation + scope + constant.character.escaped, constant.character.escape, string source, string source.ruby + settings + + fontStyle + + foreground + #ff79c6 + + + + name + Keyword + scope + keyword + settings + + foreground + #ff79c6 + + + + name + Storage + scope + storage + settings + + fontStyle + + foreground + #ff79c6 + + + + name + Storage type + scope + storage.type + settings + + fontStyle + italic + foreground + #8be9fd + + + + name + Class name + scope + entity.name.class + settings + + fontStyle + underline + foreground + #50fa7b + + + + name + Inherited class + scope + entity.other.inherited-class + settings + + fontStyle + italic underline + foreground + #50fa7b + + + + name + Function name + scope + entity.name.function + settings + + fontStyle + + foreground + #50fa7b + + + + name + Function argument + scope + variable.parameter + settings + + fontStyle + italic + foreground + #ffb86c + + + + name + Tag name + scope + entity.name.tag + settings + + fontStyle + + foreground + #ff79c6 + + + + name + Tag attribute + scope + entity.other.attribute-name + settings + + fontStyle + + foreground + #50fa7b + + + + name + Library function + scope + support.function + settings + + fontStyle + + foreground + #8be9fd + + + + name + Library constant + scope + support.constant + settings + + fontStyle + + foreground + #6be5fd + + + + name + Library class/type + scope + support.type, support.class + settings + + fontStyle + italic + foreground + #66d9ef + + + + name + Library variable + scope + support.other.variable + settings + + fontStyle + + + + + name + Invalid + scope + invalid + settings + + background + #ff79c6 + fontStyle + + foreground + #F8F8F0 + + + + name + Invalid deprecated + scope + invalid.deprecated + settings + + background + #bd93f9 + foreground + #F8F8F0 + + + + name + JSON String + scope + meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #CFCFC2 + + + + name + diff.header + scope + meta.diff, meta.diff.header + settings + + foreground + #6272a4 + + + + name + diff.deleted + scope + markup.deleted + settings + + foreground + #ff79c6 + + + + name + diff.inserted + scope + markup.inserted + settings + + foreground + #50fa7b + + + + name + diff.changed + scope + markup.changed + settings + + foreground + #E6DB74 + + + + scope + constant.numeric.line-number.find-in-files - match + settings + + foreground + #bd93f9 + + + + scope + entity.name.filename + settings + + foreground + #E6DB74 + + + + scope + message.error + settings + + foreground + #F83333 + + + + name + JSON Punctuation + scope + punctuation.definition.string.begin.json - meta.structure.dictionary.value.json, punctuation.definition.string.end.json - meta.structure.dictionary.value.json + settings + + foreground + #EEEEEE + + + + name + JSON Structure + scope + meta.structure.dictionary.json string.quoted.double.json + settings + + foreground + #8be9fd + + + + name + JSON String + scope + meta.structure.dictionary.value.json string.quoted.double.json + settings + + foreground + #f1fa8c + + + + name + JSON: 6 deep + scope + meta meta meta meta meta meta meta.structure.dictionary.value string + settings + + foreground + #50fa7b + + + + name + JSON: 5 deep + scope + meta meta meta meta meta meta.structure.dictionary.value string + settings + + foreground + #ffb86c + + + + name + JSON: 4 deep + scope + meta meta meta meta meta.structure.dictionary.value string + settings + + foreground + #ff79c6 + + + + name + JSON: 3 deep + scope + meta meta meta meta.structure.dictionary.value string + settings + + foreground + #bd93f9 + + + + name + JSON: 2 deep + scope + meta meta meta.structure.dictionary.value string + settings + + foreground + #50fa7b + + + + name + JSON: 1 deep + scope + meta meta.structure.dictionary.value string + settings + + foreground + #ffb86c + + + + uuid + 83091B89-765E-4F0D-9275-0EC6CB084126 + colorSpaceName + sRGB + semanticClass + theme.dark.dracula + author + Zeno Rocha + + diff --git a/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Dark.tmTheme b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Dark.tmTheme new file mode 100644 index 0000000000..0aba8c4fe1 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Dark.tmTheme @@ -0,0 +1,641 @@ + + + + + author + GitHub + settings + + + settings + + background + #24292e + foreground + #f6f8fa + lineHighlight + #444d56 + invisibles + #6a737d + selection + #4c2889 + caret + #fff + diffRenamed + #fafbfc + diffModified + #f9c513 + diffDeleted + #d73a49 + diffAdded + #34d058 + inactiveSelection + #444d56 + selectionBorder + #444d56 + findHighlight + #fb8532 + findHighlightForeground + #24292e + guide + #6a737d + activeGuide + #f6f8fa + stackGuide + #959da5 + highlight + #f6f8fa + popupCss + <![CDATA[html { background-color: #444d56; } h1, h2, h3, h4, h5, h6 { color: #0366d6; margin-top: 0.2em; margin-bottom: 0.2em; } h1 { font-size: 1.5em; } h2 { font-size: 1.4em; } h3 { font-size: 1.3em; } h4 { font-size: 1.2em; } h5 { font-size: 1.1em; } h6 { font-size: 1em; } blockquote { color: #c8e1ff; display: block; font-style: italic; } pre { display: block; } a { color: #79b8ff; font-style: underline; } body { color: #f6f8fa; background-color: #24292e; margin: 1px; font-size: 1em; padding: 0.2em; } .danger { color: #d73a49; } .important, .attention { color: #b392f0; } .caution, .warning { color: #fb8532; } .note { color: #fb8532; }]]> + highlightForeground + #f6f8fa + tagsOptions + underline + bracketContentsOptions + underline + bracketContentsForeground + #e1e4e8 + bracketsOptions + underline + bracketsForeground + #e1e4e8 + gutterForeground + #f6f8fa + + + + scope + comment, punctuation.definition.comment, string.comment + settings + + foreground + #959da5 + + name + Comment + + + scope + constant, entity.name.constant, variable.other.constant, variable.language + settings + + foreground + #c8e1ff + + name + Constant + + + scope + keyword.operator.symbole, keyword.other.mark + name + Clojure workaround; don't highlight these separately from their enclosing scope + settings + + + + scope + entity, entity.name + settings + + fontStyle + + foreground + #b392f0 + + name + Entity + + + scope + variable.parameter.function + settings + + foreground + #f6f8fa + + + + scope + entity.name.tag + settings + + fontStyle + + foreground + #7bcc72 + + + + scope + keyword + settings + + fontStyle + + foreground + #ea4a5a + + name + Keyword + + + scope + storage, storage.type + settings + + foreground + #ea4a5a + + name + Storage + + + scope + storage.modifier.package, storage.modifier.import, storage.type.java + settings + + foreground + #f6f8fa + + + + scope + string, punctuation.definition.string, string punctuation.section.embedded source + settings + + fontStyle + + foreground + #79b8ff + + name + String + + + name + Ada workaround; don't highlight imports as strings + scope + string.unquoted.import.ada + settings + + + + scope + support + settings + + fontStyle + + foreground + #c8e1ff + + name + Support + + + scope + meta.property-name + settings + + fontStyle + + foreground + #c8e1ff + + + + scope + variable + settings + + fontStyle + + foreground + #fb8532 + + name + Variable + + + scope + variable.other + settings + + foreground + #f6f8fa + + + + scope + invalid.broken + settings + + fontStyle + bold italic underline + foreground + #d73a49 + + name + Invalid - Broken + + + scope + invalid.deprecated + settings + + fontStyle + bold italic underline + foreground + #d73a49 + + name + Invalid – Deprecated + + + scope + invalid.illegal + settings + + fontStyle + italic underline + foreground + #fafbfc + background + #d73a49 + + name + Invalid – Illegal + + + scope + carriage-return + settings + + fontStyle + italic underline + foreground + #fafbfc + background + #d73a49 + content + ^M + + name + Carriage Return + + + scope + invalid.unimplemented + settings + + fontStyle + bold italic underline + foreground + #d73a49 + + name + Invalid - Unimplemented + + + scope + message.error + settings + + foreground + #d73a49 + + + + scope + string source + settings + + fontStyle + + foreground + #f6f8fa + + name + String embedded-source + + + scope + string variable + settings + + fontStyle + + foreground + #c8e1ff + + name + String variable + + + scope + source.regexp, string.regexp + settings + + fontStyle + + foreground + #79b8ff + + name + String.regexp + + + scope + string.regexp.character-class, string.regexp constant.character.escape, string.regexp source.ruby.embedded, string.regexp string.regexp.arbitrary-repitition + settings + + foreground + #79b8ff + + name + String.regexp.«special» + + + scope + string.regexp constant.character.escape + settings + + fontStyle + bold + foreground + #7bcc72 + + name + String.regexp constant.character.escape + + + scope + support.constant + settings + + fontStyle + + foreground + #c8e1ff + + name + Support.constant + + + scope + support.variable + settings + + foreground + #c8e1ff + + name + Support.variable + + + scope + meta.module-reference + settings + + foreground + #c8e1ff + + name + meta module-reference + + + scope + markup.list + settings + + foreground + #fb8532 + + name + Markup.list + + + scope + markup.heading, markup.heading entity.name + settings + + fontStyle + bold + foreground + #0366d6 + + name + Markup.heading + + + scope + markup.quote + settings + + foreground + #c8e1ff + + name + Markup.quote + + + scope + markup.italic + settings + + fontStyle + italic + foreground + #f6f8fa + + name + Markup.italic + + + scope + markup.bold + settings + + fontStyle + bold + foreground + #f6f8fa + + name + Markup.bold + + + scope + markup.raw + settings + + fontStyle + + foreground + #c8e1ff + + name + Markup.raw + + + scope + markup.deleted, meta.diff.header.from-file, punctuation.definition.deleted + settings + + background + #ffeef0 + foreground + #b31d28 + + name + Markup.deleted + + + scope + markup.inserted, meta.diff.header.to-file, punctuation.definition.inserted + settings + + background + #f0fff4 + foreground + #176f2c + + name + Markup.inserted + + + scope + markup.changed, punctuation.definition.changed + settings + + background + #fffdef + foreground + #b08800 + + + + scope + markup.ignored, markup.untracked + settings + + foreground + #2f363d + background + #959da5 + + + + scope + meta.diff.range + settings + + fontStyle + bold + foreground + #b392f0 + + + + scope + meta.diff.header + settings + + foreground + #c8e1ff + + + + scope + meta.separator + settings + + fontStyle + bold + foreground + #0366d6 + + name + Meta.separator + + + name + Output + scope + meta.output + settings + + foreground + #0366d6 + + + + scope + brackethighlighter.tag, brackethighlighter.curly, brackethighlighter.round, brackethighlighter.square, brackethighlighter.angle, brackethighlighter.quote + settings + + foreground + #ffeef0 + + + + scope + brackethighlighter.unmatched + settings + + foreground + #d73a49 + + + + scope + sublimelinter.mark.error + settings + + foreground + #d73a49 + + + + scope + sublimelinter.mark.warning + settings + + foreground + #fb8532 + + + + scope + sublimelinter.gutter-mark + settings + + foreground + #6a737d + + + + scope + constant.other.reference.link, string.other.link + settings + + foreground + #79b8ff + fontStyle + underline + + + + comment + GitHub Dark syntax theme + name + GitHub Dark + semanticClass + theme.dark.github + filename + github-dark + uuid + C8E24EAE-6212-41E3-AC1A-F49362B6150D + + \ No newline at end of file diff --git a/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Light.tmTheme b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Light.tmTheme new file mode 100644 index 0000000000..6150769ea9 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/GitHub-Light.tmTheme @@ -0,0 +1,643 @@ + + + + + author + GitHub + settings + + + settings + + selection + #c8c8fa + lineHighlight + #fafbfc + background + #fff + foreground + #24292e + invisibles + #959da5 + caret + #24292e + diffRenamed + #fafbfc + diffModified + #f9c513 + diffDeleted + #d73a49 + diffAdded + #34d058 + markdown + #f7f7f7 + inactiveSelection + #fafbfc + selectionBorder + #fafbfc + findHighlight + #e36209 + findHighlightForeground + #fff8f2 + guide + #959da5 + activeGuide + #24292e + stackGuide + #959da5 + highlight + #444d56 + popupCss + <![CDATA[html { background-color: #e0e0e0; } h1, h2, h3, h4, h5, h6 { color: #005cc5; margin-top: 0.2em; margin-bottom: 0.2em; } h1 { font-size: 1.5em; } h2 { font-size: 1.4em; } h3 { font-size: 1.3em; } h4 { font-size: 1.2em; } h5 { font-size: 1.1em; } h6 { font-size: 1em; } blockquote { color: #22863a; display: block; font-style: italic; } pre { display: block; } a { color: #032f62; font-style: underline; } body { color: #24292e; background-color: #fff; margin: 1px; font-size: 1em; padding: 0.2em; } .danger { color: #b31d28; } .important, .attention { color: #6f42c1; } .caution, .warning { color: #e36209; } .note { color: #735c0f; }]]> + highlightForeground + #444d56 + tagsOptions + underline + bracketContentsOptions + underline + bracketContentsForeground + #24292e + bracketsOptions + underline + bracketsForeground + #24292e + gutterForeground + #24292e + + + + scope + comment, punctuation.definition.comment, string.comment + settings + + foreground + #6a737d + + name + Comment + + + scope + constant, entity.name.constant, variable.other.constant, variable.language + settings + + foreground + #005cc5 + + name + Constant + + + scope + keyword.operator.symbole, keyword.other.mark + name + Clojure workaround; don't highlight these separately from their enclosing scope + settings + + + + scope + entity, entity.name + settings + + fontStyle + + foreground + #6f42c1 + + name + Entity + + + scope + variable.parameter.function + settings + + foreground + #24292e + + + + scope + entity.name.tag + settings + + fontStyle + + foreground + #22863a + + + + scope + keyword + settings + + fontStyle + + foreground + #d73a49 + + name + Keyword + + + scope + storage, storage.type + settings + + foreground + #d73a49 + + name + Storage + + + scope + storage.modifier.package, storage.modifier.import, storage.type.java + settings + + foreground + #24292e + + + + scope + string, punctuation.definition.string, string punctuation.section.embedded source + settings + + fontStyle + + foreground + #032f62 + + name + String + + + name + Ada workaround; don't highlight imports as strings + scope + string.unquoted.import.ada + settings + + + + scope + support + settings + + fontStyle + + foreground + #005cc5 + + name + Support + + + scope + meta.property-name + settings + + fontStyle + + foreground + #005cc5 + + + + scope + variable + settings + + fontStyle + + foreground + #e36209 + + name + Variable + + + scope + variable.other + settings + + foreground + #24292e + + + + scope + invalid.broken + settings + + fontStyle + bold italic underline + foreground + #b31d28 + + name + Invalid - Broken + + + scope + invalid.deprecated + settings + + fontStyle + bold italic underline + foreground + #b31d28 + + name + Invalid – Deprecated + + + scope + invalid.illegal + settings + + fontStyle + italic underline + background + #b31d28 + foreground + #fafbfc + + name + Invalid – Illegal + + + scope + carriage-return + settings + + fontStyle + italic underline + background + #d73a49 + foreground + #fafbfc + content + ^M + + name + Carriage Return + + + scope + invalid.unimplemented + settings + + fontStyle + bold italic underline + foreground + #b31d28 + + name + Invalid - Unimplemented + + + scope + message.error + settings + + foreground + #b31d28 + + + + scope + string source + settings + + fontStyle + + foreground + #24292e + + name + String embedded-source + + + scope + string variable + settings + + fontStyle + + foreground + #005cc5 + + name + String variable + + + scope + source.regexp, string.regexp + settings + + fontStyle + + foreground + #032f62 + + name + String.regexp + + + scope + string.regexp.character-class, string.regexp constant.character.escape, string.regexp source.ruby.embedded, string.regexp string.regexp.arbitrary-repitition + settings + + foreground + #032f62 + + name + String.regexp.«special» + + + scope + string.regexp constant.character.escape + settings + + fontStyle + bold + foreground + #22863a + + name + String.regexp constant.character.escape + + + scope + support.constant + settings + + fontStyle + + foreground + #005cc5 + + name + Support.constant + + + scope + support.variable + settings + + foreground + #005cc5 + + name + Support.variable + + + scope + meta.module-reference + settings + + foreground + #005cc5 + + name + meta module-reference + + + scope + markup.list + settings + + foreground + #735c0f + + name + Markup.list + + + scope + markup.heading, markup.heading entity.name + settings + + fontStyle + bold + foreground + #005cc5 + + name + Markup.heading + + + scope + markup.quote + settings + + foreground + #22863a + + name + Markup.quote + + + scope + markup.italic + settings + + fontStyle + italic + foreground + #24292e + + name + Markup.italic + + + scope + markup.bold + settings + + fontStyle + bold + foreground + #24292e + + name + Markup.bold + + + scope + markup.raw + settings + + fontStyle + + foreground + #005cc5 + + name + Markup.raw + + + scope + markup.deleted, meta.diff.header.from-file, punctuation.definition.deleted + settings + + background + #ffeef0 + foreground + #b31d28 + + name + Markup.deleted + + + scope + markup.inserted, meta.diff.header.to-file, punctuation.definition.inserted + settings + + background + #f0fff4 + foreground + #22863a + + name + Markup.inserted + + + scope + markup.changed, punctuation.definition.changed + settings + + background + #ffebda + foreground + #e36209 + + + + scope + markup.ignored, markup.untracked + settings + + foreground + #f6f8fa + background + #005cc5 + + + + scope + meta.diff.range + settings + + foreground + #6f42c1 + fontStyle + bold + + + + scope + meta.diff.header + settings + + foreground + #005cc5 + + + + scope + meta.separator + settings + + fontStyle + bold + foreground + #005cc5 + + name + Meta.separator + + + name + Output + scope + meta.output + settings + + foreground + #005cc5 + + + + scope + brackethighlighter.tag, brackethighlighter.curly, brackethighlighter.round, brackethighlighter.square, brackethighlighter.angle, brackethighlighter.quote + settings + + foreground + #586069 + + + + scope + brackethighlighter.unmatched + settings + + foreground + #b31d28 + + + + scope + sublimelinter.mark.error + settings + + foreground + #b31d28 + + + + scope + sublimelinter.mark.warning + settings + + foreground + #e36209 + + + + scope + sublimelinter.gutter-mark + settings + + foreground + #959da5 + + + + scope + constant.other.reference.link, string.other.link + settings + + foreground + #032f62 + fontStyle + underline + + + + comment + GitHub Light syntax theme + name + GitHub Light + semanticClass + theme.light.github + filename + github-light + uuid + A1C4DFA0-7031-11E4-9803-0800200C9A66 + + \ No newline at end of file diff --git a/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night-Eighties.tmTheme b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night-Eighties.tmTheme new file mode 100644 index 0000000000..4c6b8eeb69 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night-Eighties.tmTheme @@ -0,0 +1,247 @@ + + + + + comment + http://chriskempson.com + name + Tomorrow Night - Eighties + settings + + + settings + + background + #2D2D2D + caret + #CCCCCC + foreground + #CCCCCC + invisibles + #6A6A6A + lineHighlight + #393939 + selection + #515151 + + + + name + Comment + scope + comment + settings + + foreground + #999999 + + + + name + Foreground + scope + keyword.operator.class, constant.other, source.php.embedded.line + settings + + fontStyle + + foreground + #CCCCCC + + + + name + Variable, String Link, Tag Name, GitGutter deleted + scope + variable, support.other.variable, string.other.link, entity.name.tag, entity.other.attribute-name, meta.tag, declaration.tag, markup.deleted.git_gutter + settings + + foreground + #F2777A + + + + name + Number, Constant, Function Argument, Tag Attribute, Embedded + scope + constant.numeric, constant.language, support.constant, constant.character, variable.parameter, punctuation.section.embedded, keyword.other.unit + settings + + fontStyle + + foreground + #F99157 + + + + name + Class, Support + scope + entity.name.class, entity.name.type.class, support.type, support.class + settings + + fontStyle + + foreground + #FFCC66 + + + + name + String, Symbols, Inherited Class, Markup Heading, GitGutter inserted + scope + string, constant.other.symbol, entity.other.inherited-class, entity.name.filename, markup.heading, markup.inserted.git_gutter + settings + + fontStyle + + foreground + #99CC99 + + + + name + Operator, Misc + scope + keyword.operator, constant.other.color + settings + + foreground + #66CCCC + + + + name + Function, Special Method, Block Level, GitGutter changed + scope + entity.name.function, meta.function-call, support.function, keyword.other.special-method, meta.block-level, markup.changed.git_gutter + settings + + fontStyle + + foreground + #6699CC + + + + name + Keyword, Storage + scope + keyword, storage, storage.type, entity.name.tag.css + settings + + fontStyle + + foreground + #CC99CC + + + + name + Invalid + scope + invalid + settings + + background + #F2777A + fontStyle + + foreground + #CDCDCD + + + + name + Separator + scope + meta.separator + settings + + background + #99CCCC + foreground + #CDCDCD + + + + name + Deprecated + scope + invalid.deprecated + settings + + background + #CC99CC + fontStyle + + foreground + #CDCDCD + + + + name + Diff foreground + scope + markup.inserted.diff, markup.deleted.diff, meta.diff.header.to-file, meta.diff.header.from-file + settings + + foreground + #FFFFFF + + + + name + Diff insertion + scope + markup.inserted.diff, meta.diff.header.to-file + settings + + foreground + #718c00 + + + + name + Diff deletion + scope + markup.deleted.diff, meta.diff.header.from-file + settings + + foreground + #c82829 + + + + name + Diff header + scope + meta.diff.header.from-file, meta.diff.header.to-file + settings + + foreground + #FFFFFF + background + #4271ae + + + + name + Diff range + scope + meta.diff.range + settings + + fontStyle + italic + foreground + #3e999f + + + + uuid + DE477E5B-BD4D-46B0-BF80-2EA32A2814D5 + colorSpaceName + sRGB + + diff --git a/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night.tmTheme b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night.tmTheme new file mode 100644 index 0000000000..e0c504341b --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow-Night.tmTheme @@ -0,0 +1,247 @@ + + + + + comment + http://chriskempson.com + name + Tomorrow Night + settings + + + settings + + background + #1D1F21 + caret + #AEAFAD + foreground + #C5C8C6 + invisibles + #4B4E55 + lineHighlight + #282A2E + selection + #373B41 + + + + name + Comment + scope + comment + settings + + foreground + #969896 + + + + name + Foreground + scope + keyword.operator.class, constant.other, source.php.embedded.line + settings + + fontStyle + + foreground + #CED1CF + + + + name + Variable, String Link, Regular Expression, Tag Name, GitGutter deleted + scope + variable, support.other.variable, string.other.link, string.regexp, entity.name.tag, entity.other.attribute-name, meta.tag, declaration.tag, markup.deleted.git_gutter + settings + + foreground + #CC6666 + + + + name + Number, Constant, Function Argument, Tag Attribute, Embedded + scope + constant.numeric, constant.language, support.constant, constant.character, variable.parameter, punctuation.section.embedded, keyword.other.unit + settings + + fontStyle + + foreground + #DE935F + + + + name + Class, Support + scope + entity.name.class, entity.name.type.class, support.type, support.class + settings + + fontStyle + + foreground + #F0C674 + + + + name + String, Symbols, Inherited Class, Markup Heading, GitGutter inserted + scope + string, constant.other.symbol, entity.other.inherited-class, entity.name.filename, markup.heading, markup.inserted.git_gutter + settings + + fontStyle + + foreground + #B5BD68 + + + + name + Operator, Misc + scope + keyword.operator, constant.other.color + settings + + foreground + #8ABEB7 + + + + name + Function, Special Method, Block Level, GitGutter changed + scope + entity.name.function, meta.function-call, support.function, keyword.other.special-method, meta.block-level, markup.changed.git_gutter + settings + + fontStyle + + foreground + #81A2BE + + + + name + Keyword, Storage + scope + keyword, storage, storage.type, entity.name.tag.css + settings + + fontStyle + + foreground + #B294BB + + + + name + Invalid + scope + invalid + settings + + background + #DF5F5F + fontStyle + + foreground + #CED2CF + + + + name + Separator + scope + meta.separator + settings + + background + #82A3BF + foreground + #CED2CF + + + + name + Deprecated + scope + invalid.deprecated + settings + + background + #B798BF + fontStyle + + foreground + #CED2CF + + + + name + Diff foreground + scope + markup.inserted.diff, markup.deleted.diff, meta.diff.header.to-file, meta.diff.header.from-file + settings + + foreground + #FFFFFF + + + + name + Diff insertion + scope + markup.inserted.diff, meta.diff.header.to-file + settings + + foreground + #718c00 + + + + name + Diff deletion + scope + markup.deleted.diff, meta.diff.header.from-file + settings + + foreground + #c82829 + + + + name + Diff header + scope + meta.diff.header.from-file, meta.diff.header.to-file + settings + + foreground + #FFFFFF + background + #4271ae + + + + name + Diff range + scope + meta.diff.range + settings + + fontStyle + italic + foreground + #3e999f + + + + uuid + F96223EB-1A60-4617-92F3-D24D4F13DB09 + colorSpaceName + sRGB + + diff --git a/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow.tmTheme b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow.tmTheme new file mode 100644 index 0000000000..2b26f3cd0a --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/syntax-themes/Tomorrow.tmTheme @@ -0,0 +1,247 @@ + + + + + comment + http://chriskempson.com + name + Tomorrow + settings + + + settings + + background + #FFFFFF + caret + #AEAFAD + foreground + #4D4D4C + invisibles + #D1D1D1 + lineHighlight + #EFEFEF + selection + #D6D6D6 + + + + name + Comment + scope + comment + settings + + foreground + #8E908C + + + + name + Foreground + scope + keyword.operator.class, constant.other, source.php.embedded.line + settings + + fontStyle + + foreground + #666969 + + + + name + Variable, String Link, Regular Expression, Tag Name, GitGutter deleted + scope + variable, support.other.variable, string.other.link, string.regexp, entity.name.tag, entity.other.attribute-name, meta.tag, declaration.tag, markup.deleted.git_gutter + settings + + foreground + #C82829 + + + + name + Number, Constant, Function Argument, Tag Attribute, Embedded + scope + constant.numeric, constant.language, support.constant, constant.character, variable.parameter, punctuation.section.embedded, keyword.other.unit + settings + + fontStyle + + foreground + #F5871F + + + + name + Class, Support + scope + entity.name.class, entity.name.type.class, support.type, support.class + settings + + fontStyle + + foreground + #C99E00 + + + + name + String, Symbols, Inherited Class, Markup Heading, GitGutter inserted + scope + string, constant.other.symbol, entity.other.inherited-class, entity.name.filename, markup.heading, markup.inserted.git_gutter + settings + + fontStyle + + foreground + #718C00 + + + + name + Operator, Misc + scope + keyword.operator, constant.other.color + settings + + foreground + #3E999F + + + + name + Function, Special Method, Block Level, GitGutter changed + scope + entity.name.function, meta.function-call, support.function, keyword.other.special-method, meta.block-level, markup.changed.git_gutter + settings + + fontStyle + + foreground + #4271AE + + + + name + Keyword, Storage + scope + keyword, storage, storage.type + settings + + fontStyle + + foreground + #8959A8 + + + + name + Invalid + scope + invalid + settings + + background + #C82829 + fontStyle + + foreground + #FFFFFF + + + + name + Separator + scope + meta.separator + settings + + background + #4271AE + foreground + #FFFFFF + + + + name + Deprecated + scope + invalid.deprecated + settings + + background + #8959A8 + fontStyle + + foreground + #FFFFFF + + + + name + Diff foreground + scope + markup.inserted.diff, markup.deleted.diff, meta.diff.header.to-file, meta.diff.header.from-file + settings + + foreground + #FFFFFF + + + + name + Diff insertion + scope + markup.inserted.diff, meta.diff.header.to-file + settings + + background + #718c00 + + + + name + Diff deletion + scope + markup.deleted.diff, meta.diff.header.from-file + settings + + background + #c82829 + + + + name + Diff header + scope + meta.diff.header.from-file, meta.diff.header.to-file + settings + + foreground + #FFFFFF + background + #4271ae + + + + name + Diff range + scope + meta.diff.range + settings + + fontStyle + italic + foreground + #3e999f + + + + uuid + 82CCD69C-F1B1-4529-B39E-780F91F07604 + colorSpaceName + sRGB + + diff --git a/packages/preview/calmly-touying/0.2.0/theme/theme.typ b/packages/preview/calmly-touying/0.2.0/theme/theme.typ new file mode 100644 index 0000000000..10b91da6ff --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/theme.typ @@ -0,0 +1,313 @@ +// Warm Amber Touying Theme - Enhanced Edition +// A soft, smooth, modern presentation theme with Moloch-inspired features +// Supports: light/dark variants, multiple color themes, progress bar placement, +// Moloch-style headers, title page variants, standout slides + +#import "@preview/touying:0.6.1": * +#import "colors.typ": * +#import "typography.typ": * +#import "components.typ": * +#import "slides.typ": * + +// ============================================================================= +// RE-EXPORT COMPONENTS +// ============================================================================= + +// Layout components (don't need colors) +#let two-col = two-col +#let three-col = three-col +#let spacer = spacer + +// Components that accept optional colors parameter +// These are re-exported as-is; colors will be passed from slides when needed +#let highlight-box = highlight-box +#let algorithm-box = algorithm-box +#let alert-box = alert-box +#let example-box = example-box +#let themed-block = themed-block +#let code-block = code-block +#let quote-block = quote-block +#let soft-shadow-box = soft-shadow-box + +// Text helpers +#let alert = alert +#let muted = muted +#let subtle = subtle +#let fig-caption = fig-caption + +// Visual elements +#let accent-line = accent-line +#let soft-divider = soft-divider +#let bullet = bullet +#let pill = pill + +// Cards +#let person-card = person-card +#let institution-card = institution-card + +// Bullet markers +#let bullet-circle = bullet-circle +#let bullet-square = bullet-square +#let bullet-dash = bullet-dash + +// Citation gadget +#let cite-box = cite-box + +// Golden ratio utilities +#let phi = phi +#let golden-center = golden-center +#let golden-major = golden-major +#let golden-minor = golden-minor +#let golden-split-left = golden-split-left +#let golden-split-right = golden-split-right + +// ============================================================================= +// RE-EXPORT SLIDE TYPES +// ============================================================================= + +#let title-slide = title-slide +#let title-slide-centered = title-slide-centered +#let title-slide-moloch = title-slide-moloch +#let title-slide-split = title-slide-split +#let focus-slide = focus-slide +#let standout-slide = standout-slide +#let figure-slide = figure-slide +#let figure-slide-split = figure-slide-split +#let equation-slide = equation-slide +#let acknowledgement-slide = acknowledgement-slide +#let ending-slide = ending-slide +#let section-slide = section-slide +#let bibliography-slide = bibliography-slide + +// ============================================================================= +// RE-EXPORT COLOR UTILITIES +// ============================================================================= + +#let get-theme-colors = get-theme-colors +#let make-gradients = make-gradients + +// ============================================================================= +// SYNTAX THEME MAPPING +// ============================================================================= + +#let _get-syntax-theme(colortheme, variant) = { + let themes = ( + "tomorrow": (light: "syntax-themes/Tomorrow.tmTheme", dark: "syntax-themes/Tomorrow-Night.tmTheme"), + "warm-amber": (light: "syntax-themes/GitHub-Light.tmTheme", dark: "syntax-themes/Tomorrow-Night-Eighties.tmTheme"), + "paper": (light: "syntax-themes/GitHub-Light.tmTheme", dark: "syntax-themes/GitHub-Dark.tmTheme"), + "dracula": (light: "syntax-themes/Tomorrow.tmTheme", dark: "syntax-themes/Dracula.tmTheme"), + ) + let t = themes.at(colortheme, default: themes.at("tomorrow")) + t.at(variant, default: t.at("light")) +} + +// ============================================================================= +// MAIN THEME FUNCTION +// ============================================================================= + +/// Main theme function with Moloch-inspired configuration options +/// +/// Arguments: +/// - aspect-ratio: "16-9" (default), "4-3" +/// - variant: "light" (default), "dark" +/// - colortheme: "tomorrow" (default), "warm-amber", "paper", "dracula" +/// - progressbar: "foot" (default), "head", "frametitle", "none" +/// - header-style: "moloch" (default, colored bar), "minimal" (gradient underline) +/// - title-layout: "moloch" (default), "centered", "split" +/// - block-fill: false (default, transparent), true (filled background) +#let calmly( + aspect-ratio: "16-9", + variant: "light", + colortheme: "tomorrow", + progressbar: "foot", + header-style: "moloch", + title-layout: "moloch", + block-fill: false, + ..args, + body, +) = { + // Get colors and syntax theme for the selected theme and variant + let colors = get-theme-colors(theme: colortheme, variant: variant) + let gradients = make-gradients(colors) + let syntax-theme-path = _get-syntax-theme(colortheme, variant) + + // Create the slide function with theme colors baked in + let themed-slide( + config: (:), + repeat: auto, + setting: body => body, + composer: auto, + ..bodies, + ) = slide( + config: config, + repeat: repeat, + setting: setting, + composer: composer, + colors: colors, + header-style: header-style, + progressbar: progressbar, + ..bodies, + ) + + // Create new-section-slide with colors + let themed-new-section-slide(config: (:), body) = new-section-slide( + config: config, + colors: colors, + body, + ) + + show: touying-slides.with( + config-page( + paper: "presentation-" + aspect-ratio, + margin: (x: spacing-2xl, top: spacing-2xl + spacing-md, bottom: 32pt), // Extra top margin for header breathing room + fill: colors.bg-base, + ), + config-common( + slide-fn: themed-slide, + new-section-slide-fn: themed-new-section-slide, + datetime-format: "[month repr:long] [day], [year]", + ), + config-store( + // Store theme colors for access in slides + theme-colors: colors, + theme-gradients: gradients, + theme-variant: variant, + theme-name: colortheme, + progressbar: progressbar, + header-style: header-style, + title-layout: title-layout, + block-fill: block-fill, + ), + config-methods( + init: (self: none, body) => { + // Get colors from store and set global state for components + let c = self.store.theme-colors + theme-colors-state.update(c) + + // Refined typography setup + set text( + font: font-body, + size: size-body, + fill: c.text-secondary, + weight: "regular", + ) + + // Elegant heading styles + set heading(numbering: none) + show heading.where(level: 1): set text( + size: size-title, + weight: "semibold", + fill: c.text-primary, + tracking: tracking-tight, + ) + show heading.where(level: 2): set text( + size: size-slide-title, + weight: "semibold", + fill: c.text-primary, + tracking: tracking-tight, + ) + + // Refined list styling with custom bullets + set list( + marker: ( + bullet-circle(color: c.accent-secondary), + bullet-square(color: c.accent-secondary), + bullet-dash(color: c.accent-secondary), + ), + indent: spacing-md, + body-indent: spacing-sm, + ) + + // Elegant numbered lists + set enum( + numbering: n => text( + fill: c.accent-primary, + weight: "medium", + size: size-small, + )[#n.], + indent: spacing-md, + body-indent: spacing-sm, + ) + + // Subtle link styling + show link: it => text(fill: c.accent-primary, weight: "medium")[#it] + + // Refined code styling with per-theme syntax highlighting + set raw(theme: syntax-theme-path) + show raw: set text(font: font-mono, size: size-code, fill: c.text-secondary) + show raw.where(block: true): block.with( + fill: c.bg-surface, + stroke: 0.5pt + c.border-subtle, + radius: radius-md, + inset: spacing-md, + width: 100%, + ) + + // Elegant emphasis + show strong: it => text(fill: c.text-primary, weight: "semibold")[#it.body] + show emph: it => text(fill: c.text-secondary, style: "italic")[#it.body] + + // Citation styling - light grey background pill + show cite: it => box( + fill: c.bg-muted, + radius: 3pt, + inset: (x: 4pt, y: 2pt), + )[#text(size: 0.9em)[#it]] + + // Math styling - larger and clearer + set math.equation(numbering: none) + show math.equation: set text(size: 1.15em) + + // Refined paragraph spacing + set par(leading: 0.7em, justify: false) + + body + }, + alert: utils.alert-with-primary-color, + cover: (self: none, body) => { + let c = self.store.theme-colors + box( + fill: c.bg-base.transparentize(30%), + radius: radius-sm, + )[#body] + }, + ), + config-colors( + primary: colors.accent-primary, + secondary: colors.accent-secondary, + tertiary: colors.accent-subtle, + neutral-lightest: colors.bg-base, + neutral-light: colors.bg-muted, + neutral-dark: colors.text-secondary, + neutral-darkest: colors.text-primary, + ), + ..args, + ) + + body +} + +// ============================================================================= +// ALIASES AND BACKWARD COMPATIBILITY +// ============================================================================= + +// Backward compatibility aliases +#let warm-amber-theme = calmly +#let thesis-theme = calmly + +// Convenience function to create a presentation with specific settings +#let moloch-style-theme = calmly.with( + header-style: "moloch", + progressbar: "foot", + title-layout: "moloch", +) + +#let minimal-style-theme = calmly.with( + header-style: "minimal", + progressbar: "foot", + title-layout: "centered", +) + +#let dark-theme = calmly.with( + variant: "dark", +) diff --git a/packages/preview/calmly-touying/0.2.0/theme/typography.typ b/packages/preview/calmly-touying/0.2.0/theme/typography.typ new file mode 100644 index 0000000000..1978061cb8 --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/theme/typography.typ @@ -0,0 +1,95 @@ +// Typography Settings - Refined & Elegant +// Optimized for readability with generous breathing room +// Includes golden ratio spacing utilities inspired by Moloch + +// ============================================================================= +// GOLDEN RATIO UTILITIES +// ============================================================================= + +// The golden ratio constant (φ ≈ 1.618) +#let phi = 1.618033988749895 + +// Golden ratio spacing - mathematically pleasing proportions +// Use for title pages and special layouts +#let golden-space-above = 1fr * phi // Larger space above +#let golden-space-below = 1fr // Smaller space below + +// Golden ratio helper for vertical centering with offset +// Creates mathematically-informed spacing above/below content +#let golden-center(body) = { + v(golden-space-above) + body + v(golden-space-below) +} + +// Golden ratio proportions for layouts +#let golden-major = phi / (1 + phi) // ~0.618 (larger portion) +#let golden-minor = 1 / (1 + phi) // ~0.382 (smaller portion) + +// Split layout using golden ratio (e.g., for title pages) +#let golden-split-left = golden-minor * 100% // ~38.2% +#let golden-split-right = golden-major * 100% // ~61.8% + +// ============================================================================= +// FONT FAMILIES +// ============================================================================= + +// Font families (prioritize installed fonts) +#let font-heading = ("Source Sans 3", "Inter", "Noto Sans", "sans-serif") +#let font-body = ("Source Sans 3", "Inter", "Noto Sans", "sans-serif") +#let font-mono = ("JetBrains Mono", "Fira Code", "Noto Sans Mono", "monospace") +#let font-math = ("STIX Two Math", "Latin Modern Math") + +// Type scale - refined sizing with more contrast +#let size-display = 42pt // Hero text +#let size-title = 34pt // Section/title slides +#let size-slide-title = 26pt // Slide headings +#let size-subtitle = 18pt // Subtitles +#let size-body = 17pt // Body text +#let size-small = 15pt // Smaller body +#let size-caption = 13pt // Captions, labels +#let size-code = 13pt // Code blocks +#let size-footnote = 11pt // Footnotes +#let size-focus = 38pt // Focus slide text +#let size-micro = 10pt // Very small text + +// Font weights - using lighter weights for elegance +#let weight-black = 900 +#let weight-bold = 700 +#let weight-semibold = 600 +#let weight-medium = 500 +#let weight-regular = 400 +#let weight-light = 300 + +// Spacing constants - generous whitespace +#let spacing-3xs = 2pt +#let spacing-2xs = 4pt +#let spacing-xs = 6pt +#let spacing-sm = 10pt +#let spacing-md = 16pt +#let spacing-lg = 24pt +#let spacing-xl = 36pt +#let spacing-2xl = 48pt +#let spacing-3xl = 64pt + +// Border radius - softer, more rounded +#let radius-sm = 6pt +#let radius-md = 10pt +#let radius-lg = 14pt +#let radius-xl = 20pt +#let radius-full = 9999pt + +// Line heights +#let leading-tight = 1.15 +#let leading-snug = 1.3 +#let leading-normal = 1.5 +#let leading-relaxed = 1.7 + +// Letter spacing +#let tracking-tight = -0.02em +#let tracking-normal = 0em +#let tracking-wide = 0.02em +#let tracking-wider = 0.04em + +// Paragraph spacing +#let par-spacing = 0.8em diff --git a/packages/preview/calmly-touying/0.2.0/thumbnail.png b/packages/preview/calmly-touying/0.2.0/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..65a905d740c4fd735c5aec8f8ebc84dcd64cedbb GIT binary patch literal 53559 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 literal 0 HcmV?d00001 diff --git a/packages/preview/calmly-touying/0.2.0/typst.toml b/packages/preview/calmly-touying/0.2.0/typst.toml new file mode 100644 index 0000000000..a3728b90af --- /dev/null +++ b/packages/preview/calmly-touying/0.2.0/typst.toml @@ -0,0 +1,23 @@ +[package] +name = "calmly-touying" +version = "0.2.0" +entrypoint = "lib.typ" +authors = ["Yichen Han"] +license = "MIT" +description = "A calm, modern presentation theme for Touying with Moloch-inspired design." +repository = "https://github.com/YHan228/calmly-touying" +keywords = ["presentation", "slides", "theme", "touying", "academic"] +categories = ["presentation", "layout"] +disciplines = ["computer-science", "mathematics", "engineering"] +compiler = "0.12.0" +exclude = [ + "examples", + "*.pdf", + ".gitignore", + ".claude", +] + +[template] +path = "template" +entrypoint = "main.typ" +thumbnail = "thumbnail.png"