hscontrol/templates: add Material for MkDocs design assets

Add design system assets for HTML templates:
- headscale.svg: Logo with optimized viewBox for proper alignment
- style.css: Material for MkDocs CSS variables and typography
- design.go: Design system constants for consistent styling

The logo viewBox is adjusted to 32.92 0 1247.08 640 to eliminate
whitespace from the original export and ensure left alignment with
text content.
This commit is contained in:
Kristoffer Dalby authored and Kristoffer Dalby committed 2025-11-12 08:28:12 -06:00
1 parent 89285c317b
commit 285c4e46a9
3 files changed
+628

No files matched your search

+482
View File
@@ -0,0 +1,482 @@
package templates
import (
elem "github.com/chasefleming/elem-go"
"github.com/chasefleming/elem-go/attrs"
"github.com/chasefleming/elem-go/styles"
)
// Design System Constants
// These constants define the visual language for all Headscale HTML templates.
// They ensure consistency across all pages and make it easy to maintain and update the design.
// Color System
// EXTRACTED FROM: https://headscale.net/stable/assets/stylesheets/main.342714a4.min.css
// Material for MkDocs design system - exact values from official docs.
const (
// Text colors - from --md-default-fg-color CSS variables.
colorTextPrimary = "#000000de" //nolint:unused // rgba(0,0,0,0.87) - Body text
colorTextSecondary = "#0000008a" //nolint:unused // rgba(0,0,0,0.54) - Headings (--md-default-fg-color--light)
colorTextTertiary = "#00000052" //nolint:unused // rgba(0,0,0,0.32) - Lighter text
colorTextLightest = "#00000012" //nolint:unused // rgba(0,0,0,0.07) - Lightest text
// Code colors - from --md-code-* CSS variables.
colorCodeFg = "#36464e" //nolint:unused // Code text color (--md-code-fg-color)
colorCodeBg = "#f5f5f5" //nolint:unused // Code background (--md-code-bg-color)
// Border colors.
colorBorderLight = "#e5e7eb" //nolint:unused // Light borders
colorBorderMedium = "#d1d5db" //nolint:unused // Medium borders
// Background colors.
colorBackgroundPage = "#ffffff" //nolint:unused // Page background
colorBackgroundCard = "#ffffff" //nolint:unused // Card/content background
// Accent colors - from --md-primary/accent-fg-color.
colorPrimaryAccent = "#4051b5" //nolint:unused // Primary accent (links)
colorAccent = "#526cfe" //nolint:unused // Secondary accent
// Success colors.
colorSuccess = "#059669" //nolint:unused // Success states
colorSuccessLight = "#d1fae5" //nolint:unused // Success backgrounds
)
// Spacing System
// Based on 4px/8px base unit for consistent rhythm.
// Uses rem units for scalability with user font size preferences.
const (
spaceXS = "0.25rem" //nolint:unused // 4px - Tight spacing
spaceS = "0.5rem" //nolint:unused // 8px - Small spacing
spaceM = "1rem" //nolint:unused // 16px - Medium spacing (base)
spaceL = "1.5rem" //nolint:unused // 24px - Large spacing
spaceXL = "2rem" //nolint:unused // 32px - Extra large spacing
space2XL = "3rem" //nolint:unused // 48px - 2x extra large spacing
space3XL = "4rem" //nolint:unused // 64px - 3x extra large spacing
)
// Typography System
// EXTRACTED FROM: https://headscale.net/stable/assets/stylesheets/main.342714a4.min.css
// Material for MkDocs typography - exact values from .md-typeset CSS.
const (
// Font families - from CSS custom properties.
fontFamilySystem = `"Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif` //nolint:unused
fontFamilyCode = `"Roboto Mono", "SF Mono", Monaco, "Cascadia Code", Consolas, "Courier New", monospace` //nolint:unused
// Font sizes - from .md-typeset CSS rules.
fontSizeBase = "0.8rem" //nolint:unused // 12.8px - Base text (.md-typeset)
fontSizeH1 = "2em" //nolint:unused // 2x base - Main headings
fontSizeH2 = "1.5625em" //nolint:unused // 1.5625x base - Section headings
fontSizeH3 = "1.25em" //nolint:unused // 1.25x base - Subsection headings
fontSizeSmall = "0.8em" //nolint:unused // 0.8x base - Small text
fontSizeCode = "0.85em" //nolint:unused // 0.85x base - Inline code
// Line heights - from .md-typeset CSS rules.
lineHeightBase = "1.6" //nolint:unused // Body text (.md-typeset)
lineHeightH1 = "1.3" //nolint:unused // H1 headings
lineHeightH2 = "1.4" //nolint:unused // H2 headings
lineHeightH3 = "1.5" //nolint:unused // H3 headings
lineHeightCode = "1.4" //nolint:unused // Code blocks (pre)
)
// Responsive Container Component
// Creates a centered container with responsive padding and max-width.
// Mobile-first approach: starts at 100% width with padding, constrains on larger screens.
//
//nolint:unused // Reserved for future use in Phase 4.
func responsiveContainer(children ...elem.Node) *elem.Element {
return elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Width: "100%",
styles.MaxWidth: "min(800px, 90vw)", // Responsive: 90% of viewport or 800px max
styles.Margin: "0 auto", // Center horizontally
styles.Padding: "clamp(1rem, 5vw, 2.5rem)", // Fluid padding: 16px to 40px
}.ToInline(),
}, children...)
}
// Card Component
// Reusable card for grouping related content with visual separation.
// Parameters:
// - title: Optional title for the card (empty string for no title)
// - children: Content elements to display in the card
//
//nolint:unused // Reserved for future use in Phase 4.
func card(title string, children ...elem.Node) *elem.Element {
cardContent := children
if title != "" {
// Prepend title as H3 if provided
cardContent = append([]elem.Node{
elem.H3(attrs.Props{
attrs.Style: styles.Props{
styles.MarginTop: "0",
styles.MarginBottom: spaceM,
styles.FontSize: fontSizeH3,
styles.LineHeight: lineHeightH3, // 1.5 - H3 line height
styles.Color: colorTextSecondary,
}.ToInline(),
}, elem.Text(title)),
}, children...)
}
return elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Background: colorBackgroundCard,
styles.Border: "1px solid " + colorBorderLight,
styles.BorderRadius: "0.5rem", // 8px rounded corners
styles.Padding: "clamp(1rem, 3vw, 1.5rem)", // Responsive padding
styles.MarginBottom: spaceL,
styles.BoxShadow: "0 1px 3px rgba(0,0,0,0.1)", // Subtle shadow
}.ToInline(),
}, cardContent...)
}
// Code Block Component
// EXTRACTED FROM: .md-typeset pre CSS rules
// Exact styling from Material for MkDocs documentation.
//
//nolint:unused // Used across apple.go, windows.go, register_web.go templates.
func codeBlock(code string) *elem.Element {
return elem.Pre(attrs.Props{
attrs.Style: styles.Props{
styles.Display: "block",
styles.Padding: "0.77em 1.18em", // From .md-typeset pre
styles.Border: "none", // No border in original
styles.BorderRadius: "0.1rem", // From .md-typeset code
styles.BackgroundColor: colorCodeBg, // #f5f5f5
styles.FontFamily: fontFamilyCode, // Roboto Mono
styles.FontSize: fontSizeCode, // 0.85em
styles.LineHeight: lineHeightCode, // 1.4
styles.OverflowX: "auto", // Horizontal scroll
"overflow-wrap": "break-word", // Word wrapping
"word-wrap": "break-word", // Legacy support
styles.WhiteSpace: "pre-wrap", // Preserve whitespace
styles.MarginTop: spaceM, // 1em
styles.MarginBottom: spaceM, // 1em
styles.Color: colorCodeFg, // #36464e
styles.BoxShadow: "none", // No shadow in original
}.ToInline(),
},
elem.Code(nil, elem.Text(code)),
)
}
// Base Typeset Styles
// Returns inline styles for the main content container that matches .md-typeset.
// EXTRACTED FROM: .md-typeset CSS rule from Material for MkDocs.
//
//nolint:unused // Used in general.go for mdTypesetBody.
func baseTypesetStyles() styles.Props {
return styles.Props{
styles.FontSize: fontSizeBase, // 0.8rem
styles.LineHeight: lineHeightBase, // 1.6
styles.Color: colorTextPrimary,
styles.FontFamily: fontFamilySystem,
"overflow-wrap": "break-word",
styles.TextAlign: "left",
}
}
// H1 Styles
// Returns inline styles for H1 headings that match .md-typeset h1.
// EXTRACTED FROM: .md-typeset h1 CSS rule from Material for MkDocs.
//
//nolint:unused // Used across templates for main headings.
func h1Styles() styles.Props {
return styles.Props{
styles.Color: colorTextSecondary, // rgba(0, 0, 0, 0.54)
styles.FontSize: fontSizeH1, // 2em
styles.LineHeight: lineHeightH1, // 1.3
styles.Margin: "0 0 1.25em",
styles.FontWeight: "300",
"letter-spacing": "-0.01em",
styles.FontFamily: fontFamilySystem, // Roboto
"overflow-wrap": "break-word",
}
}
// H2 Styles
// Returns inline styles for H2 headings that match .md-typeset h2.
// EXTRACTED FROM: .md-typeset h2 CSS rule from Material for MkDocs.
//
//nolint:unused // Used across templates for section headings.
func h2Styles() styles.Props {
return styles.Props{
styles.FontSize: fontSizeH2, // 1.5625em
styles.LineHeight: lineHeightH2, // 1.4
styles.Margin: "1.6em 0 0.64em",
styles.FontWeight: "300",
"letter-spacing": "-0.01em",
styles.Color: colorTextSecondary, // rgba(0, 0, 0, 0.54)
styles.FontFamily: fontFamilySystem, // Roboto
"overflow-wrap": "break-word",
}
}
// H3 Styles
// Returns inline styles for H3 headings that match .md-typeset h3.
// EXTRACTED FROM: .md-typeset h3 CSS rule from Material for MkDocs.
//
//nolint:unused // Used across templates for subsection headings.
func h3Styles() styles.Props {
return styles.Props{
styles.FontSize: fontSizeH3, // 1.25em
styles.LineHeight: lineHeightH3, // 1.5
styles.Margin: "1.6em 0 0.8em",
styles.FontWeight: "400",
"letter-spacing": "-0.01em",
styles.Color: colorTextSecondary, // rgba(0, 0, 0, 0.54)
styles.FontFamily: fontFamilySystem, // Roboto
"overflow-wrap": "break-word",
}
}
// Paragraph Styles
// Returns inline styles for paragraphs that match .md-typeset p.
// EXTRACTED FROM: .md-typeset p CSS rule from Material for MkDocs.
//
//nolint:unused // Used for consistent paragraph spacing.
func paragraphStyles() styles.Props {
return styles.Props{
styles.Margin: "1em 0",
styles.FontFamily: fontFamilySystem, // Roboto
styles.FontSize: fontSizeBase, // 0.8rem - inherited from .md-typeset
styles.LineHeight: lineHeightBase, // 1.6 - inherited from .md-typeset
styles.Color: colorTextPrimary, // rgba(0, 0, 0, 0.87)
"overflow-wrap": "break-word",
}
}
// Ordered List Styles
// Returns inline styles for ordered lists that match .md-typeset ol.
// EXTRACTED FROM: .md-typeset ol CSS rule from Material for MkDocs.
//
//nolint:unused // Used for numbered instruction lists.
func orderedListStyles() styles.Props {
return styles.Props{
styles.MarginBottom: "1em",
styles.MarginTop: "1em",
styles.PaddingLeft: "2em",
styles.FontFamily: fontFamilySystem, // Roboto - inherited from .md-typeset
styles.FontSize: fontSizeBase, // 0.8rem - inherited from .md-typeset
styles.LineHeight: lineHeightBase, // 1.6 - inherited from .md-typeset
styles.Color: colorTextPrimary, // rgba(0, 0, 0, 0.87) - inherited from .md-typeset
"overflow-wrap": "break-word",
}
}
// Unordered List Styles
// Returns inline styles for unordered lists that match .md-typeset ul.
// EXTRACTED FROM: .md-typeset ul CSS rule from Material for MkDocs.
//
//nolint:unused // Used for bullet point lists.
func unorderedListStyles() styles.Props {
return styles.Props{
styles.MarginBottom: "1em",
styles.MarginTop: "1em",
styles.PaddingLeft: "2em",
styles.FontFamily: fontFamilySystem, // Roboto - inherited from .md-typeset
styles.FontSize: fontSizeBase, // 0.8rem - inherited from .md-typeset
styles.LineHeight: lineHeightBase, // 1.6 - inherited from .md-typeset
styles.Color: colorTextPrimary, // rgba(0, 0, 0, 0.87) - inherited from .md-typeset
"overflow-wrap": "break-word",
}
}
// Link Styles
// Returns inline styles for links that match .md-typeset a.
// EXTRACTED FROM: .md-typeset a CSS rule from Material for MkDocs.
// Note: Hover states cannot be implemented with inline styles.
//
//nolint:unused // Used for text links.
func linkStyles() styles.Props {
return styles.Props{
styles.Color: colorPrimaryAccent, // #4051b5 - var(--md-primary-fg-color)
styles.TextDecoration: "none",
"word-break": "break-word",
styles.FontFamily: fontFamilySystem, // Roboto - inherited from .md-typeset
}
}
// Inline Code Styles (updated)
// Returns inline styles for inline code that matches .md-typeset code.
// EXTRACTED FROM: .md-typeset code CSS rule from Material for MkDocs.
//
//nolint:unused // Used for inline code snippets.
func inlineCodeStyles() styles.Props {
return styles.Props{
styles.BackgroundColor: colorCodeBg, // #f5f5f5
styles.Color: colorCodeFg, // #36464e
styles.BorderRadius: "0.1rem",
styles.FontSize: fontSizeCode, // 0.85em
styles.FontFamily: fontFamilyCode, // Roboto Mono
styles.Padding: "0 0.2941176471em",
"word-break": "break-word",
}
}
// Inline Code Component
// For inline code snippets within text.
//
//nolint:unused // Reserved for future inline code usage.
func inlineCode(code string) *elem.Element {
return elem.Code(attrs.Props{
attrs.Style: inlineCodeStyles().ToInline(),
}, elem.Text(code))
}
// orDivider creates a visual "or" divider between sections.
// Styled with lines on either side for better visual separation.
//
//nolint:unused // Used in apple.go template.
func orDivider() *elem.Element {
return elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Display: "flex",
styles.AlignItems: "center",
styles.Gap: spaceM,
styles.MarginTop: space2XL,
styles.MarginBottom: space2XL,
styles.Width: "100%",
}.ToInline(),
},
elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Flex: "1",
styles.Height: "1px",
styles.BackgroundColor: colorBorderLight,
}.ToInline(),
}),
elem.Strong(attrs.Props{
attrs.Style: styles.Props{
styles.Color: colorTextSecondary,
styles.FontSize: fontSizeBase,
styles.FontWeight: "500",
"text-transform": "uppercase",
"letter-spacing": "0.05em",
}.ToInline(),
}, elem.Text("or")),
elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Flex: "1",
styles.Height: "1px",
styles.BackgroundColor: colorBorderLight,
}.ToInline(),
}),
)
}
// warningBox creates a warning message box with icon and content.
//
//nolint:unused // Used in apple.go template.
func warningBox(title, message string) *elem.Element {
return elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Display: "flex",
styles.AlignItems: "flex-start",
styles.Gap: spaceM,
styles.Padding: spaceL,
styles.BackgroundColor: "#fef3c7", // yellow-100
styles.Border: "1px solid #f59e0b", // yellow-500
styles.BorderRadius: "0.5rem",
styles.MarginTop: spaceL,
styles.MarginBottom: spaceL,
}.ToInline(),
},
elem.Raw(`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink: 0; margin-top: 2px;"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>`),
elem.Div(nil,
elem.Strong(attrs.Props{
attrs.Style: styles.Props{
styles.Display: "block",
styles.Color: "#92400e", // yellow-800
styles.FontSize: fontSizeH3,
styles.MarginBottom: spaceXS,
}.ToInline(),
}, elem.Text(title)),
elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Color: colorTextPrimary,
styles.FontSize: fontSizeBase,
}.ToInline(),
}, elem.Text(message)),
),
)
}
// downloadButton creates a nice button-style link for downloads.
//
//nolint:unused // Used in apple.go template.
func downloadButton(href, text string) *elem.Element {
return elem.A(attrs.Props{
attrs.Href: href,
attrs.Download: "headscale_macos.mobileconfig",
attrs.Style: styles.Props{
styles.Display: "inline-block",
styles.Padding: "0.75rem 1.5rem",
styles.BackgroundColor: "#3b82f6", // blue-500
styles.Color: "#ffffff",
styles.TextDecoration: "none",
styles.BorderRadius: "0.5rem",
styles.FontWeight: "500",
styles.Transition: "background-color 0.2s",
styles.MarginRight: spaceM,
styles.MarginBottom: spaceM,
}.ToInline(),
}, elem.Text(text))
}
// External Link Component
// Creates a link with proper security attributes for external URLs.
// Automatically adds rel="noreferrer noopener" and target="_blank".
//
//nolint:unused // Used in apple.go, oidc_callback.go templates.
func externalLink(href, text string) *elem.Element {
return elem.A(attrs.Props{
attrs.Href: href,
attrs.Rel: "noreferrer noopener",
attrs.Target: "_blank",
attrs.Style: styles.Props{
styles.Color: colorPrimaryAccent, // #4051b5 - base link color
styles.TextDecoration: "none",
}.ToInline(),
}, elem.Text(text))
}
// Instruction Step Component
// For numbered instruction lists with consistent formatting.
//
//nolint:unused // Reserved for future use in Phase 4.
func instructionStep(_ int, text string) *elem.Element {
return elem.Li(attrs.Props{
attrs.Style: styles.Props{
styles.MarginBottom: spaceS,
styles.LineHeight: lineHeightBase,
}.ToInline(),
}, elem.Text(text))
}
// Status Message Component
// For displaying success/error/info messages with appropriate styling.
//
//nolint:unused // Reserved for future use in Phase 4.
func statusMessage(message string, isSuccess bool) *elem.Element {
bgColor := colorSuccessLight
textColor := colorSuccess
if !isSuccess {
bgColor = "#fee2e2" // red-100
textColor = "#dc2626" // red-600
}
return elem.Div(attrs.Props{
attrs.Style: styles.Props{
styles.Padding: spaceM,
styles.BackgroundColor: bgColor,
styles.Color: textColor,
styles.BorderRadius: "0.5rem",
styles.Border: "1px solid " + textColor,
styles.MarginBottom: spaceL,
styles.FontSize: fontSizeBase,
styles.LineHeight: lineHeightBase,
}.ToInline(),
}, elem.Text(message))
}
+1
View File
@@ -0,0 +1 @@
<svg class="headscale-logo" width="400" height="140" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2" viewBox="32.92 0 1247.08 640"><path d="M.08 0v-.736h.068v.3C.203-.509.27-.545.347-.545c.029 0 .055.005.079.015.024.01.045.025.062.045.017.02.031.045.041.075.009.03.014.065.014.105V0H.475v-.289C.475-.352.464-.4.443-.433.422-.466.385-.483.334-.483c-.027 0-.052.006-.075.017C.236-.455.216-.439.2-.419c-.017.02-.029.044-.038.072-.009.028-.014.059-.014.093V0H.08Z" style="fill:#f8b5cb;fill-rule:nonzero" transform="translate(32.92220721 521.8022953) scale(235.3092)"/><path d="M.051-.264c0-.036.007-.071.02-.105.013-.034.031-.064.055-.09.023-.026.052-.047.086-.063.033-.015.071-.023.112-.023.039 0 .076.007.109.021.033.014.062.033.087.058.025.025.044.054.058.088.014.035.021.072.021.113v.005H.121c.001.031.007.059.018.084.01.025.024.047.042.065.018.019.04.033.065.043.025.01.052.015.082.015.026 0 .049-.003.069-.01.02-.007.038-.016.054-.028C.466-.102.48-.115.492-.13c.011-.015.022-.03.032-.046l.057.03C.556-.097.522-.058.48-.03.437-.001.387.013.328.013.284.013.245.006.21-.01.175-.024.146-.045.123-.07.1-.095.082-.125.07-.159.057-.192.051-.227.051-.264ZM.128-.32h.396C.51-.375.485-.416.449-.441.412-.466.371-.479.325-.479c-.048 0-.089.013-.123.039-.034.026-.059.066-.074.12Z" style="fill:#8d8d8d;fill-rule:nonzero" transform="translate(177.16674681 521.8022953) scale(235.3092)"/><path d="M.051-.267c0-.038.007-.074.021-.108.014-.033.033-.063.058-.088.025-.025.054-.045.087-.06.033-.015.069-.022.108-.022.043 0 .083.009.119.027.035.019.066.047.093.084v-.097h.067V0H.537v-.091C.508-.056.475-.029.44-.013.404.005.365.013.323.013.284.013.248.006.215-.01.182-.024.153-.045.129-.071.104-.096.085-.126.072-.16.058-.193.051-.229.051-.267Zm.279.218c.027 0 .054-.005.079-.015.025-.01.048-.024.068-.043.019-.018.035-.04.047-.067.012-.027.018-.056.018-.089 0-.031-.005-.059-.016-.086C.515-.375.501-.398.482-.417.462-.436.44-.452.415-.463.389-.474.361-.479.331-.479c-.031 0-.059.006-.084.017C.221-.45.199-.434.18-.415c-.019.02-.033.043-.043.068-.011.026-.016.053-.016.082 0 .029.005.056.016.082.011.026.025.049.044.069.019.02.041.036.066.047.025.012.053.018.083.018Z" style="fill:#8d8d8d;fill-rule:nonzero" transform="translate(327.76463481 521.8022953) scale(235.3092)"/><path d="M.051-.267c0-.038.007-.074.021-.108.014-.033.033-.063.058-.088.025-.025.054-.045.087-.06.033-.015.069-.022.108-.022.043 0 .083.009.119.027.035.019.066.047.093.084v-.302h.068V0H.537v-.091C.508-.056.475-.029.44-.013.404.005.365.013.323.013.284.013.248.006.215-.01.182-.024.153-.045.129-.071.104-.096.085-.126.072-.16.058-.193.051-.229.051-.267Zm.279.218c.027 0 .054-.005.079-.015.025-.01.048-.024.068-.043.019-.018.035-.04.047-.067.011-.027.017-.056.017-.089 0-.031-.005-.059-.016-.086C.514-.375.5-.398.481-.417.462-.436.439-.452.414-.463.389-.474.361-.479.331-.479c-.031 0-.059.006-.084.017C.221-.45.199-.434.18-.415c-.019.02-.033.043-.043.068-.011.026-.016.053-.016.082 0 .029.005.056.016.082.011.026.025.049.044.069.019.02.041.036.066.047.025.012.053.018.083.018Z" style="fill:#8d8d8d;fill-rule:nonzero" transform="translate(488.71612761 521.8022953) scale(235.3092)"/><path d="m.034-.062.043-.049c.017.019.035.034.054.044.018.01.037.015.057.015.013 0 .026-.002.038-.007.011-.004.021-.01.031-.018.009-.008.016-.017.021-.028.005-.011.008-.022.008-.035 0-.019-.005-.034-.014-.047C.263-.199.248-.21.229-.221.205-.234.183-.247.162-.259.14-.271.122-.284.107-.298.092-.311.08-.327.071-.344.062-.361.058-.381.058-.404c0-.021.004-.04.012-.058.007-.016.018-.031.031-.044.013-.013.028-.022.046-.029.018-.007.037-.01.057-.01.029 0 .056.006.079.019s.045.031.068.053l-.044.045C.291-.443.275-.456.258-.465.241-.474.221-.479.2-.479c-.022 0-.041.007-.056.02C.128-.445.12-.428.12-.408c0 .019.006.035.017.048.011.013.027.026.048.037.027.015.05.028.071.04.021.013.038.026.052.039.014.013.025.028.032.044.007.016.011.035.011.057 0 .021-.004.041-.011.059-.008.019-.019.036-.033.05-.014.015-.031.026-.05.035C.237.01.215.014.191.014c-.03 0-.059-.006-.086-.02C.077-.019.053-.037.034-.062Z" style="fill:#8d8d8d;fill-rule:nonzero" transform="translate(649.90292961 521.8022953) scale(235.3092)"/><path d="M.051-.266c0-.04.007-.077.022-.111.014-.034.034-.063.059-.089.025-.025.054-.044.089-.058.035-.014.072-.021.113-.021.051 0 .098.01.139.03.041.021.075.049.1.085l-.05.043C.498-.418.47-.441.439-.456.408-.471.372-.479.331-.479c-.03 0-.058.005-.083.016C.222-.452.2-.436.181-.418.162-.399.148-.376.137-.35c-.011.026-.016.054-.016.084 0 .031.005.06.016.086.011.027.025.049.044.068.019.019.041.034.067.044.025.011.053.016.084.016.077 0 .141-.03.191-.09l.051.04c-.028.036-.062.064-.103.085C.43.004.384.014.332.014.291.014.254.007.219-.008.184-.022.155-.042.13-.067.105-.092.086-.121.072-.156.058-.19.051-.227.051-.266Z" style="fill:#8d8d8d;fill-rule:nonzero" transform="translate(741.20289921 521.8022953) scale(235.3092)"/><path d="M.051-.267c0-.038.007-.074.021-.108.0Line truncated

