Skip to main content

euv_ui/style/css/
const.rs

1/// Raw stylesheet for rendered markdown bodies ([`crate::euv_markdown`]).
2///
3/// `class!` cannot express descendant selectors, so markdown typography is
4/// injected once at startup through `Css::inject_css`. All colors reference
5/// the theme CSS variables, so light/dark switching works unchanged.
6pub const EUV_MD_CSS: &str = r#"
7.md-body {
8    line-height: 1.7;
9    font-size: var(--font-base);
10    word-wrap: break-word;
11}
12.md-body h1, .md-body h2, .md-body h3, .md-body h4, .md-body h5, .md-body h6 {
13    position: relative;
14    font-weight: 700;
15    letter-spacing: -0.01em;
16    margin-top: 1.8em;
17    margin-bottom: 0.6em;
18    scroll-margin-top: 72px;
19    line-height: 1.3;
20}
21.md-body h1 {
22    font-size: var(--font-3xl);
23    margin-top: 0;
24    padding-bottom: 0.4em;
25    border-bottom: 1px solid var(--border);
26}
27.md-body h2 {
28    font-size: var(--font-2xl);
29    padding-bottom: 0.3em;
30    border-bottom: 1px dashed var(--border);
31}
32.md-body h3 { font-size: var(--font-xl); }
33.md-body h4 { font-size: var(--font-lg); }
34.md-body h5, .md-body h6 { font-size: var(--font-base); }
35.md-body .header-anchor {
36    float: left;
37    margin-left: -0.9em;
38    padding-right: 0.2em;
39    opacity: 0;
40    color: var(--muted-foreground);
41    font-weight: 400;
42    transition: opacity 0.15s ease-out;
43    user-select: none;
44}
45.md-body h1:hover .header-anchor,
46.md-body h2:hover .header-anchor,
47.md-body h3:hover .header-anchor,
48.md-body h4:hover .header-anchor,
49.md-body h5:hover .header-anchor,
50.md-body h6:hover .header-anchor {
51    opacity: 1;
52}
53/* On narrow viewports the negative `margin-left: -0.9em` pushes the `#`
54   sign past the left edge of the viewport (anchor x ≈ -11px on a 380px
55   viewport), so hover-revealed anchors get clipped. On mobile we drop
56   the float + negative margin and absolutely position the anchor at
57   the heading's left edge instead, with the heading content shifted
58   right via `padding-left`. This way:
59
60   * The `#` stays inside the viewport at all times.
61   * The `#` is vertically centered against the first line of the
62     heading (`align-items: center`), so the two sit on the same
63     optical line instead of the `#` floating above the heading text.
64   * The heading text gets the full content width (minus the small
65     reserved gutter), so a long heading like "Markdown Features" no
66     longer wraps with one orphan word on its own line leaving a big
67     empty space at the end of the first line. */
68@media (max-width: 767px) {
69    .md-body h1,
70    .md-body h2,
71    .md-body h3,
72    .md-body h4,
73    .md-body h5,
74    .md-body h6 {
75        position: relative;
76        padding-left: 1.6em;
77    }
78    .md-body .header-anchor {
79        position: absolute;
80        left: 0;
81        top: 0;
82        height: 100%;
83        width: 1em;
84        margin: 0;
85        padding: 0;
86        float: none;
87        display: inline-flex;
88        align-items: center;
89        justify-content: center;
90        font-size: 0.85em;
91        line-height: 1;
92    }
93}
94.md-body p, .md-body ul, .md-body ol, .md-body blockquote, .md-body pre, .md-body table {
95    margin: 1em 0;
96}
97.md-body ul, .md-body ol {
98    padding-left: 1.4em;
99}
100.md-body ul { list-style: disc; }
101.md-body ol { list-style: decimal; }
102.md-body ul ul, .md-body ul ol, .md-body ol ul, .md-body ol ol {
103    margin: 0.25em 0;
104}
105.md-body li { margin: 0.25em 0; }
106.md-body li input[type="checkbox"] {
107    margin-right: 0.4em;
108    accent-color: var(--accent);
109}
110.md-body a {
111    color: var(--accent);
112    font-weight: 500;
113    text-decoration: underline;
114    text-underline-offset: 3px;
115    text-decoration-style: dashed;
116    text-decoration-color: var(--border);
117}
118.md-body a:hover {
119    text-decoration-style: solid;
120    text-decoration-color: var(--accent);
121}
122.md-body strong { font-weight: 700; }
123.md-body em { font-style: italic; }
124.md-body del { opacity: 0.6; }
125.md-body hr {
126    border: none;
127    border-top: 1px dashed var(--border);
128    margin: 2em 0;
129}
130.md-body blockquote {
131    margin: 1em 0;
132    padding: 0.4em 1em;
133    border-left: 4px solid var(--border);
134    color: var(--muted-foreground);
135}
136.md-body blockquote p { margin: 0.4em 0; }
137.md-body code {
138    font-family: ui-monospace, monospace;
139    font-size: 0.875em;
140    padding: 0.15em 0.4em;
141    background: var(--accent-muted);
142    border: 1px solid var(--border);
143    /* Inline <code> that wraps to multiple lines must keep its border
144       on every fragment, otherwise the first line loses its right border
145       and subsequent lines lose their left border.
146
147       box-decoration-break: clone alone is not enough in practice: the
148       per-fragment borders stack against the next fragment's background
149       and the visual gap between fragments collapses, making the right
150       border of one line look like the left border of the next (and
151       neither looks fully closed). Making the element inline-block
152       guarantees each fragment draws its own box with its own four
153       borders, exactly the same trick used by euv_tag. */
154    -webkit-box-decoration-break: clone;
155    box-decoration-break: clone;
156    display: inline-block;
157    vertical-align: text-top;
158    line-height: 1.4;
159}
160.md-body pre {
161    padding: 1em 1.2em;
162    overflow-x: auto;
163    border: 1px solid var(--border);
164    background: var(--accent-muted);
165}
166.md-body pre code {
167    padding: 0;
168    border: none;
169    background: transparent;
170    font-size: 0.875rem;
171    line-height: 1.6;
172}
173.md-body table {
174    width: 100%;
175    border-collapse: collapse;
176    font-size: var(--font-sm);
177    display: block;
178    overflow-x: auto;
179}
180.md-body table thead { border-bottom: 2px solid var(--border); }
181.md-body table th, .md-body table td {
182    padding: 0.5em 0.9em;
183    border: 1px solid var(--border);
184    text-align: left;
185}
186.md-body table th { font-weight: 700; }
187.md-body table tbody tr:nth-child(2n) { background: var(--accent-muted); }
188.md-body img { max-width: 100%; }
189.md-body .docs-container {
190    margin: 1.2em 0;
191    padding: 0.1em 1.2em;
192    border-left: 4px solid var(--foreground);
193    background: var(--accent-muted);
194}
195.md-body .docs-container .docs-container-title {
196    font-weight: 700;
197    font-size: var(--font-sm);
198    letter-spacing: 0.04em;
199    text-transform: uppercase;
200    margin: 0.8em 0 0.4em;
201}
202.md-body .docs-container.tip { border-left-style: solid; }
203.md-body .docs-container.warning { border-left-style: dashed; }
204.md-body .docs-container.danger {
205    border-left: 4px double var(--foreground);
206}
207.md-body .docs-container.details {
208    border-left: 1px solid var(--border);
209    background: transparent;
210}
211.md-body .footnote-definition { font-size: var(--font-sm); color: var(--muted-foreground); }
212"#;