@tdocs/tdocs 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/compiler.js +80 -5
- package/build/parser.js +28 -7
- package/package.json +1 -1
- package/templates/style.css +292 -24
package/build/compiler.js
CHANGED
|
@@ -44,7 +44,13 @@ renderer.paragraph = function ({ tokens }) {
|
|
|
44
44
|
const text = this.parser.parseInline(tokens);
|
|
45
45
|
return applyAttributes(text, (t) => `<p>${t}</p>\n`);
|
|
46
46
|
};
|
|
47
|
-
|
|
47
|
+
renderer.br = function () {
|
|
48
|
+
return '</p>\n<p>';
|
|
49
|
+
};
|
|
50
|
+
marked_1.marked.use({
|
|
51
|
+
renderer,
|
|
52
|
+
breaks: true
|
|
53
|
+
});
|
|
48
54
|
marked_1.marked.use((0, marked_highlight_1.markedHighlight)({
|
|
49
55
|
langPrefix: 'hljs language-',
|
|
50
56
|
highlight(code, lang) {
|
|
@@ -55,14 +61,83 @@ marked_1.marked.use((0, marked_highlight_1.markedHighlight)({
|
|
|
55
61
|
// Phase 2: Markdown Compilation
|
|
56
62
|
// This module will iterate through the AST and transform raw Markdown strings into valid HTML strings.
|
|
57
63
|
function compileMarkdown(ast) {
|
|
64
|
+
// Regex to find things like {{ installation.html }} or { installation.html }
|
|
65
|
+
const injectionRegex = /\{\{?\s*([a-zA-Z0-9_.-]+)\s*\}?\}/g;
|
|
58
66
|
// Recursively compile markdown content to html
|
|
59
67
|
function compileNode(node) {
|
|
68
|
+
let generatedHtml = `<h1>${node.title}</h1>\n`;
|
|
60
69
|
if (node.markdownContent) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
// 1. Strip base indentation from all lines so Marked doesn't treat the whole block as code
|
|
71
|
+
let lines = node.markdownContent.split('\n');
|
|
72
|
+
const nonEmptyLines = lines.filter(l => l.trim().length > 0);
|
|
73
|
+
if (nonEmptyLines.length > 0) {
|
|
74
|
+
const minIndent = Math.min(...nonEmptyLines.map(l => l.match(/^[ \t]*/)?.[0].length || 0));
|
|
75
|
+
if (minIndent > 0) {
|
|
76
|
+
lines = lines.map(line => line.trim().length > 0 ? line.substring(minIndent) : '');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// 2. Custom DSL Pre-processor
|
|
80
|
+
let listMode = 'none';
|
|
81
|
+
let listIndent = 0;
|
|
82
|
+
let olCounter = 1;
|
|
83
|
+
for (let i = 0; i < lines.length; i++) {
|
|
84
|
+
const line = lines[i];
|
|
85
|
+
const trimmed = line.trim();
|
|
86
|
+
const hMatch = line.match(/^([ \t]*)h([1-6]):[ \t]*(.*)$/);
|
|
87
|
+
if (hMatch) {
|
|
88
|
+
lines[i] = `${hMatch[1]}${'#'.repeat(parseInt(hMatch[2]))} ${hMatch[3].trimEnd()}`;
|
|
89
|
+
listMode = 'none';
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (trimmed === 'list:') {
|
|
93
|
+
listMode = 'ul';
|
|
94
|
+
listIndent = line.match(/^[ \t]*/)?.[0].length || 0;
|
|
95
|
+
lines[i] = '';
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (trimmed === 'numberlist:') {
|
|
99
|
+
listMode = 'ol';
|
|
100
|
+
listIndent = line.match(/^[ \t]*/)?.[0].length || 0;
|
|
101
|
+
olCounter = 1;
|
|
102
|
+
lines[i] = '';
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (listMode !== 'none') {
|
|
106
|
+
const currentIndent = line.match(/^[ \t]*/)?.[0].length || 0;
|
|
107
|
+
if (trimmed === '') {
|
|
108
|
+
// Ignore empty lines
|
|
109
|
+
}
|
|
110
|
+
else if (currentIndent <= listIndent) {
|
|
111
|
+
listMode = 'none'; // Exit list mode on dedent
|
|
112
|
+
// Need to process this line normally now since it's not a list item
|
|
113
|
+
const hMatch = line.match(/^([ \t]*)h([1-6]):[ \t]*(.*)$/);
|
|
114
|
+
if (hMatch) {
|
|
115
|
+
lines[i] = `${hMatch[1]}${'#'.repeat(parseInt(hMatch[2]))} ${hMatch[3].trimEnd()}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
const relativeIndent = Math.max(0, currentIndent - listIndent - 2);
|
|
120
|
+
const spaces = ' '.repeat(relativeIndent);
|
|
121
|
+
if (listMode === 'ul') {
|
|
122
|
+
lines[i] = `${spaces}- ${trimmed}`;
|
|
123
|
+
}
|
|
124
|
+
else if (listMode === 'ol') {
|
|
125
|
+
lines[i] = `${spaces}${olCounter++}. ${trimmed}`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let processedContent = lines.join('\n');
|
|
131
|
+
// 3. Inject HTML Partials
|
|
132
|
+
processedContent = processedContent.replace(injectionRegex, (match, varName) => {
|
|
133
|
+
if (ast.partials && ast.partials[varName]) {
|
|
134
|
+
return ast.partials[varName];
|
|
135
|
+
}
|
|
136
|
+
return match; // Keep string intact if var not found
|
|
137
|
+
});
|
|
138
|
+
generatedHtml += marked_1.marked.parse(processedContent);
|
|
65
139
|
}
|
|
140
|
+
node.htmlContent = generatedHtml;
|
|
66
141
|
if (node.children && node.children.length > 0) {
|
|
67
142
|
node.children.forEach(compileNode);
|
|
68
143
|
}
|
package/build/parser.js
CHANGED
|
@@ -5,16 +5,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.parseTDoc = parseTDoc;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
8
9
|
// The config is simple key-value pairs, let's parse it manually.
|
|
9
10
|
function parseTDoc(filePath) {
|
|
10
11
|
const fileContent = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
11
12
|
let config = {};
|
|
13
|
+
let partials = {};
|
|
12
14
|
let rawBody = fileContent;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
// 1. Extract Imports (Custom HTML Snippets)
|
|
16
|
+
const importRegex = /^import\s+([^\s]+)\s+from\s+['"]([^'"]+)['"]/gm;
|
|
17
|
+
let match;
|
|
18
|
+
while ((match = importRegex.exec(fileContent)) !== null) {
|
|
19
|
+
const variableName = match[1];
|
|
20
|
+
const relativePath = match[2];
|
|
21
|
+
const tdocDirectory = path_1.default.dirname(filePath);
|
|
22
|
+
const absolutePath = path_1.default.resolve(tdocDirectory, relativePath);
|
|
23
|
+
if (fs_1.default.existsSync(absolutePath)) {
|
|
24
|
+
partials[variableName] = fs_1.default.readFileSync(absolutePath, 'utf-8');
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
console.warn(`Warning: Could not find imported file ${absolutePath}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Remove processed imports from rawBody
|
|
31
|
+
rawBody = rawBody.replace(importRegex, '').trim();
|
|
32
|
+
// 2. Parse Config Frontmatter
|
|
33
|
+
if (rawBody.startsWith('@config')) {
|
|
34
|
+
const endConfigIdx = rawBody.indexOf('---');
|
|
15
35
|
if (endConfigIdx !== -1) {
|
|
16
|
-
const configBlock =
|
|
17
|
-
rawBody =
|
|
36
|
+
const configBlock = rawBody.substring('@config'.length, endConfigIdx).trim();
|
|
37
|
+
rawBody = rawBody.substring(endConfigIdx + 3).trim();
|
|
18
38
|
// Parse key: value
|
|
19
39
|
const configLines = configBlock.split('\n');
|
|
20
40
|
for (const line of configLines) {
|
|
@@ -32,10 +52,11 @@ function parseTDoc(filePath) {
|
|
|
32
52
|
}
|
|
33
53
|
}
|
|
34
54
|
}
|
|
35
|
-
//
|
|
55
|
+
// 3. Parse structural markers and markdown content
|
|
36
56
|
const tree = buildTree(rawBody);
|
|
37
57
|
return {
|
|
38
58
|
config,
|
|
59
|
+
partials,
|
|
39
60
|
tree
|
|
40
61
|
};
|
|
41
62
|
}
|
|
@@ -51,7 +72,7 @@ function buildTree(content) {
|
|
|
51
72
|
if (match) {
|
|
52
73
|
// It's a structural marker
|
|
53
74
|
const indentStr = match[1];
|
|
54
|
-
const title = match[2];
|
|
75
|
+
const title = match[2].trimEnd();
|
|
55
76
|
const level = indentStr.length;
|
|
56
77
|
const newNode = {
|
|
57
78
|
id: title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, ''),
|
|
@@ -90,7 +111,7 @@ function buildTree(content) {
|
|
|
90
111
|
// Clean up trailing whitespace on markdown content
|
|
91
112
|
const cleanMarkdown = (nodes) => {
|
|
92
113
|
for (const node of nodes) {
|
|
93
|
-
node.markdownContent = node.markdownContent.
|
|
114
|
+
node.markdownContent = node.markdownContent.trimEnd();
|
|
94
115
|
cleanMarkdown(node.children);
|
|
95
116
|
}
|
|
96
117
|
};
|
package/package.json
CHANGED
package/templates/style.css
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
|
+
@import url('https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500&family=Poppins:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400&display=swap');
|
|
2
|
+
|
|
1
3
|
:root {
|
|
2
|
-
--bg-color: #
|
|
3
|
-
--
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
--
|
|
7
|
-
--
|
|
4
|
+
--bg-color: #0d0d10;
|
|
5
|
+
--bg-surface: #141418;
|
|
6
|
+
--bg-elevated: #1a1a20;
|
|
7
|
+
--bg-hover: #1e1e26;
|
|
8
|
+
--text-color: #e8e8f0;
|
|
9
|
+
--text-muted: #888899;
|
|
10
|
+
--text-subtle: #555566;
|
|
11
|
+
--sidebar-bg: #111115;
|
|
12
|
+
--header-bg: #0a0a0d;
|
|
13
|
+
--header-text: #f0f0f8;
|
|
14
|
+
--accent-color: #7c6af7;
|
|
15
|
+
--accent-glow: rgba(124, 106, 247, 0.15);
|
|
16
|
+
--accent-dim: rgba(124, 106, 247, 0.4);
|
|
17
|
+
--border-color: rgba(255,255,255,0.06);
|
|
18
|
+
--border-active: rgba(124, 106, 247, 0.5);
|
|
19
|
+
--code-bg: #0f0f14;
|
|
20
|
+
--radius: 8px;
|
|
21
|
+
--radius-sm: 5px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
* {
|
|
25
|
+
box-sizing: border-box;
|
|
8
26
|
}
|
|
9
27
|
|
|
10
28
|
.tdoc-body {
|
|
11
|
-
font-family:
|
|
29
|
+
font-family: 'Poppins', sans-serif;
|
|
12
30
|
margin: 0;
|
|
13
31
|
padding: 0;
|
|
14
32
|
background-color: var(--bg-color);
|
|
@@ -16,64 +34,314 @@
|
|
|
16
34
|
display: flex;
|
|
17
35
|
flex-direction: column;
|
|
18
36
|
min-height: 100vh;
|
|
37
|
+
font-size: 15px;
|
|
38
|
+
line-height: 1.7;
|
|
39
|
+
-webkit-font-smoothing: antialiased;
|
|
19
40
|
}
|
|
20
41
|
|
|
42
|
+
/* ── Header ── */
|
|
21
43
|
.tdoc-header {
|
|
22
44
|
background-color: var(--header-bg);
|
|
23
45
|
color: var(--header-text);
|
|
24
|
-
padding:
|
|
46
|
+
padding: 0 2rem;
|
|
47
|
+
height: 56px;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
border-bottom: 1px solid var(--border-color);
|
|
51
|
+
position: sticky;
|
|
52
|
+
top: 0;
|
|
53
|
+
z-index: 100;
|
|
54
|
+
backdrop-filter: blur(12px);
|
|
25
55
|
}
|
|
26
56
|
|
|
27
57
|
.tdoc-site-title {
|
|
28
58
|
margin: 0;
|
|
59
|
+
font-family: 'Poppins', sans-serif;
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
font-style: bold;
|
|
62
|
+
font-size: 1.3rem;
|
|
63
|
+
letter-spacing: 0.01em;
|
|
64
|
+
color: var(--header-text);
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: 0.5rem;
|
|
29
68
|
}
|
|
30
69
|
|
|
70
|
+
.tdoc-site-title::before {
|
|
71
|
+
content: '';
|
|
72
|
+
display: inline-block;
|
|
73
|
+
width: 8px;
|
|
74
|
+
height: 8px;
|
|
75
|
+
border-radius: 50%;
|
|
76
|
+
background: var(--accent-color);
|
|
77
|
+
box-shadow: 0 0 10px var(--accent-color);
|
|
78
|
+
flex-shrink: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ── Layout ── */
|
|
31
82
|
.tdoc-layout {
|
|
32
83
|
display: flex;
|
|
33
84
|
flex: 1;
|
|
34
85
|
}
|
|
35
86
|
|
|
87
|
+
/* ── Sidebar ── */
|
|
36
88
|
.tdoc-sidebar {
|
|
37
|
-
width:
|
|
89
|
+
width: 260px;
|
|
90
|
+
flex-shrink: 0;
|
|
38
91
|
background-color: var(--sidebar-bg);
|
|
39
|
-
padding:
|
|
40
|
-
border-right: 1px solid
|
|
92
|
+
padding: 1.5rem 0.75rem;
|
|
93
|
+
border-right: 1px solid var(--border-color);
|
|
94
|
+
position: sticky;
|
|
95
|
+
top: 56px;
|
|
96
|
+
height: calc(100vh - 56px);
|
|
97
|
+
overflow-y: auto;
|
|
98
|
+
scrollbar-width: thin;
|
|
99
|
+
scrollbar-color: var(--text-subtle) transparent;
|
|
41
100
|
}
|
|
42
101
|
|
|
102
|
+
.tdoc-sidebar::-webkit-scrollbar {
|
|
103
|
+
width: 4px;
|
|
104
|
+
}
|
|
105
|
+
.tdoc-sidebar::-webkit-scrollbar-track {
|
|
106
|
+
background: transparent;
|
|
107
|
+
}
|
|
108
|
+
.tdoc-sidebar::-webkit-scrollbar-thumb {
|
|
109
|
+
background: var(--text-subtle);
|
|
110
|
+
border-radius: 4px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* ── Nav Items ── */
|
|
43
114
|
.tdoc-nav-item {
|
|
44
115
|
margin-left: var(--tdoc-indent, 0px);
|
|
45
|
-
padding:
|
|
116
|
+
padding: 6px 10px;
|
|
46
117
|
cursor: pointer;
|
|
47
|
-
color: var(--
|
|
118
|
+
color: var(--text-muted);
|
|
119
|
+
font-size: 0.84rem;
|
|
120
|
+
font-weight: 400;
|
|
121
|
+
border-radius: var(--radius-sm);
|
|
122
|
+
transition: color 0.15s ease, background 0.15s ease;
|
|
123
|
+
position: relative;
|
|
124
|
+
letter-spacing: 0.01em;
|
|
125
|
+
line-height: 1.4;
|
|
126
|
+
margin-bottom: 1px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.tdoc-nav-item[data-level="0"] {
|
|
130
|
+
font-size: 0.8rem;
|
|
131
|
+
font-weight: 600;
|
|
132
|
+
text-transform: uppercase;
|
|
133
|
+
letter-spacing: 0.08em;
|
|
134
|
+
color: var(--text-subtle);
|
|
135
|
+
margin-top: 1rem;
|
|
136
|
+
padding: 4px 10px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.tdoc-nav-item[data-level="0"]:first-child {
|
|
140
|
+
margin-top: 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.tdoc-nav-item[data-level="2"] {
|
|
144
|
+
font-size: 0.85rem;
|
|
145
|
+
font-weight: 400;
|
|
48
146
|
}
|
|
49
147
|
|
|
50
148
|
.tdoc-nav-item:hover {
|
|
51
|
-
text-
|
|
149
|
+
color: var(--text-color);
|
|
150
|
+
background: var(--bg-hover);
|
|
151
|
+
text-decoration: none;
|
|
52
152
|
}
|
|
53
153
|
|
|
54
154
|
.tdoc-nav-item.tdoc-active {
|
|
55
|
-
|
|
56
|
-
|
|
155
|
+
color: var(--accent-color);
|
|
156
|
+
background: var(--accent-glow);
|
|
157
|
+
font-weight: 500;
|
|
57
158
|
}
|
|
58
159
|
|
|
59
|
-
.tdoc-nav-item.tdoc-
|
|
60
|
-
|
|
160
|
+
.tdoc-nav-item.tdoc-active::before {
|
|
161
|
+
content: '';
|
|
162
|
+
position: absolute;
|
|
163
|
+
left: 0;
|
|
164
|
+
top: 50%;
|
|
165
|
+
transform: translateY(-50%);
|
|
166
|
+
width: 3px;
|
|
167
|
+
height: 60%;
|
|
168
|
+
background: var(--accent-color);
|
|
169
|
+
border-radius: 0 2px 2px 0;
|
|
170
|
+
box-shadow: 0 0 8px var(--accent-color);
|
|
61
171
|
}
|
|
62
172
|
|
|
173
|
+
/* ── Content Area ── */
|
|
63
174
|
.tdoc-content {
|
|
64
175
|
flex: 1;
|
|
65
|
-
padding:
|
|
66
|
-
max-width:
|
|
176
|
+
padding: 3rem 4rem;
|
|
177
|
+
max-width: 820px;
|
|
178
|
+
animation: contentFade 0.2s ease;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@keyframes contentFade {
|
|
182
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
183
|
+
to { opacity: 1; transform: translateY(0); }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* ── Markdown Typography ── */
|
|
187
|
+
.tdoc-content h1 {
|
|
188
|
+
font-family: 'Poppins', sans-serif;
|
|
189
|
+
font-weight: 400;
|
|
190
|
+
font-size: 2.2rem;
|
|
191
|
+
line-height: 1.2;
|
|
192
|
+
color: var(--text-color);
|
|
193
|
+
margin: 0 0 1rem 0;
|
|
194
|
+
letter-spacing: -0.02em;
|
|
195
|
+
border-bottom: 1px solid var(--border-color);
|
|
196
|
+
padding-bottom: 0.75rem;
|
|
67
197
|
}
|
|
68
198
|
|
|
199
|
+
.tdoc-content h2 {
|
|
200
|
+
font-family: 'Poppins', sans-serif;
|
|
201
|
+
font-weight: 600;
|
|
202
|
+
font-size: 1.35rem;
|
|
203
|
+
color: var(--text-color);
|
|
204
|
+
margin: 2.5rem 0 0.75rem;
|
|
205
|
+
letter-spacing: -0.01em;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.tdoc-content h3 {
|
|
209
|
+
font-weight: 600;
|
|
210
|
+
font-size: 1.1rem;
|
|
211
|
+
color: var(--text-color);
|
|
212
|
+
margin: 2rem 0 0.5rem;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.tdoc-content p {
|
|
216
|
+
color: #c0c0d0;
|
|
217
|
+
margin: 0 0 1.2rem;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.tdoc-content a {
|
|
221
|
+
color: var(--accent-color);
|
|
222
|
+
text-decoration: none;
|
|
223
|
+
border-bottom: 1px solid var(--accent-dim);
|
|
224
|
+
transition: border-color 0.15s, color 0.15s;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.tdoc-content a:hover {
|
|
228
|
+
color: #a090ff;
|
|
229
|
+
border-bottom-color: #a090ff;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.tdoc-content ol,
|
|
233
|
+
.tdoc-content ul {
|
|
234
|
+
padding-left: 1.5rem;
|
|
235
|
+
color: #c0c0d0;
|
|
236
|
+
margin: 0 0 1.2rem;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.tdoc-content li {
|
|
240
|
+
margin-bottom: 0.4rem;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.tdoc-content code {
|
|
244
|
+
font-family: 'Geist Mono', monospace;
|
|
245
|
+
font-size: 0.83em;
|
|
246
|
+
background: var(--code-bg);
|
|
247
|
+
color: #b4a8ff;
|
|
248
|
+
padding: 0.15em 0.45em;
|
|
249
|
+
border-radius: 4px;
|
|
250
|
+
border: 1px solid rgba(124, 106, 247, 0.2);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.tdoc-content pre {
|
|
254
|
+
background: var(--code-bg);
|
|
255
|
+
border: 1px solid var(--border-color);
|
|
256
|
+
border-radius: var(--radius);
|
|
257
|
+
padding: 1.25rem 1.5rem;
|
|
258
|
+
overflow-x: auto;
|
|
259
|
+
margin: 1.5rem 0;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.tdoc-content pre code {
|
|
263
|
+
background: none;
|
|
264
|
+
border: none;
|
|
265
|
+
padding: 0;
|
|
266
|
+
font-size: 0.88rem;
|
|
267
|
+
color: #d0d0e8;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.tdoc-content blockquote {
|
|
271
|
+
border-left: 3px solid var(--accent-color);
|
|
272
|
+
background: var(--accent-glow);
|
|
273
|
+
margin: 1.5rem 0;
|
|
274
|
+
padding: 0.75rem 1.25rem;
|
|
275
|
+
border-radius: 0 var(--radius) var(--radius) 0;
|
|
276
|
+
color: #b0b0cc;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.tdoc-content table {
|
|
280
|
+
width: 100%;
|
|
281
|
+
border-collapse: collapse;
|
|
282
|
+
margin: 1.5rem 0;
|
|
283
|
+
font-size: 0.9rem;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.tdoc-content th {
|
|
287
|
+
text-align: left;
|
|
288
|
+
padding: 0.6rem 1rem;
|
|
289
|
+
background: var(--bg-elevated);
|
|
290
|
+
color: var(--text-muted);
|
|
291
|
+
font-weight: 600;
|
|
292
|
+
font-size: 0.8rem;
|
|
293
|
+
text-transform: uppercase;
|
|
294
|
+
letter-spacing: 0.06em;
|
|
295
|
+
border-bottom: 1px solid var(--border-color);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.tdoc-content td {
|
|
299
|
+
padding: 0.6rem 1rem;
|
|
300
|
+
border-bottom: 1px solid var(--border-color);
|
|
301
|
+
color: #c0c0d0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.tdoc-content tr:last-child td {
|
|
305
|
+
border-bottom: none;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* ── Alert / Warning Box ── */
|
|
309
|
+
.text-red {
|
|
310
|
+
color: #ff6b6b;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.alert-box {
|
|
314
|
+
border: 1px solid rgba(255, 107, 107, 0.35);
|
|
315
|
+
background: rgba(255, 107, 107, 0.07);
|
|
316
|
+
padding: 0.9rem 1.25rem;
|
|
317
|
+
margin: 1.5rem 0;
|
|
318
|
+
border-radius: var(--radius);
|
|
319
|
+
font-size: 0.9rem;
|
|
320
|
+
font-family: 'Poppins', sans-serif;
|
|
321
|
+
font-weight: 500;
|
|
322
|
+
letter-spacing: 0;
|
|
323
|
+
display: flex;
|
|
324
|
+
align-items: center;
|
|
325
|
+
gap: 0.6rem;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.alert-box::before {
|
|
329
|
+
content: '⚠';
|
|
330
|
+
font-size: 1rem;
|
|
331
|
+
color: #ff6b6b;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/* ── Footer ── */
|
|
69
335
|
.tdoc-footer {
|
|
70
336
|
padding: 1rem 2rem;
|
|
71
337
|
text-align: center;
|
|
72
|
-
border-top: 1px solid
|
|
73
|
-
font-size: 0.
|
|
74
|
-
|
|
338
|
+
border-top: 1px solid var(--border-color);
|
|
339
|
+
font-size: 0.8rem;
|
|
340
|
+
background: var(--header-bg);
|
|
75
341
|
}
|
|
76
342
|
|
|
77
343
|
.tdoc-footer-text {
|
|
78
344
|
margin: 0;
|
|
79
|
-
|
|
345
|
+
color: var(--text-subtle);
|
|
346
|
+
letter-spacing: 0.03em;
|
|
347
|
+
}
|