diff --git a/Source/docfx.json b/Source/docfx.json index ef0b458..f642057 100644 --- a/Source/docfx.json +++ b/Source/docfx.json @@ -143,6 +143,11 @@ ], "build": { "content": [ + { + "files": [ + "index.md" + ] + }, { "files": [ "**/*.{md,yml}" diff --git a/Source/index.md b/Source/index.md index 83227ce..cce1037 100644 --- a/Source/index.md +++ b/Source/index.md @@ -1,93 +1,787 @@ +--- +title: Home +_disableToc: true +_disableAffix: true +_disableBreadcrumb: true +_disableContribution: true +--- -
- -
+.cratis-hero-logo { + width: 270px; max-width: 72%; + filter: brightness(0) invert(1); + margin-bottom: 30px; + position: relative; z-index: 1; + box-shadow: none; border-radius: 0; + animation: logoFloat 7s ease-in-out infinite; +} +@keyframes logoFloat { + 0%,100% { transform: translateY(0); filter: brightness(0) invert(1) drop-shadow(0 0 0px transparent); } + 50% { transform: translateY(-7px); filter: brightness(0) invert(1) drop-shadow(0 0 22px rgba(99,102,241,0.45)); } +} + +.cratis-hero h1 { + color: #ffffff !important; + font-size: 2.65rem; font-weight: 800; + margin-bottom: 18px; + position: relative; z-index: 1; + border-bottom: none !important; + letter-spacing: -0.025em; + text-shadow: 0 0 70px rgba(99,102,241,0.55); +} + +.cratis-hero-tagline { + color: rgba(255,255,255,0.72); + font-size: 1.12rem; line-height: 1.8; + max-width: 560px; + margin: 0 auto 44px; + position: relative; z-index: 1; +} + +.cratis-hero-ctas { + display: flex; gap: 14px; + justify-content: center; flex-wrap: wrap; + position: relative; z-index: 1; +} + +.cratis-btn { + display: inline-flex; align-items: center; gap: 8px; + padding: 12px 28px; border-radius: 40px; + font-weight: 700; font-size: 0.95rem; + text-decoration: none !important; + cursor: pointer; border: none; letter-spacing: 0.01em; + transition: transform 0.22s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.22s ease; +} +.cratis-btn-primary { + background: linear-gradient(135deg, #6366f1, #8b5cf6); + color: #ffffff !important; + box-shadow: 0 4px 22px rgba(99,102,241,0.52); +} +.cratis-btn-primary:hover { + transform: translateY(-4px) scale(1.05); + box-shadow: 0 12px 36px rgba(99,102,241,0.78); + color: #ffffff !important; +} +.cratis-btn-ghost { + background: rgba(255,255,255,0.07); + color: #ffffff !important; + border: 1px solid rgba(255,255,255,0.2); + backdrop-filter: blur(8px); +} +.cratis-btn-ghost:hover { + background: rgba(255,255,255,0.15); + transform: translateY(-4px) scale(1.05); + border-color: rgba(255,255,255,0.4); + color: #ffffff !important; +} + +/* ---- GETTING STARTED ------------------------------------ */ +.cratis-getting-started { + padding: 56px 36px 60px; + background: var(--bg-2); + border-top: 1px solid var(--border); +} +.cratis-section-header { margin-bottom: 30px; } +.cratis-section-header h2 { + color: #ffffff !important; + font-size: 1.85rem; font-weight: 800; + margin-bottom: 6px; + border-bottom: none !important; + letter-spacing: -0.015em; +} +.cratis-section-header p { color: var(--muted); font-size: 1rem; margin: 0; } + +.cratis-steps { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 20px; +} +.cratis-step-card { + background: var(--bg-3); + border: 1px solid var(--border); + border-radius: 14px; padding: 24px; + position: relative; overflow: hidden; + transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease; +} +.cratis-step-card::before { + content: ''; + position: absolute; top: 0; left: 0; right: 0; height: 2px; + background: linear-gradient(90deg, #6366f1, #8b5cf6); + opacity: 0.5; transition: opacity .25s ease; +} +.cratis-step-card:hover { + border-color: rgba(99,102,241,0.45); + transform: translateY(-3px); + box-shadow: 0 10px 36px rgba(0,0,0,0.38), 0 0 0 1px rgba(99,102,241,0.15); +} +.cratis-step-card:hover::before { opacity: 1; } + +.step-badge { + display: inline-flex; align-items: center; justify-content: center; + width: 32px; height: 32px; + background: linear-gradient(135deg, #6366f1, #8b5cf6); + color: #fff; border-radius: 50%; + font-weight: 800; font-size: 0.9rem; + margin-bottom: 12px; + box-shadow: 0 4px 14px rgba(99,102,241,0.48); +} +.cratis-step-card h3 { color: rgba(255,255,255,0.95) !important; font-size: 1.05rem; font-weight: 700; margin-bottom: 6px; } +.cratis-step-card p { color: var(--muted); font-size: 0.875rem; margin-bottom: 14px; line-height: 1.65; } + +.cratis-code { + background: #05070e; + border: 1px solid rgba(255,255,255,0.07); + border-radius: 8px; + padding: 10px 46px 10px 14px; + font-family: 'Consolas','Monaco','Courier New',monospace; + font-size: 0.82rem; overflow-x: auto; + margin-bottom: 8px; position: relative; + color: #e2e8f0; box-shadow: none; +} +.cratis-code .cmd-dollar { color: #818cf8; user-select: none; margin-right: 6px; font-weight: 700; } + +.cratis-copy-btn { + position: absolute; top: 7px; right: 7px; + background: rgba(99,102,241,0.12); + border: 1px solid rgba(99,102,241,0.25); + color: rgba(255,255,255,0.5); + border-radius: 4px; padding: 2px 8px; + font-size: 0.7rem; cursor: pointer; + transition: background .15s, color .15s, border-color .15s; + font-family: inherit; +} +.cratis-copy-btn:hover { background: rgba(99,102,241,0.38); color: #fff; border-color: rgba(99,102,241,0.6); } + +/* ---- SCROLL HINT ---------------------------------------- */ +.cratis-scroll-hint { + text-align: center; padding: 22px 0; + color: rgba(255,255,255,0.3); + font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700; + display: flex; flex-direction: column; align-items: center; gap: 5px; + background: var(--bg-2); border-top: 1px solid var(--border); +} +.cratis-scroll-hint-arrow { + font-size: 1.25rem; + animation: bounceDown 2s ease-in-out infinite; + filter: drop-shadow(0 0 10px rgba(99,102,241,1)); + color: rgba(99,102,241,0.85); +} +@keyframes bounceDown { + 0%,100% { transform: translateY(0); opacity: 0.6; } + 50% { transform: translateY(9px); opacity: 1; } +} + +/* ---- ARCHITECTURE SECTION ------------------------------- */ +.cratis-arch-section { + padding: 56px 36px 88px; + background: var(--bg); + border-top: 1px solid var(--border); +} +.cratis-stack { max-width: 720px; margin: 0 auto; } + +/* ========================================================= + BOX WRAPPER — provides 3D depth slice behind each box + ========================================================= */ +.cratis-box-wrapper { position: relative; margin-bottom: 4px; } + +/* The physical depth layer offset bottom-right */ +.cratis-box-wrapper::after { + content: ''; + position: absolute; + bottom: -9px; right: -9px; + top: 9px; left: 9px; + border-radius: 14px; + background: var(--box-depth); + z-index: 0; opacity: 0.55; + transition: transform 0.3s ease, opacity 0.3s ease; + pointer-events: none; +} +.cratis-box-wrapper:hover::after { transform: translate(5px,5px); opacity: 0.75; } -## Chronicle +/* ========================================================= + BOX — the clickable layer card + ========================================================= */ +.cratis-box { + position: relative; z-index: 1; + border-radius: 14px; overflow: hidden; + cursor: pointer; user-select: none; + border-left: 8px solid var(--box-accent); + transition: + transform 0.28s cubic-bezier(0.34,1.56,0.64,1), + box-shadow 0.28s ease; +} +.cratis-box:hover { + transform: translate(-7px,-10px); + box-shadow: + 0 24px 60px var(--box-glow), + 0 0 0 1px rgba(255,255,255,0.06) inset; +} + +/* Shake/crack animation on open */ +@keyframes boxCrack { + 0% { transform: translateX(0) rotate(0deg) scale(1); } + 12% { transform: translateX(-9px) rotate(-2deg) scale(1.028); } + 28% { transform: translateX( 9px) rotate( 2deg) scale(1.034); } + 44% { transform: translateX(-6px) rotate(-1.3deg) scale(1.016); } + 60% { transform: translateX( 6px) rotate( 1deg) scale(1.022); } + 76% { transform: translateX(-3px) rotate(-0.5deg); } + 100% { transform: translateX(0) rotate(0deg) scale(1); } +} +.cratis-box.is-cracking { animation: boxCrack 0.3s ease; } + +/* Header */ +.cratis-box-header { + padding: 18px 22px; + display: flex; align-items: center; justify-content: space-between; + position: relative; overflow: hidden; +} +/* Diagonal stripe texture */ +.cratis-box-header::before { + content: ''; position: absolute; inset: 0; + background: repeating-linear-gradient( + -55deg, transparent 0, transparent 16px, + rgba(255,255,255,0.028) 16px, rgba(255,255,255,0.028) 18px + ); + pointer-events: none; +} +/* Shimmer scan on hover */ +.cratis-box-header::after { + content: ''; position: absolute; + top: 0; left: -145%; width: 75%; height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.16), transparent); + pointer-events: none; +} +.cratis-box:hover .cratis-box-header::after { animation: shimmer 0.7s ease forwards; } +@keyframes shimmer { 0% { left: -145%; } 100% { left: 165%; } } + +.cratis-box-header-left { display: flex; align-items: center; gap: 14px; position: relative; z-index: 1; } + +.cratis-box-icon { + font-size: 2.2rem; line-height: 1; + box-shadow: none; border-radius: 0; + filter: drop-shadow(0 0 5px rgba(255,255,255,0.2)); + transition: transform 0.32s cubic-bezier(0.34,1.56,0.64,1), filter 0.32s ease; +} +.cratis-box:hover .cratis-box-icon { + transform: scale(1.22) rotate(-12deg); + filter: drop-shadow(0 0 18px rgba(255,255,255,0.6)); +} + +.cratis-box-title { + color: #fff; font-size: 1.25rem; font-weight: 800; margin: 0; + letter-spacing: -0.015em; + text-shadow: 0 1px 10px rgba(0,0,0,0.35); +} +.cratis-box-desc { color: rgba(255,255,255,0.65); font-size: 0.76rem; margin: 3px 0 0; } + +.cratis-box-toggle { + color: rgba(255,255,255,0.8); font-size: 1rem; line-height: 1; + width: 28px; height: 28px; + display: flex; align-items: center; justify-content: center; + background: rgba(255,255,255,0.12); border-radius: 50%; + flex-shrink: 0; position: relative; z-index: 1; + transition: transform 0.42s cubic-bezier(0.34,1.56,0.64,1), background 0.2s ease; +} +.cratis-box.is-open .cratis-box-toggle { transform: rotate(180deg); background: rgba(255,255,255,0.22); } + +.coming-soon-pill { + display: inline-block; + background: rgba(255,255,255,0.14); color: rgba(255,255,255,0.88); + font-size: 0.6rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; + padding: 2px 8px; border-radius: 10px; + border: 1px solid rgba(255,255,255,0.22); + margin-left: 10px; vertical-align: middle; + animation: pillPulse 3s ease-in-out infinite; +} +@keyframes pillPulse { 0%,100% { opacity: 0.9; } 50% { opacity: 0.55; } } + +/* Box body */ +.cratis-box-body { + max-height: 0; overflow: hidden; + transition: max-height 0.52s cubic-bezier(0.4,0,0.2,1); + background: rgba(0,0,0,0.42); + border-top: 1px solid rgba(255,255,255,0.05); +} +.cratis-box.is-open .cratis-box-body { max-height: 540px; } + +/* ========================================================= + FEATURE CARDS — physically drop in on open + ========================================================= */ +.cratis-cards-grid { + padding: 18px 18px 6px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(145px, 1fr)); + gap: 10px; +} -Cratis Chronicle is an Event Sourcing database built with ease of use, productivity, compliance and maintainability in mind. -It provides the core server, referred to as the **Kernel** with a .NET client SDK to access it and tooling built into it. +@keyframes cardFall { + 0% { + opacity: 0; + transform: translateY(-110px) rotate(var(--c-rot, 0deg)) scale(0.32); + filter: blur(6px); + } + 52% { opacity: 1; filter: blur(0); } + 66% { transform: translateY(11px) rotate(calc(var(--c-rot, 0deg) * 0.08)) scale(1.08); } + 80% { transform: translateY(-5px) scale(0.97); } + 91% { transform: translateY(3px) scale(1.02); } + 100% { + opacity: 1; + transform: translateY(0) rotate(0deg) scale(1); + filter: blur(0); + } +} + +.cratis-feature-card { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.08); + border-top: 2px solid var(--box-color); + border-radius: 10px; + padding: 11px 12px 10px; + color: rgba(255,255,255,0.84); + font-size: 0.8rem; font-weight: 500; line-height: 1.45; + opacity: 0; + transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease; +} +.cratis-box.is-open .cratis-feature-card { + animation: cardFall 0.56s cubic-bezier(0.34,1.56,0.64,1) forwards; +} + +/* Per-card rotation + staggered delay */ +.cratis-box.is-open .cratis-feature-card:nth-child(1) { --c-rot: -16deg; animation-delay: 0.02s; } +.cratis-box.is-open .cratis-feature-card:nth-child(2) { --c-rot: 13deg; animation-delay: 0.07s; } +.cratis-box.is-open .cratis-feature-card:nth-child(3) { --c-rot: -9deg; animation-delay: 0.12s; } +.cratis-box.is-open .cratis-feature-card:nth-child(4) { --c-rot: 15deg; animation-delay: 0.17s; } +.cratis-box.is-open .cratis-feature-card:nth-child(5) { --c-rot: -12deg; animation-delay: 0.22s; } +.cratis-box.is-open .cratis-feature-card:nth-child(6) { --c-rot: 9deg; animation-delay: 0.27s; } +.cratis-box.is-open .cratis-feature-card:nth-child(7) { --c-rot: -14deg; animation-delay: 0.32s; } +.cratis-box.is-open .cratis-feature-card:nth-child(8) { --c-rot: 11deg; animation-delay: 0.37s; } -[Get started](docs/Chronicle/). +.cratis-feature-card:hover { + transform: translateY(-4px) scale(1.07); + background: rgba(255,255,255,0.11); + box-shadow: 0 8px 24px rgba(0,0,0,0.55), 0 0 16px var(--box-glow); +} +.cf-icon { font-size: 1rem; display: block; margin-bottom: 5px; } +.cf-text { display: block; } + +/* Box footer */ +.cratis-box-footer { padding: 6px 18px 18px; } +.cratis-box-link { + display: inline-flex; align-items: center; gap: 7px; + font-size: 0.82rem; font-weight: 700; + text-decoration: none !important; + padding: 7px 18px; border-radius: 20px; + color: #ffffff !important; + background: var(--box-link-bg); + border: 1px solid rgba(255,255,255,0.14); + letter-spacing: 0.01em; + transition: transform 0.22s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.22s ease, background 0.22s ease; +} +.cratis-box-link:hover { + transform: translateX(7px) scale(1.05); + box-shadow: 0 4px 20px var(--box-glow); + background: var(--box-link-hover); + border-color: rgba(255,255,255,0.3); + color: #ffffff !important; +} + +/* ---- Connector arrows ----------------------------------- */ +.cratis-connector { + display: flex; flex-direction: column; align-items: center; + padding: 7px 0 11px; position: relative; +} +.cratis-connector::before { + content: ''; position: absolute; bottom: 13px; + width: 26px; height: 26px; border-radius: 50%; + background: rgba(99,102,241,0.1); + animation: connPulse 2.2s ease-in-out infinite; +} +@keyframes connPulse { + 0%,100% { transform: scale(0.65); opacity: 0.9; } + 50% { transform: scale(1.7); opacity: 0.1; } +} +.cratis-connector-line { + width: 2px; height: 18px; + background: linear-gradient(to bottom, rgba(99,102,241,0.7), rgba(139,92,246,0.35)); + margin-bottom: 1px; + animation: lineFlow 2.2s ease-in-out infinite; +} +@keyframes lineFlow { 0%,100% { opacity: 0.35; } 50% { opacity: 1; } } +.cratis-connector-arrow { + font-size: 1.1rem; color: rgba(139,92,246,0.9); line-height: 1; + filter: drop-shadow(0 0 9px rgba(99,102,241,1)); + animation: arrowBounce 2.2s ease-in-out infinite; + position: relative; z-index: 1; +} +@keyframes arrowBounce { 0%,100% { transform: translateY(0); } 50% { transform: translateY(6px); } } + -## Arc +
-Cratis Arc represents an opinionated approach to building consistent applications based on the concepts behind CQRS. -It offers extensions for different frameworks and is built on top of ASP.NET Core. One of the traits the application model has is the -bridging between the backend and the frontend. The application model provides a tool, called **ProxyGenerator** that generates TypeScript -code for recognized artifacts matching the criteria of what is considered a **commmand** or a **query**. + +
+ +

Build better software, faster.

+

Cratis is a suite of open-source libraries and tools for building robust, event-driven .NET applications — with productivity, compliance, and maintainability at its core.

+ +
-[Get started](docs/Arc/). + +
+
+

🛠️ Get started in two steps

+

Install the .NET templates and spin up your first Cratis application in minutes.

+
+
+
+
1
+

Install the Cratis templates

+

Add the official Cratis project templates to your .NET CLI. You only need to do this once.

+
+ $dotnet new install Cratis.Templates + +
+
+
+
2
+

Create your application

+

Scaffold a new Cratis application complete with Chronicle, Arc, and a React frontend — all wired up and ready to go.

+
+ $dotnet new cratis -n MyApp + +
+
+ $cd MyApp && dotnet run + +
+
+
+
-## Fundamentals + +
+ Explore the Cratis stack + +
-The Cratis fundamentals holds generic reusable helpers, utilities and tools that aims at solving common problems and help developers be more productive. -Fundamentals offers functionality for .NET and JavaScript environments. It is not a goal to have parity, as the different environments offer different -building blocks. + +
+
+

🏗️ The Cratis stack

+

Click any layer — watch it crack open and reveal what’s inside.

+
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+
-You should look at it as a convenience layer on top of the existing base environment you're running in. +
-[Get started](docs/Fundamentals/). + diff --git a/Source/package.json b/Source/package.json index 295cce1..21723fa 100644 --- a/Source/package.json +++ b/Source/package.json @@ -7,8 +7,8 @@ "type": "module", "scripts": { "restore": "dotnet restore && dotnet tool restore", - "watch": "rm -rf ./_site && rm -rf ./obj && dotnet clean && concurrently 'yarn serve' 'npm-watch build'", - "watch:articles": "rm -rf ./_site && concurrently 'yarn serve' 'npm-watch build':articles", + "watch": "dotnet docfx docfx.json --serve --watch", + "watch:articles": "dotnet docfx docfx.json --serve --watch", "build:ts": "./build-tsdocs.sh", "build:storybooks": "NODE_OPTIONS=\"--loader ts-node/esm\" node build-storybooks.ts", "preprocess:storybooks": "NODE_OPTIONS=\"--loader ts-node/esm\" node preprocess-storybooks.ts", diff --git a/Source/templates/material/public/main.css b/Source/templates/material/public/main.css index a5ca6f6..4549e3c 100644 --- a/Source/templates/material/public/main.css +++ b/Source/templates/material/public/main.css @@ -1,202 +1,233 @@ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100;400;700&display=swap'); -:root { - --bs-font-sans-serif: 'Roboto'; - --bs-border-radius: 10px; - - --border-radius-button: 40px; - --card-box-shadow: 0 1px 2px 0 #3d41440f, 0 1px 3px 1px #3d414429; - - --material-yellow-light: #e6dfbf; - --material-yellow-dark: #5a5338; +/* ============================================================ + Cratis - Single dark theme matching the landing page + Colors: bg #090b16 / #0d1120 / #131828 accent #6366f1 / #8b5cf6 + ============================================================ */ - --material-blue-light: #c4d9f1; - --material-blue-dark: #383e5a; - - --material-red-light: #f1c4c4; - --material-red-dark: #5a3838; - - --material-warning-header: #f57f171a; - --material-warning-background: #f6e8bd; - --material-warning-background-dark: #57502c; - - --material-info-header: #1976d21a; - --material-info-background: #e3f2fd; - --material-info-background-dark: #2c4557; - - --material-danger-header: #d32f2f1a; - --material-danger-background: #ffebee; - --material-danger-background-dark: #572c2c; -} +:root, +[data-bs-theme="dark"], +[data-bs-theme="light"] { + color-scheme: dark; -/* HEADINGS */ + --bs-font-sans-serif: 'Roboto', 'Segoe UI', sans-serif; + --bs-border-radius: 10px; -h1 { - font-weight: 600; - font-size: 32px; -} + --bs-body-bg: #090b16; + --bs-body-bg-rgb: 9, 11, 22; + --bs-body-color: rgba(255,255,255,0.88); + --bs-body-color-rgb: 226, 226, 226; + --bs-emphasis-color: #ffffff; + --bs-secondary-color: rgba(255,255,255,0.48); + --bs-secondary-bg: #131828; + --bs-secondary-bg-rgb: 19, 24, 40; + --bs-tertiary-bg: #0d1120; + --bs-tertiary-bg-rgb: 13, 17, 32; + --bs-tertiary-color: rgba(255,255,255,0.35); + + --bs-border-color: rgba(255,255,255,0.07); + --bs-border-color-translucent: rgba(255,255,255,0.07); + + --bs-primary: #6366f1; + --bs-primary-rgb: 99, 102, 241; + --bs-primary-text-emphasis: #a5b4fc; + --bs-primary-bg-subtle: #1e1b4b; + --bs-primary-border-subtle: #4338ca; + + --bs-link-color: #818cf8; + --bs-link-color-rgb: 129, 140, 248; + --bs-link-hover-color: #a5b4fc; + --bs-heading-color: #ffffff; + --bs-code-color: #a78bfa; -h2 { - font-weight: 600; - font-size: 24px; - line-height: 1.8; -} + --border-radius-button: 40px; + --card-box-shadow: 0 2px 8px rgba(0,0,0,0.55), 0 1px 3px rgba(0,0,0,0.4); -h3 { - font-weight: 600; - font-size: 20px; - line-height: 1.8; + --material-yellow-light: #e6dfbf; + --material-yellow-dark: #5a5338; + --material-blue-light: #c4d9f1; + --material-blue-dark: #383e5a; + --material-red-light: #f1c4c4; + --material-red-dark: #5a3838; + + --material-warning-header: rgba(245,127,23,0.22); + --material-warning-background: #3a3014; + --material-warning-background-dark: #3a3014; + --material-info-header: rgba(25,118,210,0.22); + --material-info-background: #0f2233; + --material-info-background-dark: #0f2233; + --material-danger-header: rgba(211,47,47,0.22); + --material-danger-background: #2c1010; + --material-danger-background-dark: #2c1010; +} + +/* ---- Always hide the dark/light mode toggle button ---- */ +button[onclick*="toggleTheme"], +.theme-switch, +.btn-theme, +[data-bs-toggle*="theme"], +[title*="dark mode"], +[title*="light mode"], +[aria-label*="dark mode"], +[aria-label*="light mode"], +[aria-label*="Switch to"] { + display: none !important; } -h5 { - font-size: 14px; - padding: 10px 0px; -} +/* ============================================================ + HEADINGS + ============================================================ */ +h1 { font-weight: 700; font-size: 32px; color: #ffffff; } +h2 { font-weight: 600; font-size: 24px; line-height: 1.8; color: rgba(255,255,255,0.92); } +h3 { font-weight: 600; font-size: 20px; line-height: 1.8; color: rgba(255,255,255,0.90); } +h5 { font-size: 14px; padding: 10px 0; color: rgba(255,255,255,0.80); } article h2, article h3, -article h4 { - margin-top: 15px; - margin-bottom: 15px; -} +article h4 { margin-top: 15px; margin-bottom: 15px; } -article h4 { - padding-bottom: 8px; - border-bottom: 2px solid #ddd; -} +article h2, +article h3 { border-bottom: 1px solid rgba(255,255,255,0.07); padding-bottom: 6px; } -/** IMAGES **/ +article h4 { padding-bottom: 8px; border-bottom: 2px solid rgba(255,255,255,0.1); } + +/* ============================================================ + IMAGES + ============================================================ */ img { border-radius: var(--bs-border-radius); box-shadow: var(--card-box-shadow); } -/** NAVBAR **/ -.navbar-brand > img { - box-shadow: none; - color: var(--bs-nav-link-color); -} - -[data-bs-theme='light'] nav.navbar { - background-color: var(--bs-primary-bg-subtle); -} - -[data-bs-theme='dark'] nav.navbar { - background-color: var(--bs-tertiary-bg); +/* ============================================================ + NAVBAR + ============================================================ */ +nav.navbar { + background: #0d1120 !important; + border-bottom: 1px solid rgba(255,255,255,0.07) !important; + backdrop-filter: blur(12px); } - +.navbar-brand > img { box-shadow: none; } .navbar-nav > li > a { border-radius: var(--border-radius-button); transition: 200ms; + color: rgba(255,255,255,0.72) !important; } - .navbar-nav a.nav-link:focus, .navbar-nav a.nav-link:hover { - background-color: var(--bs-primary-border-subtle); + background-color: rgba(99,102,241,0.15); + color: #ffffff !important; } - .navbar-nav .nav-link.active, -.navbar-nav .nav-link.show { - color: var(--bs-link-hover-color); -} - -/** SEARCH AND FILTER **/ +.navbar-nav .nav-link.show { color: #818cf8 !important; } + +/* ============================================================ + SIDEBAR / TOC + ============================================================ */ +.toc .nav > li > a { color: rgba(255,255,255,0.65); border-radius: 6px; } +.toc .nav > li.active > a, +.toc .nav > li > a:hover { color: #818cf8; background: rgba(99,102,241,0.1); } + +/* ============================================================ + SEARCH + ============================================================ */ input.form-control { border-radius: var(--border-radius-button); -} - -form.filter { - margin: 0.3rem; -} - -/** ALERTS **/ -.alert { - padding: 0; - border: none; - box-shadow: var(--card-box-shadow); -} - -.alert > p { - padding: 0.2rem 0.7rem 0.7rem 1rem; -} - -.alert > ul { - margin-bottom: 0; - padding: 5px 40px; -} - + background: rgba(255,255,255,0.05); + border-color: rgba(255,255,255,0.12); + color: rgba(255,255,255,0.88); +} +input.form-control:focus { + background: rgba(255,255,255,0.08); + border-color: #6366f1; + box-shadow: 0 0 0 3px rgba(99,102,241,0.25); +} +form.filter { margin: 0.3rem; } + +/* ============================================================ + TABLES + ============================================================ */ +table { border-color: rgba(255,255,255,0.07) !important; } +table th { + background: rgba(99,102,241,0.12); + color: rgba(255,255,255,0.92); + border-color: rgba(255,255,255,0.07) !important; +} +table td { + border-color: rgba(255,255,255,0.07) !important; + color: rgba(255,255,255,0.80); +} +table tbody tr:hover td { background: rgba(99,102,241,0.06); } + +/* ============================================================ + ALERTS + ============================================================ */ +.alert { padding: 0; border: none; box-shadow: var(--card-box-shadow); } +.alert > p { padding: 0.2rem 0.7rem 0.7rem 1rem; } +.alert > ul { margin-bottom: 0; padding: 5px 40px; } .alert > h5 { padding: 0.5rem 0.7rem 0.7rem 1rem; border-radius: var(--bs-border-radius) var(--bs-border-radius) 0 0; font-weight: bold; text-transform: capitalize; } +.alert-info { color: var(--material-blue-light); background-color: var(--material-info-background); } +.alert-info > h5 { background-color: var(--material-info-header); } +.alert-warning { color: var(--material-yellow-light); background-color: var(--material-warning-background); } +.alert-warning > h5 { background-color: var(--material-warning-header); } +.alert-danger { color: var(--material-red-light); background-color: var(--material-danger-background); } +.alert-danger > h5 { background-color: var(--material-danger-header); } -.alert-info { - color: var(--material-blue-dark); - background-color: var(--material-info-background); -} - -[data-bs-theme='dark'] .alert-info { - color: var(--material-blue-light); - background-color: var(--material-info-background-dark); -} - -.alert-info > h5 { - background-color: var(--material-info-header); -} - -.alert-warning { - color: var(--material-yellow-dark); - background-color: var(--material-warning-background); -} - -[data-bs-theme='dark'] .alert-warning { - color: var(--material-yellow-light); - background-color: var(--material-warning-background-dark); -} - -.alert-warning > h5 { - background-color: var(--material-warning-header); -} - -.alert-danger { - color: var(--material-red-dark); - background-color: var(--material-danger-background); -} - -[data-bs-theme='dark'] .alert-danger { - color: var(--material-red-light); - background-color: var(--material-danger-background-dark); -} - -.alert-danger > h5 { - background-color: var(--material-danger-header); -} - -/* CODE HIGHLIGHT */ +/* ============================================================ + CODE BLOCKS + ============================================================ */ code { - border-radius: var(--bs-border-radius); - margin: 4px 2px; - box-shadow: var(--card-box-shadow); -} - -/* STORYBOOK INTEGRATION */ - -/* When a storybook page is active, break out of container constraints to fill right side */ + border-radius: 6px; + margin: 2px; + padding: 2px 6px; + box-shadow: none; + background: rgba(99,102,241,0.12); + color: #a78bfa; + font-size: 0.875em; +} +pre { + background: #05070e !important; + border: 1px solid rgba(255,255,255,0.07); + border-radius: 10px; + box-shadow: 0 4px 24px rgba(0,0,0,0.4); +} +pre code { background: transparent; box-shadow: none; color: #e2e8f0; padding: 0; } + +/* ============================================================ + BUTTONS + ============================================================ */ +.btn-primary { + background: linear-gradient(135deg, #6366f1, #8b5cf6); + border-color: transparent; + color: #ffffff; +} +.btn-primary:hover { + background: linear-gradient(135deg, #4f52d8, #7c3aed); + border-color: transparent; +} + +/* ============================================================ + BREADCRUMB + ============================================================ */ +.breadcrumb-item + .breadcrumb-item::before { color: rgba(255,255,255,0.3); } +.breadcrumb-item a { color: #818cf8; } +.breadcrumb-item.active { color: rgba(255,255,255,0.5); } + +/* ============================================================ + STORYBOOK INTEGRATION + ============================================================ */ main.container-xxl:has(.storybook-container) { max-width: 100% !important; padding-right: 0 !important; margin-right: 0 !important; } - -main.container-xxl:has(.storybook-container) > .affix { - display: none !important; -} - -main.container-xxl:has(.storybook-container) > .content { - margin-right: 0 !important; -} +main.container-xxl:has(.storybook-container) > .affix { display: none !important; } +main.container-xxl:has(.storybook-container) > .content { margin-right: 0 !important; } .storybook-container { width: 100%; @@ -205,10 +236,19 @@ main.container-xxl:has(.storybook-container) > .content { margin: 0; padding: 0 1.5rem 0 0; } - .storybook-container iframe { width: 100%; height: 100%; border: none; display: block; } + +/* ============================================================ + LANDING PAGE - strip DocFX content wrapper padding + ============================================================ */ +article:has(.cratis-landing) { + padding: 0 !important; + margin: 0 !important; + max-width: 100% !important; +} +.content:has(.cratis-landing) { padding: 0 !important; } diff --git a/Source/templates/material/public/main.js b/Source/templates/material/public/main.js index 94c7554..e5f4d81 100644 --- a/Source/templates/material/public/main.js +++ b/Source/templates/material/public/main.js @@ -1,3 +1,7 @@ +// Always use dark theme – no light/dark switching +document.documentElement.setAttribute('data-bs-theme', 'dark'); +localStorage.setItem('docfx-theme', 'dark'); + export default { iconLinks: [ {