From e161e858c2a57505d27875926a1f9736ede678bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20Johan=20G=C3=BCtzkow?= <70779496+CJGutz@users.noreply.github.com> Date: Thu, 19 Sep 2024 21:54:37 +0200 Subject: [PATCH] 5: Add markdown rendering to eportfolio (#16) * added markdown dependency and created markdown render operation * move file path of markdown operation to context * refactor course routes and context and add course list page * styling to courses list and more in context * tailwindstyles and under development markers * simplify error handling into function --- .gitignore | 3 + Cargo.lock | 16 + eportfolio/Cargo.toml | 1 + eportfolio/src/main.rs | 120 +- eportfolio/src/render_markdown.rs | 36 + eportfolio/tailwind.config.js | 4 +- eportfolio/templates/base.html | 2 +- eportfolio/templates/course-detail.html | 9 + eportfolio/templates/course-list.html | 22 + eportfolio/templates/css/tailwind-output.css | 1362 +++++++++++++++-- .../templates/markdown/courses/CS4505.md | 3 + .../templates/markdown/courses/CS4510.md | 3 + .../templates/markdown/courses/CS4515.md | 3 + .../templates/markdown/courses/DSAIT4005.md | 3 + 14 files changed, 1405 insertions(+), 182 deletions(-) create mode 100644 eportfolio/src/render_markdown.rs create mode 100644 eportfolio/templates/course-detail.html create mode 100644 eportfolio/templates/course-list.html create mode 100644 eportfolio/templates/markdown/courses/CS4505.md create mode 100644 eportfolio/templates/markdown/courses/CS4510.md create mode 100644 eportfolio/templates/markdown/courses/CS4515.md create mode 100644 eportfolio/templates/markdown/courses/DSAIT4005.md diff --git a/.gitignore b/.gitignore index ea8c4bf..04b189f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ /target +package.json +pnpm-lock.yaml +**/*/node_modules diff --git a/Cargo.lock b/Cargo.lock index 91a34c3..1a4eda6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,9 +6,25 @@ version = 3 name = "eportfolio" version = "0.1.0" dependencies = [ + "markdown", "unchained_web", ] +[[package]] +name = "markdown" +version = "1.0.0-alpha.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911a8325e6fb87b89890cd4529a2ab34c2669c026279e61c26b7140a3d821ccb" +dependencies = [ + "unicode-id", +] + [[package]] name = "unchained_web" version = "0.1.1" + +[[package]] +name = "unicode-id" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" diff --git a/eportfolio/Cargo.toml b/eportfolio/Cargo.toml index c860bd5..ad1d724 100644 --- a/eportfolio/Cargo.toml +++ b/eportfolio/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +markdown = "1.0.0-alpha.20" unchained = { package = "unchained_web", path = "../unchained" } diff --git a/eportfolio/src/main.rs b/eportfolio/src/main.rs index e94a727..d2d7931 100644 --- a/eportfolio/src/main.rs +++ b/eportfolio/src/main.rs @@ -1,8 +1,11 @@ use std::collections::HashMap; +pub mod render_markdown; + +use render_markdown::render_md; use unchained::{ error::Error, - router::{HTTPVerb::*, ResponseContent, Route}, + router::{HTTPVerb::*, Request, Response, ResponseContent, Route}, server::Server, templates::{ context::{ctx_map, ctx_str, ctx_vec, ContextTree, Primitive}, @@ -30,6 +33,13 @@ fn handle_error(e: &Error) -> String { } } +fn load_tmpl_and_handle_error(path: &str, context: Option<HashMap<String, ContextTree>>) -> String { + match load_template(path, context, &RenderOptions::empty()) { + Ok(template) => template.to_string(), + Err(e) => handle_error(&e), + } +} + fn create_skill( id: &str, name: &str, @@ -74,15 +84,23 @@ fn create_experience( ]) } +fn create_course(course_id: &str, title: &str, image_path: &str) -> ContextTree { + ctx_map([ + ("course_id", ctx_str(course_id)), + ("title", ctx_str(title)), + ("image", ctx_str(image_path)), + ]) +} + fn folder_access(path: &str) -> Route { Route::new(GET, path, ResponseContent::FolderAccess) } fn main() { - let mut context_landing = HashMap::new(); + let mut context_base = HashMap::new(); let current_year: isize = current_year().try_into().unwrap(); - context_landing.insert( + context_base.insert( "current_year".to_string(), ContextTree::Leaf(Primitive::Num(current_year)), ); @@ -94,12 +112,14 @@ fn main() { ("label", ctx_str("Experience")), ]), ctx_map([("href", ctx_str("/skills")), ("label", ctx_str("Skills"))]), + ctx_map([("href", ctx_str("/courses")), ("label", ctx_str("Courses"))]), ]); - context_landing.insert("page_links".to_string(), page_links.clone()); + context_base.insert("page_links".to_string(), page_links.clone()); - let mut context_skills = context_landing.clone(); - let mut context_experience = context_landing.clone(); - let context_404 = context_landing.clone(); + let mut context_landing = context_base.clone(); + let mut context_skills = context_base.clone(); + let mut context_experience = context_base.clone(); + let mut context_courses = context_base.clone(); context_landing.insert( "carl_images".to_string(), @@ -139,53 +159,52 @@ fn main() { create_experience("tihlde-index", "Programmer with TIHLDE Index", "Worked as a Back-end developer for index.", "tihlde.jpg", "Aug 2021", "Jun 2022", "https://tihlde.org", "https://github.com/tihlde/lepton", vec!["Django", "Docker"]), ])); - let start = std::time::Instant::now(); - let landing = load_template( - "templates/landing.html", - Some(context_landing), - &RenderOptions::empty(), - ); - let skills = load_template( - "templates/skills.html", - Some(context_skills), - &RenderOptions::empty(), - ); - let experience = load_template( - "templates/experience.html", - Some(context_experience), - &RenderOptions::empty(), - ); - let page_404 = load_template( - "templates/404.html", - Some(context_404), - &RenderOptions::empty(), + context_courses.insert( + "course_pages".to_string(), + ctx_vec(vec![ + create_course("CS4515", "3D Computer Graphics and Animation", ""), + create_course("CS4505", "Software Architecture", ""), + create_course("DSAIT4005", "Machine and Deep Learning", ""), + create_course("CS4510", "Formal Reasoning about Software", ""), + ]), ); + + let start = std::time::Instant::now(); + let landing = + load_tmpl_and_handle_error("templates/landing.html", Some(context_landing.clone())); + let skills = load_tmpl_and_handle_error("templates/skills.html", Some(context_skills)); + let experience = + load_tmpl_and_handle_error("templates/experience.html", Some(context_experience)); + let courses = load_tmpl_and_handle_error("templates/course-list.html", Some(context_courses)); + let page_404 = load_tmpl_and_handle_error("templates/404.html", Some(context_landing)); let duration = start.elapsed(); println!("Finished rendering after {} s", duration.as_secs_f64()); let routes = vec![ + Route::new(GET, "/", ResponseContent::Str(landing)), + Route::new(GET, "/skills", ResponseContent::Str(skills)), + Route::new(GET, "/experience", ResponseContent::Str(experience)), + Route::new(GET, "/courses", ResponseContent::Str(courses)), Route::new( GET, - "/", - ResponseContent::Str(match &landing { - Ok(template) => template.to_string(), - Err(e) => handle_error(e), - }), - ), - Route::new( - GET, - "/skills", - ResponseContent::Str(match &skills { - Ok(template) => template.to_string(), - Err(e) => handle_error(e), - }), - ), - Route::new( - GET, - "/experience", - ResponseContent::Str(match &experience { - Ok(template) => template.to_string(), - Err(e) => handle_error(e), + "courses/:courseid", + ResponseContent::FromRequest({ + let page_404 = page_404.clone(); + Box::new(move |req: Request| { + let md = if let Some(courseid) = req.path_params.get("courseid") { + let mut ctx = context_base.clone(); + let path = format!("templates/markdown/courses/{}.md", courseid); + ctx.insert("course_md_path".to_string(), ctx_str(&path)); + render_md("templates/course-detail.html", Some(ctx)).ok() + } else { + None + }; + let is_some = md.is_some(); + Response::new( + Some(md.unwrap_or(page_404.clone())), + if is_some { 200 } else { 404 }, + ) + }) }), ), folder_access("/images/*"), @@ -197,10 +216,9 @@ fn main() { Route::new( GET, "/*", - ResponseContent::Str(match &page_404 { - Ok(template) => template.to_string(), - Err(e) => handle_error(e), - }), + ResponseContent::FromRequest(Box::new(move |_req: Request| { + Response::new(Some(page_404.clone()), 404) + })), ), ]; let mut server = Server::new(routes); diff --git a/eportfolio/src/render_markdown.rs b/eportfolio/src/render_markdown.rs new file mode 100644 index 0000000..50b22e6 --- /dev/null +++ b/eportfolio/src/render_markdown.rs @@ -0,0 +1,36 @@ +use std::collections::HashMap; + +use markdown::Options; +use unchained::{ + error::WebResult, + templates::{ + context::{ContextMap, ContextTree::*, Primitive::*}, + operations::{unwrap_n_params, TemplateOperation}, + render::{load_template, RenderOptions}, + }, +}; + +pub fn render_md(path: &str, context: Option<ContextMap>) -> WebResult<String> { + let closure = { + |call, ctx, opts| { + let file_path = unwrap_n_params::<1>(&call.parameters)?[0]; + let path_in_context = ctx.get(file_path); + let file_path = if let Some(Leaf(Str(valid_path))) = path_in_context { + valid_path + } else { + file_path + }; + let file_content = load_template(file_path, Some(ctx.clone()), opts)?; + let md = markdown::to_html_with_options(&file_content, &Options::gfm()); + Ok(md.unwrap_or_default()) + } + } as TemplateOperation; + + load_template( + path, + context.clone(), + &RenderOptions { + custom_operations: HashMap::from([("md", closure)]), + }, + ) +} diff --git a/eportfolio/tailwind.config.js b/eportfolio/tailwind.config.js index d569d85..545b72b 100644 --- a/eportfolio/tailwind.config.js +++ b/eportfolio/tailwind.config.js @@ -17,5 +17,7 @@ module.exports = { }, }, }, - plugins: [], + plugins: [ + require('@tailwindcss/typography'), + ], } diff --git a/eportfolio/templates/base.html b/eportfolio/templates/base.html index 88067bc..555a6a1 100644 --- a/eportfolio/templates/base.html +++ b/eportfolio/templates/base.html @@ -47,7 +47,7 @@ </div> </nav> </header> - <main class="container relative"> + <main class="grow container relative"> {* slot default *} </main> <footer class="p-4 z-10 md:flex md:items-center md:justify-around md:p-6 bg-off-white shadow-[0px_0px_10px_2px_rgba(0,0,0,0.3)]"> diff --git a/eportfolio/templates/course-detail.html b/eportfolio/templates/course-detail.html new file mode 100644 index 0000000..cbc0b9e --- /dev/null +++ b/eportfolio/templates/course-detail.html @@ -0,0 +1,9 @@ +{* component templates/base.html { +<div class="flex flex-col gap-5 items-start px-6 lg:px-20 py-6"> +<a href="/courses" class="border-b border-black mvn-button">🠐 List of courses</a> +<div class="grid w-full"> + <div class="prose prose-sm lg:prose-lg m-auto"> + {* md course_md_path *} + </div> +</div></div> +} *} diff --git a/eportfolio/templates/course-list.html b/eportfolio/templates/course-list.html new file mode 100644 index 0000000..01a4fde --- /dev/null +++ b/eportfolio/templates/course-list.html @@ -0,0 +1,22 @@ +{* comment { + Takes in a list of page information called "pages". Each has a course id (also file name), title, and possible image path. +} *} +{* component templates/base.html { + <div class="w-full my-10"> + <div class="m-10"> + <h1 class="text-3xl lg:text-5xl font-bold lg:w-2/3">Courses</h1> + <p class="text-gray-700">Following is a list of pages with information about some of the courses I have taken.</p> + </div> + <div class="grid lg:grid-cols-3 grid-cols-1 gap-5 p-4 place-items-stretch"> + {* for page in course_pages { + <a href="/courses/{* get page.course_id *}" class="focus:ring-2 focus:rounded-lg focus:ring-black focus:outline-none"> + <div class="border-2 border-gray-500 rounded-lg p-4 bg-zinc-50 mvn-button shadow-gray-800 shadow-md h-full"> + <p class="text-sm ">{* get page.course_id *}</p> + <h3 class="text-xl">{* get page.title *}</h3> + </div> + </a> + } *} + </div> + </div> +} *} + diff --git a/eportfolio/templates/css/tailwind-output.css b/eportfolio/templates/css/tailwind-output.css index 636953d..b930133 100644 --- a/eportfolio/templates/css/tailwind-output.css +++ b/eportfolio/templates/css/tailwind-output.css @@ -1,5 +1,113 @@ +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + /* -! tailwindcss v3.4.9 | MIT License | https://tailwindcss.com +! tailwindcss v3.4.12 | MIT License | https://tailwindcss.com */ /* @@ -446,148 +554,792 @@ video { display: none; } -*, ::before, ::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; +.container { + width: 100%; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.prose { + color: var(--tw-prose-body); + max-width: 65ch; +} + +.prose :where(p):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.25em; + margin-bottom: 1.25em; +} + +.prose :where([class~="lead"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-lead); + font-size: 1.25em; + line-height: 1.6; + margin-top: 1.2em; + margin-bottom: 1.2em; +} + +.prose :where(a):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-links); + text-decoration: underline; + font-weight: 500; +} + +.prose :where(strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-bold); + font-weight: 600; +} + +.prose :where(a strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(blockquote strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(thead th strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: decimal; + margin-top: 1.25em; + margin-bottom: 1.25em; + padding-inline-start: 1.625em; +} + +.prose :where(ol[type="A"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: upper-alpha; +} + +.prose :where(ol[type="a"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: lower-alpha; +} + +.prose :where(ol[type="A" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: upper-alpha; +} + +.prose :where(ol[type="a" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: lower-alpha; +} + +.prose :where(ol[type="I"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: upper-roman; +} + +.prose :where(ol[type="i"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: lower-roman; +} + +.prose :where(ol[type="I" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: upper-roman; +} + +.prose :where(ol[type="i" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: lower-roman; +} + +.prose :where(ol[type="1"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: decimal; +} + +.prose :where(ul):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + list-style-type: disc; + margin-top: 1.25em; + margin-bottom: 1.25em; + padding-inline-start: 1.625em; +} + +.prose :where(ol > li):not(:where([class~="not-prose"],[class~="not-prose"] *))::marker { + font-weight: 400; + color: var(--tw-prose-counters); +} + +.prose :where(ul > li):not(:where([class~="not-prose"],[class~="not-prose"] *))::marker { + color: var(--tw-prose-bullets); +} + +.prose :where(dt):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-headings); + font-weight: 600; + margin-top: 1.25em; +} + +.prose :where(hr):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + border-color: var(--tw-prose-hr); + border-top-width: 1px; + margin-top: 3em; + margin-bottom: 3em; +} + +.prose :where(blockquote):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-weight: 500; + font-style: italic; + color: var(--tw-prose-quotes); + border-inline-start-width: 0.25rem; + border-inline-start-color: var(--tw-prose-quote-borders); + quotes: "\201C""\201D""\2018""\2019"; + margin-top: 1.6em; + margin-bottom: 1.6em; + padding-inline-start: 1em; +} + +.prose :where(blockquote p:first-of-type):not(:where([class~="not-prose"],[class~="not-prose"] *))::before { + content: open-quote; +} + +.prose :where(blockquote p:last-of-type):not(:where([class~="not-prose"],[class~="not-prose"] *))::after { + content: close-quote; +} + +.prose :where(h1):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-headings); + font-weight: 800; + font-size: 2.25em; + margin-top: 0; + margin-bottom: 0.8888889em; + line-height: 1.1111111; +} + +.prose :where(h1 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-weight: 900; + color: inherit; +} + +.prose :where(h2):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-headings); + font-weight: 700; + font-size: 1.5em; + margin-top: 2em; + margin-bottom: 1em; + line-height: 1.3333333; +} + +.prose :where(h2 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-weight: 800; + color: inherit; +} + +.prose :where(h3):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-headings); + font-weight: 600; + font-size: 1.25em; + margin-top: 1.6em; + margin-bottom: 0.6em; + line-height: 1.6; +} + +.prose :where(h3 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-weight: 700; + color: inherit; +} + +.prose :where(h4):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-headings); + font-weight: 600; + margin-top: 1.5em; + margin-bottom: 0.5em; + line-height: 1.5; +} + +.prose :where(h4 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-weight: 700; + color: inherit; +} + +.prose :where(img):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 2em; + margin-bottom: 2em; +} + +.prose :where(picture):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + display: block; + margin-top: 2em; + margin-bottom: 2em; +} + +.prose :where(video):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 2em; + margin-bottom: 2em; +} + +.prose :where(kbd):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-weight: 500; + font-family: inherit; + color: var(--tw-prose-kbd); + box-shadow: 0 0 0 1px rgb(var(--tw-prose-kbd-shadows) / 10%), 0 3px 0 rgb(var(--tw-prose-kbd-shadows) / 10%); + font-size: 0.875em; + border-radius: 0.3125rem; + padding-top: 0.1875em; + padding-inline-end: 0.375em; + padding-bottom: 0.1875em; + padding-inline-start: 0.375em; +} + +.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-code); + font-weight: 600; + font-size: 0.875em; +} + +.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::before { + content: "`"; +} + +.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::after { + content: "`"; +} + +.prose :where(a code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(h1 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(h2 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; + font-size: 0.875em; +} + +.prose :where(h3 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; + font-size: 0.9em; +} + +.prose :where(h4 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(blockquote code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(thead th code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: inherit; +} + +.prose :where(pre):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-pre-code); + background-color: var(--tw-prose-pre-bg); + overflow-x: auto; + font-weight: 400; + font-size: 0.875em; + line-height: 1.7142857; + margin-top: 1.7142857em; + margin-bottom: 1.7142857em; + border-radius: 0.375rem; + padding-top: 0.8571429em; + padding-inline-end: 1.1428571em; + padding-bottom: 0.8571429em; + padding-inline-start: 1.1428571em; +} + +.prose :where(pre code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + background-color: transparent; + border-width: 0; + border-radius: 0; + padding: 0; + font-weight: inherit; + color: inherit; + font-size: inherit; + font-family: inherit; + line-height: inherit; +} + +.prose :where(pre code):not(:where([class~="not-prose"],[class~="not-prose"] *))::before { + content: none; +} + +.prose :where(pre code):not(:where([class~="not-prose"],[class~="not-prose"] *))::after { + content: none; +} + +.prose :where(table):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + width: 100%; + table-layout: auto; + margin-top: 2em; + margin-bottom: 2em; + font-size: 0.875em; + line-height: 1.7142857; +} + +.prose :where(thead):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + border-bottom-width: 1px; + border-bottom-color: var(--tw-prose-th-borders); +} + +.prose :where(thead th):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-headings); + font-weight: 600; + vertical-align: bottom; + padding-inline-end: 0.5714286em; + padding-bottom: 0.5714286em; + padding-inline-start: 0.5714286em; +} + +.prose :where(tbody tr):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + border-bottom-width: 1px; + border-bottom-color: var(--tw-prose-td-borders); +} + +.prose :where(tbody tr:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + border-bottom-width: 0; +} + +.prose :where(tbody td):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + vertical-align: baseline; +} + +.prose :where(tfoot):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + border-top-width: 1px; + border-top-color: var(--tw-prose-th-borders); +} + +.prose :where(tfoot td):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + vertical-align: top; +} + +.prose :where(th, td):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + text-align: start; +} + +.prose :where(figure > *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + margin-bottom: 0; +} + +.prose :where(figcaption):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + color: var(--tw-prose-captions); + font-size: 0.875em; + line-height: 1.4285714; + margin-top: 0.8571429em; +} + +.prose { + --tw-prose-body: #374151; + --tw-prose-headings: #111827; + --tw-prose-lead: #4b5563; + --tw-prose-links: #111827; + --tw-prose-bold: #111827; + --tw-prose-counters: #6b7280; + --tw-prose-bullets: #d1d5db; + --tw-prose-hr: #e5e7eb; + --tw-prose-quotes: #111827; + --tw-prose-quote-borders: #e5e7eb; + --tw-prose-captions: #6b7280; + --tw-prose-kbd: #111827; + --tw-prose-kbd-shadows: 17 24 39; + --tw-prose-code: #111827; + --tw-prose-pre-code: #e5e7eb; + --tw-prose-pre-bg: #1f2937; + --tw-prose-th-borders: #d1d5db; + --tw-prose-td-borders: #e5e7eb; + --tw-prose-invert-body: #d1d5db; + --tw-prose-invert-headings: #fff; + --tw-prose-invert-lead: #9ca3af; + --tw-prose-invert-links: #fff; + --tw-prose-invert-bold: #fff; + --tw-prose-invert-counters: #9ca3af; + --tw-prose-invert-bullets: #4b5563; + --tw-prose-invert-hr: #374151; + --tw-prose-invert-quotes: #f3f4f6; + --tw-prose-invert-quote-borders: #374151; + --tw-prose-invert-captions: #9ca3af; + --tw-prose-invert-kbd: #fff; + --tw-prose-invert-kbd-shadows: 255 255 255; + --tw-prose-invert-code: #fff; + --tw-prose-invert-pre-code: #d1d5db; + --tw-prose-invert-pre-bg: rgb(0 0 0 / 50%); + --tw-prose-invert-th-borders: #4b5563; + --tw-prose-invert-td-borders: #374151; + font-size: 1rem; + line-height: 1.75; +} + +.prose :where(picture > img):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + margin-bottom: 0; +} + +.prose :where(li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +.prose :where(ol > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0.375em; +} + +.prose :where(ul > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0.375em; +} + +.prose :where(.prose > ul > li p):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.75em; + margin-bottom: 0.75em; +} + +.prose :where(.prose > ul > li > p:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.25em; +} + +.prose :where(.prose > ul > li > p:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 1.25em; +} + +.prose :where(.prose > ol > li > p:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.25em; +} + +.prose :where(.prose > ol > li > p:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 1.25em; +} + +.prose :where(ul ul, ul ol, ol ul, ol ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.75em; + margin-bottom: 0.75em; +} + +.prose :where(dl):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.25em; + margin-bottom: 1.25em; +} + +.prose :where(dd):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.5em; + padding-inline-start: 1.625em; +} + +.prose :where(hr + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; +} + +.prose :where(h2 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; +} + +.prose :where(h3 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; +} + +.prose :where(h4 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; +} + +.prose :where(thead th:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0; +} + +.prose :where(thead th:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 0; +} + +.prose :where(tbody td, tfoot td):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-top: 0.5714286em; + padding-inline-end: 0.5714286em; + padding-bottom: 0.5714286em; + padding-inline-start: 0.5714286em; +} + +.prose :where(tbody td:first-child, tfoot td:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0; +} + +.prose :where(tbody td:last-child, tfoot td:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 0; +} + +.prose :where(figure):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 2em; + margin-bottom: 2em; +} + +.prose :where(.prose > :first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; +} + +.prose :where(.prose > :last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 0; +} + +.prose-sm { + font-size: 0.875rem; + line-height: 1.7142857; +} + +.prose-sm :where(p):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.1428571em; + margin-bottom: 1.1428571em; +} + +.prose-sm :where([class~="lead"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 1.2857143em; + line-height: 1.5555556; + margin-top: 0.8888889em; + margin-bottom: 0.8888889em; +} + +.prose-sm :where(blockquote):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + margin-bottom: 1.3333333em; + padding-inline-start: 1.1111111em; +} + +.prose-sm :where(h1):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 2.1428571em; + margin-top: 0; + margin-bottom: 0.8em; + line-height: 1.2; +} + +.prose-sm :where(h2):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 1.4285714em; + margin-top: 1.6em; + margin-bottom: 0.8em; + line-height: 1.4; +} + +.prose-sm :where(h3):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 1.2857143em; + margin-top: 1.5555556em; + margin-bottom: 0.4444444em; + line-height: 1.5555556; +} + +.prose-sm :where(h4):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.4285714em; + margin-bottom: 0.5714286em; + line-height: 1.4285714; +} + +.prose-sm :where(img):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7142857em; + margin-bottom: 1.7142857em; +} + +.prose-sm :where(picture):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7142857em; + margin-bottom: 1.7142857em; +} + +.prose-sm :where(picture > img):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + margin-bottom: 0; +} + +.prose-sm :where(video):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7142857em; + margin-bottom: 1.7142857em; +} + +.prose-sm :where(kbd):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8571429em; + border-radius: 0.3125rem; + padding-top: 0.1428571em; + padding-inline-end: 0.3571429em; + padding-bottom: 0.1428571em; + padding-inline-start: 0.3571429em; +} + +.prose-sm :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8571429em; +} + +.prose-sm :where(h2 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.9em; +} + +.prose-sm :where(h3 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8888889em; +} + +.prose-sm :where(pre):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8571429em; + line-height: 1.6666667; + margin-top: 1.6666667em; + margin-bottom: 1.6666667em; + border-radius: 0.25rem; + padding-top: 0.6666667em; + padding-inline-end: 1em; + padding-bottom: 0.6666667em; + padding-inline-start: 1em; +} + +.prose-sm :where(ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.1428571em; + margin-bottom: 1.1428571em; + padding-inline-start: 1.5714286em; +} + +.prose-sm :where(ul):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.1428571em; + margin-bottom: 1.1428571em; + padding-inline-start: 1.5714286em; +} + +.prose-sm :where(li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.2857143em; + margin-bottom: 0.2857143em; +} + +.prose-sm :where(ol > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0.4285714em; +} + +.prose-sm :where(ul > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0.4285714em; +} + +.prose-sm :where(.prose-sm > ul > li p):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.5714286em; + margin-bottom: 0.5714286em; +} + +.prose-sm :where(.prose-sm > ul > li > p:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.1428571em; +} + +.prose-sm :where(.prose-sm > ul > li > p:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 1.1428571em; +} + +.prose-sm :where(.prose-sm > ol > li > p:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.1428571em; +} + +.prose-sm :where(.prose-sm > ol > li > p:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 1.1428571em; +} + +.prose-sm :where(ul ul, ul ol, ol ul, ol ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.5714286em; + margin-bottom: 0.5714286em; +} + +.prose-sm :where(dl):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.1428571em; + margin-bottom: 1.1428571em; +} + +.prose-sm :where(dt):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.1428571em; } -::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-gradient-from-position: ; - --tw-gradient-via-position: ; - --tw-gradient-to-position: ; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; - --tw-contain-size: ; - --tw-contain-layout: ; - --tw-contain-paint: ; - --tw-contain-style: ; +.prose-sm :where(dd):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.2857143em; + padding-inline-start: 1.5714286em; } -.container { - width: 100%; - margin-right: auto; - margin-left: auto; +.prose-sm :where(hr):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 2.8571429em; + margin-bottom: 2.8571429em; } -@media (min-width: 640px) { - .container { - max-width: 640px; - } +.prose-sm :where(hr + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; } -@media (min-width: 768px) { - .container { - max-width: 768px; - } +.prose-sm :where(h2 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; } -@media (min-width: 1024px) { - .container { - max-width: 1024px; - } +.prose-sm :where(h3 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; } -@media (min-width: 1280px) { - .container { - max-width: 1280px; - } +.prose-sm :where(h4 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; } -@media (min-width: 1536px) { - .container { - max-width: 1536px; - } +.prose-sm :where(table):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8571429em; + line-height: 1.5; +} + +.prose-sm :where(thead th):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 1em; + padding-bottom: 0.6666667em; + padding-inline-start: 1em; +} + +.prose-sm :where(thead th:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0; +} + +.prose-sm :where(thead th:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 0; +} + +.prose-sm :where(tbody td, tfoot td):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-top: 0.6666667em; + padding-inline-end: 1em; + padding-bottom: 0.6666667em; + padding-inline-start: 1em; +} + +.prose-sm :where(tbody td:first-child, tfoot td:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0; +} + +.prose-sm :where(tbody td:last-child, tfoot td:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 0; +} + +.prose-sm :where(figure):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7142857em; + margin-bottom: 1.7142857em; +} + +.prose-sm :where(figure > *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + margin-bottom: 0; +} + +.prose-sm :where(figcaption):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8571429em; + line-height: 1.3333333; + margin-top: 0.6666667em; +} + +.prose-sm :where(.prose-sm > :first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; +} + +.prose-sm :where(.prose-sm > :last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 0; } .absolute { @@ -639,6 +1391,10 @@ video { margin: 2rem; } +.m-auto { + margin: auto; +} + .mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; @@ -829,6 +1585,14 @@ video { place-items: center; } +.place-items-stretch { + place-items: stretch; +} + +.items-start { + align-items: flex-start; +} + .items-center { align-items: center; } @@ -933,10 +1697,18 @@ video { border-width: 1px; } +.border-2 { + border-width: 2px; +} + .border-4 { border-width: 4px; } +.border-b { + border-bottom-width: 1px; +} + .border-l { border-left-width: 1px; } @@ -961,6 +1733,11 @@ video { border-color: rgb(75 85 99 / var(--tw-border-opacity)); } +.border-red-400 { + --tw-border-opacity: 1; + border-color: rgb(248 113 113 / var(--tw-border-opacity)); +} + .bg-blue-300 { --tw-bg-opacity: 1; background-color: rgb(147 197 253 / var(--tw-bg-opacity)); @@ -985,6 +1762,11 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } +.bg-zinc-50 { + --tw-bg-opacity: 1; + background-color: rgb(250 250 250 / var(--tw-bg-opacity)); +} + .bg-gradient-radial { background-image: radial-gradient(farthest-corner at 300px 400px, var(--tw-gradient-stops)); } @@ -1049,6 +1831,11 @@ video { padding-bottom: 1rem; } +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + .text-center { text-align: center; } @@ -1096,6 +1883,11 @@ video { line-height: 1.25rem; } +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + .text-xs { font-size: 0.75rem; line-height: 1rem; @@ -1185,6 +1977,11 @@ video { box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.shadow-gray-800 { + --tw-shadow-color: #1f2937; + --tw-shadow: var(--tw-shadow-colored); +} + .blur-md { --tw-blur: blur(12px); filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); @@ -1256,6 +2053,255 @@ html { scroll-behavior: smooth; } +@media (min-width: 1024px) { + .lg\:prose-lg { + font-size: 1.125rem; + line-height: 1.7777778; + } + + .lg\:prose-lg :where(p):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + margin-bottom: 1.3333333em; + } + + .lg\:prose-lg :where([class~="lead"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 1.2222222em; + line-height: 1.4545455; + margin-top: 1.0909091em; + margin-bottom: 1.0909091em; + } + + .lg\:prose-lg :where(blockquote):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.6666667em; + margin-bottom: 1.6666667em; + padding-inline-start: 1em; + } + + .lg\:prose-lg :where(h1):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 2.6666667em; + margin-top: 0; + margin-bottom: 0.8333333em; + line-height: 1; + } + + .lg\:prose-lg :where(h2):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 1.6666667em; + margin-top: 1.8666667em; + margin-bottom: 1.0666667em; + line-height: 1.3333333; + } + + .lg\:prose-lg :where(h3):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 1.3333333em; + margin-top: 1.6666667em; + margin-bottom: 0.6666667em; + line-height: 1.5; + } + + .lg\:prose-lg :where(h4):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7777778em; + margin-bottom: 0.4444444em; + line-height: 1.5555556; + } + + .lg\:prose-lg :where(img):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7777778em; + margin-bottom: 1.7777778em; + } + + .lg\:prose-lg :where(picture):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7777778em; + margin-bottom: 1.7777778em; + } + + .lg\:prose-lg :where(picture > img):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + margin-bottom: 0; + } + + .lg\:prose-lg :where(video):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7777778em; + margin-bottom: 1.7777778em; + } + + .lg\:prose-lg :where(kbd):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8888889em; + border-radius: 0.3125rem; + padding-top: 0.2222222em; + padding-inline-end: 0.4444444em; + padding-bottom: 0.2222222em; + padding-inline-start: 0.4444444em; + } + + .lg\:prose-lg :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8888889em; + } + + .lg\:prose-lg :where(h2 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8666667em; + } + + .lg\:prose-lg :where(h3 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.875em; + } + + .lg\:prose-lg :where(pre):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8888889em; + line-height: 1.75; + margin-top: 2em; + margin-bottom: 2em; + border-radius: 0.375rem; + padding-top: 1em; + padding-inline-end: 1.5em; + padding-bottom: 1em; + padding-inline-start: 1.5em; + } + + .lg\:prose-lg :where(ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + margin-bottom: 1.3333333em; + padding-inline-start: 1.5555556em; + } + + .lg\:prose-lg :where(ul):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + margin-bottom: 1.3333333em; + padding-inline-start: 1.5555556em; + } + + .lg\:prose-lg :where(li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.6666667em; + margin-bottom: 0.6666667em; + } + + .lg\:prose-lg :where(ol > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0.4444444em; + } + + .lg\:prose-lg :where(ul > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0.4444444em; + } + + .lg\:prose-lg :where(.lg\:prose-lg > ul > li p):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.8888889em; + margin-bottom: 0.8888889em; + } + + .lg\:prose-lg :where(.lg\:prose-lg > ul > li > p:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + } + + .lg\:prose-lg :where(.lg\:prose-lg > ul > li > p:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 1.3333333em; + } + + .lg\:prose-lg :where(.lg\:prose-lg > ol > li > p:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + } + + .lg\:prose-lg :where(.lg\:prose-lg > ol > li > p:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 1.3333333em; + } + + .lg\:prose-lg :where(ul ul, ul ol, ol ul, ol ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.8888889em; + margin-bottom: 0.8888889em; + } + + .lg\:prose-lg :where(dl):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + margin-bottom: 1.3333333em; + } + + .lg\:prose-lg :where(dt):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.3333333em; + } + + .lg\:prose-lg :where(dd):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0.6666667em; + padding-inline-start: 1.5555556em; + } + + .lg\:prose-lg :where(hr):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 3.1111111em; + margin-bottom: 3.1111111em; + } + + .lg\:prose-lg :where(hr + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + } + + .lg\:prose-lg :where(h2 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + } + + .lg\:prose-lg :where(h3 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + } + + .lg\:prose-lg :where(h4 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + } + + .lg\:prose-lg :where(table):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8888889em; + line-height: 1.5; + } + + .lg\:prose-lg :where(thead th):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 0.75em; + padding-bottom: 0.75em; + padding-inline-start: 0.75em; + } + + .lg\:prose-lg :where(thead th:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0; + } + + .lg\:prose-lg :where(thead th:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 0; + } + + .lg\:prose-lg :where(tbody td, tfoot td):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-top: 0.75em; + padding-inline-end: 0.75em; + padding-bottom: 0.75em; + padding-inline-start: 0.75em; + } + + .lg\:prose-lg :where(tbody td:first-child, tfoot td:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-start: 0; + } + + .lg\:prose-lg :where(tbody td:last-child, tfoot td:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + padding-inline-end: 0; + } + + .lg\:prose-lg :where(figure):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 1.7777778em; + margin-bottom: 1.7777778em; + } + + .lg\:prose-lg :where(figure > *):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + margin-bottom: 0; + } + + .lg\:prose-lg :where(figcaption):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + font-size: 0.8888889em; + line-height: 1.5; + margin-top: 1em; + } + + .lg\:prose-lg :where(.lg\:prose-lg > :first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-top: 0; + } + + .lg\:prose-lg :where(.lg\:prose-lg > :last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) { + margin-bottom: 0; + } +} + .hover\:border-transparent:hover { border-color: transparent; } @@ -1289,11 +2335,28 @@ html { z-index: 10; } +.focus\:rounded-lg:focus { + border-radius: 0.5rem; +} + +.focus\:border-4:focus { + border-width: 4px; +} + +.focus\:border-2:focus { + border-width: 2px; +} + .focus\:text-blue-700:focus { --tw-text-opacity: 1; color: rgb(29 78 216 / var(--tw-text-opacity)); } +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + .focus\:outline-transparent:focus { outline-color: transparent; } @@ -1304,11 +2367,43 @@ html { box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } +.focus\:ring:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-2:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + .focus\:ring-gray-200:focus { --tw-ring-opacity: 1; --tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity)); } +.focus\:ring-red-800:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(153 27 27 / var(--tw-ring-opacity)); +} + +.focus\:ring-white:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); +} + +.focus\:ring-off-white:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(248 248 248 / var(--tw-ring-opacity)); +} + +.focus\:ring-black:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity)); +} + @media not all and (min-width: 1024px) { .max-lg\:self-start { align-self: flex-start; @@ -1427,6 +2522,10 @@ html { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .lg\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .lg\:flex-row { flex-direction: row; } @@ -1453,6 +2552,11 @@ html { padding: 0px; } + .lg\:px-20 { + padding-left: 5rem; + padding-right: 5rem; + } + .lg\:text-3xl { font-size: 1.875rem; line-height: 2.25rem; diff --git a/eportfolio/templates/markdown/courses/CS4505.md b/eportfolio/templates/markdown/courses/CS4505.md new file mode 100644 index 0000000..a13acb6 --- /dev/null +++ b/eportfolio/templates/markdown/courses/CS4505.md @@ -0,0 +1,3 @@ +# Software Architecture +🔨 Under development + diff --git a/eportfolio/templates/markdown/courses/CS4510.md b/eportfolio/templates/markdown/courses/CS4510.md new file mode 100644 index 0000000..2ee621f --- /dev/null +++ b/eportfolio/templates/markdown/courses/CS4510.md @@ -0,0 +1,3 @@ +# Formal Reasoning about Software +🔨 Under development + diff --git a/eportfolio/templates/markdown/courses/CS4515.md b/eportfolio/templates/markdown/courses/CS4515.md new file mode 100644 index 0000000..67fcc4e --- /dev/null +++ b/eportfolio/templates/markdown/courses/CS4515.md @@ -0,0 +1,3 @@ +# 3D Computer Graphics and Animation +🔨 Under development + diff --git a/eportfolio/templates/markdown/courses/DSAIT4005.md b/eportfolio/templates/markdown/courses/DSAIT4005.md new file mode 100644 index 0000000..1ff869b --- /dev/null +++ b/eportfolio/templates/markdown/courses/DSAIT4005.md @@ -0,0 +1,3 @@ +# Machine and Deep Learning +🔨 Under development +