After

Width:  |  Height:  |  Size: 7.8 KiB

+145
View File
@@ -0,0 +1,145 @@
/* CSS Variables from Material for MkDocs */
:root {
--md-default-fg-color: rgba(0, 0, 0, 0.87);
--md-default-fg-color--light: rgba(0, 0, 0, 0.54);
--md-default-fg-color--lighter: rgba(0, 0, 0, 0.32);
--md-default-fg-color--lightest: rgba(0, 0, 0, 0.07);
--md-code-fg-color: #36464e;
--md-code-bg-color: #f5f5f5;
--md-primary-fg-color: #4051b5;
--md-accent-fg-color: #526cfe;
--md-typeset-a-color: var(--md-primary-fg-color);
--md-text-font: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI",
"Helvetica Neue", Arial, sans-serif;
--md-code-font: "Roboto Mono", "SF Mono", Monaco, "Cascadia Code", Consolas,
"Courier New", monospace;
}
/* Base Typography */
.md-typeset {
font-size: 0.8rem;
line-height: 1.6;
color: var(--md-default-fg-color);
font-family: var(--md-text-font);
overflow-wrap: break-word;
text-align: left;
}
/* Headings */
.md-typeset h1 {
color: var(--md-default-fg-color--light);
font-size: 2em;
line-height: 1.3;
margin: 0 0 1.25em;
font-weight: 300;
letter-spacing: -0.01em;
}
.md-typeset h1:not(:first-child) {
margin-top: 2em;
}
.md-typeset h2 {
font-size: 1.5625em;
line-height: 1.4;
margin: 2.4em 0 0.64em;
font-weight: 300;
letter-spacing: -0.01em;
color: var(--md-default-fg-color--light);
}
.md-typeset h3 {
font-size: 1.25em;
line-height: 1.5;
margin: 2em 0 0.8em;
font-weight: 400;
letter-spacing: -0.01em;
color: var(--md-default-fg-color--light);
}
/* Paragraphs and block elements */
.md-typeset p {
margin: 1em 0;
}
.md-typeset blockquote,
.md-typeset dl,
.md-typeset figure,
.md-typeset ol,
.md-typeset pre,
.md-typeset ul {
margin-bottom: 1em;
margin-top: 1em;
}
/* Lists */
.md-typeset ol,
.md-typeset ul {
padding-left: 2em;
}
/* Links */
.md-typeset a {
color: var(--md-typeset-a-color);
text-decoration: none;
word-break: break-word;
}
.md-typeset a:hover,
.md-typeset a:focus {
color: var(--md-accent-fg-color);
}
/* Code (inline) */
.md-typeset code {
background-color: var(--md-code-bg-color);
color: var(--md-code-fg-color);
border-radius: 0.1rem;
font-size: 0.85em;
font-family: var(--md-code-font);
padding: 0 0.2941176471em;
word-break: break-word;
}
/* Code blocks (pre) */
.md-typeset pre {
display: block;
line-height: 1.4;
margin: 1em 0;
overflow-x: auto;
}
.md-typeset pre > code {
background-color: var(--md-code-bg-color);
color: var(--md-code-fg-color);
display: block;
padding: 0.7720588235em 1.1764705882em;
font-family: var(--md-code-font);
font-size: 0.85em;
line-height: 1.4;
overflow-wrap: break-word;
word-wrap: break-word;
white-space: pre-wrap;
}
/* Links in code */
.md-typeset a code {
color: currentcolor;
}
/* Logo */
.headscale-logo {
display: block;
width: 400px;
max-width: 100%;
height: auto;
margin: 0 0 3rem 0;
padding: 0;
}
@media (max-width: 768px) {
.headscale-logo {
width: 200px;
margin-left: 0;
}
}